Skip to content
Beta · The spec may still change before general availability. The API domain api.hensa.example is a placeholder. See changes →

Payment requests

Create a dynamic VietQR per order. When the customer pays, Hensa matches it automatically and sends payment_request.paid.

Create a payment request

POST/v1/payment_requests

Requires Idempotency-Key

Creates a dynamic VietQR with its own amount and referenceCode. Render qrPayload as a QR code for the customer – or redirect them to the hosted Hensa Pay page at payUrl. Expires after 15 minutes.

Request body

amountintegerrequired

Amount to collect, integer VND, minimum 1,000.

externalOrderRefstring

Your own order id (max 64 chars). Returned as-is in webhooks.

Returns

201 · PaymentRequest

Possible errors

  • validation_error 400 Invalid request data – see message.
  • idempotency_conflict 409 Same Idempotency-Key with a different body.
  • no_active_bank_account 422 The store has no active bank account.
  • merchant_name_required 422 The store has no name yet – set it in the Dashboard before creating QR codes (live mode only).
  • plan_limit 422 The current plan's limit is reached.
curl -X POST https://api.hensa.example/v1/payment_requests \
-H "Authorization: Bearer $HENSA_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"amount":150000,"externalOrderRef":"DH-1024"}'
Response 201
{
"id": "prq_01JD7Q8M4K2X9V3T6B5N0R1W8Y",
"amount": 150000,
"amountReceived": 0,
"currency": "VND",
"referenceCode": "LK7F3K9",
"status": "pending",
"qrPayload": "00020101021238…",
"receiver": {
"name": "CA PHE MOC",
"bankName": "MB Bank",
"accountMasked": "•••• 6789"
},
"externalOrderRef": "DH-1024",
"payUrl": "https://pay.hensa.vn/r/pt_7Hq2mX9vKd4RtY1nB8cZ0w",
"expiresAt": "2026-11-03T08:15:00Z",
"createdAt": "2026-11-03T08:00:00Z"
}

Retrieve a payment request

GET/v1/payment_requests/{id}

Use it to re-check the status if a webhook has not arrived.

Parameters

idstring · pathrequired

Payment request ID.

Returns

200 · PaymentRequest

Possible errors

  • not_found 404 Not found (or not owned by this key's store).
curl https://api.hensa.example/v1/payment_requests/prq_01JD7Q8M4K2X9V3T6B5N0R1W8Y \
-H "Authorization: Bearer $HENSA_API_KEY"
Response 200
{
"id": "prq_01JD7Q8M4K2X9V3T6B5N0R1W8Y",
"amount": 150000,
"amountReceived": 0,
"currency": "VND",
"referenceCode": "LK7F3K9",
"status": "pending",
"qrPayload": "00020101021238…",
"receiver": {
"name": "CA PHE MOC",
"bankName": "MB Bank",
"accountMasked": "•••• 6789"
},
"externalOrderRef": "DH-1024",
"payUrl": "https://pay.hensa.vn/r/pt_7Hq2mX9vKd4RtY1nB8cZ0w",
"expiresAt": "2026-11-03T08:15:00Z",
"createdAt": "2026-11-03T08:00:00Z"
}

List payment requests

GET/v1/payment_requests

Newest first. Cursor-paginated.

Parameters

statusstring · query

Filter by status.

limitinteger · query

Items per page (1–100, default 25).

cursorstring · query

The nextCursor value from the previous page.

Returns

200 · A page of PaymentRequest plus nextCursor for the next page.

Possible errors

  • validation_error 400 Invalid request data – see message.
curl https://api.hensa.example/v1/payment_requests?limit=25 \
-H "Authorization: Bearer $HENSA_API_KEY"
Response 200
{
"data": [
{
"id": "prq_01JD7Q8M4K2X9V3T6B5N0R1W8Y",
"amount": 150000,
"amountReceived": 0,
"currency": "VND",
"referenceCode": "LK7F3K9",
"status": "pending",
"qrPayload": "00020101021238…",
"receiver": {
"name": "CA PHE MOC",
"bankName": "MB Bank",
"accountMasked": "•••• 6789"
},
"externalOrderRef": "DH-1024",
"payUrl": "https://pay.hensa.vn/r/pt_7Hq2mX9vKd4RtY1nB8cZ0w",
"expiresAt": "2026-11-03T08:15:00Z",
"createdAt": "2026-11-03T08:00:00Z"
}
],
"nextCursor": "…"
}

Objects

PaymentRequest

idstringrequired

Payment request ID.

amountintegerrequired

Amount to collect, integer VND.

amountReceivedintegerrequired

Total of the transfers matched to this request. Less than amount while partially_paid; can exceed it on overpayment.

currency"VND"required

Always VND.

referenceCodestringrequired

Reference the customer puts in the transfer description – used for auto-matching.

statusstringrequired

pending · paid in full · partially_paid underpaid · expired · cancelled.

qrPayloadstringrequired

VietQR (EMVCo) string – render it as a QR code.

receiverobjectrequired

Receiver shown to the customer before paying.

receiver.namestringrequired
receiver.bankNamestringrequired
receiver.accountMaskedstringrequired
externalOrderRefstring | nullrequired

Your own order id (if sent at creation).

payUrlstring | nullrequired

The hosted Hensa Pay page for this request (QR, open-banking-app buttons, receipt). Send it to the payer or redirect them here instead of rendering the QR yourself. The URL carries a secret – share it only with the payer. null once the page is revoked.

expiresAtstringrequired

Expires 15 minutes after creation.

createdAtstringrequired

Creation time.

PaymentRequest · Example
{
"id": "prq_01JD7Q8M4K2X9V3T6B5N0R1W8Y",
"amount": 150000,
"amountReceived": 0,
"currency": "VND",
"referenceCode": "LK7F3K9",
"status": "pending",
"qrPayload": "00020101021238…",
"receiver": {
"name": "CA PHE MOC",
"bankName": "MB Bank",
"accountMasked": "•••• 6789"
},
"externalOrderRef": "DH-1024",
"payUrl": "https://pay.hensa.vn/r/pt_7Hq2mX9vKd4RtY1nB8cZ0w",
"expiresAt": "2026-11-03T08:15:00Z",
"createdAt": "2026-11-03T08:00:00Z"
}