Refund a transaction
https://userapi.sepay.vn/v2/transactions/{transaction_id}/refundUse this when money arrived with no order behind it, for example a transfer straight into the real account or into a registered static VA.
Get transaction ids from List transactions.
Refunds currently apply to VietinBank enterprise accounts. An account at another bank returns 422 unsupported_bank; an account that has not been enabled returns 422 not_available. The Sandbox does not apply this gate, so a refund that works there can still return 422 not_available in production.
Without the header SePay returns 422 idempotency_key_required. Replaying the same key returns the existing record instead of moving money a second time.
How it runs
Steps 1, 6 and 10 on your side are the same as the order route: see Idempotency and reconciliation.
Step 3 also settles which bank handles it, since the bank comes from the account that received the payment. When the payment belongs to a VA order, that order is still recorded and the budget is shared with the order route.
Path parameters
Collection transaction id, from List transactions
Headers
A dedup key you generate, unique per refund request, at most 100 characters. Replaying the same key returns the existing record instead of moving money twice. A longer key answers 422 validation_error with the error on idempotency_key.
Request body
Amount to refund (VND, positive integer). Omit it to refund the whole remaining amount of the original payment.
When the payment belongs to a VA order, that order is still recorded as the refund's subject and the budget is shared with Refund an order. Using the other route cannot pay the money out twice.
Code Examples
curl --request POST \--url https://userapi.sepay.vn/v2/transactions/6398452/refund \--header 'Authorization: Bearer REPLACE_BEARER_TOKEN' \--header 'X-Idempotency-Key: refund-order-DH20250001-01' \--header 'content-type: application/json' \--data '{"refund_amount":50000}'
Response (HTTP 200)
{
"status": "success",
"data": {
"refund_id": "RF-7QK3-M8PZ-4VNW",
"order_type": "va_order",
"order_id": "string",
"order_code": "string",
"xid": "string",
"transaction_id": "string",
"original_reference": "string",
"amount": 50000,
"currency": "VND",
"scope": "full",
"status": "pending",
"created_at": "2026-08-28 14:05:00"
}
}Errors
| HTTP | error_code | Description |
|---|---|---|
| 404 | transaction_not_found | Transaction not found, or not owned by the authenticated company |
| 409 | idempotency_key_reused | This X-Idempotency-Key was already used for a different refund request. Use a new key. |
| 422 | idempotency_key_required | The X-Idempotency-Key header is missing, or the key is longer than 100 characters |
| 422 | not_available | SePay has not opened refunds on this account. Contact SePay. |
| 422 | unsupported_bank | This account's bank does not support refunds |
| 422 | unsupported_currency | The bank cannot refund the original payment's currency |
| 422 | not_refundable | This payment cannot be refunded |
| 422 | no_original_transaction | The original collection payment was not found |
| 422 | already_refunded | The original payment is already fully refunded |
| 422 | unsupported_amount_precision | The original amount cannot be represented in its currency |
| 422 | validation_error | refund_amount is invalid, or above the remaining amount |
| 422 | refund_declined | The bank declined the refund |
| 422 | refund_duplicate_reference | The refund reference already exists at the bank |
| 422 | refund_amount_invalid | The amount is not valid for the original payment |
| 422 | refund_failed | The bank accepted the request but could not complete it |
| 422 | refund_rejected | The bank did not accept the refund |
| 500 | unexpected_error | A fault on SePay's side, not in your request. The refund may already have reached the bank, so look it up via List refunds or resend the same key, never a new one. |
| 503 | refund_busy | Another refund for the same original payment is in progress. No record was created; retry in a few seconds with the same key. |
| 503 | vietinbank_map_connection_error | SePay could not reach VietinBank. The refund record exists and is pending; SePay reconciles it on its own. Resend the same key to get that record back, never a new one. |