You can refund a QR Code payment that has been successful either in full amount or partial amount. However there are things to note:
If a refund of the full amount is requested within 24 hours of payment completion, the original payment will be VOIDED. The original fee and VAT charged will be fully returned.
If a refund of a partial amount is requested or if a refund of any amount is requested after 24 hours of payment completion, the original payment will be REFUNDED. The original fee and VAT charged will NOT be returned at all.
- This Refund API will only work for successful QR payments.
- This Refund API will return
PENDINGstatus in API response upon execution. A follow-up webhook/callback will be sent to your system's URL when refund has been processed successfully.
The validity period for a refund is 7 days from payment date. After 7 days you cannot request a refund.
Your customer will receive the refund fund instantly after you have successfully get the success callback of the QR Code refund.
However if the customer paid using other than the issuer list below (source: https://docs.xendit.co/docs/qris), you cannot request a refund (example: payment QRIS via Mandiri cannot be refunded using this endpoint):
If you wish to refund QRIS from other issuers, please use our disbursement feature instead.
Here are the steps on how to create QR Code refund:
1. Create secret API Key on your dashboard. Guidance here
2. Set your callback URL in your Xendit dashboard so you will get notified when refund is Successful or Failed.
V1
V2
3. Create Refund QR payment using endpoint:
| Type | End point |
| V1 | POST https://api.xendit.co/qr_codes/payments/:qrpy_id/refunds |
| V2 | POST https://api.xendit.co/refunds (recommend to use this as this is the UPDATED version per 2026) |
4. You'll find response like this in your system or Webhook tab:
V1
{
"id": "qrrf_3a38022e-7f9a-4ef0-a421-e18d9cb877e3",
"qrpy_id": "qrpy_f3cad64b-5392-499f-99e1-7d60cb615527",
"status": "PENDING",
"currency": "IDR",
"payment_amount": 100,
"refund_amount": 100,
"channel_code": "ID_DANA",
"reason": "",
"failure_code": null,
"refunded_at": null,
"created": "2023-04-04T10:41:33.798952Z",
"updated": "2023-04-04T10:41:33.798952Z"
}
V2
{
"created": "2026-08-12T05:24:59.455Z",
"business_id": "5fd8d26ab9e3681b44626adb",
"event": "refund.succeeded",
"data": {
"id": "rfd-1a799807-dd4f-4037-a089-848a0ceff587",
"amount": 1,
"reason": "REQUESTED_BY_CUSTOMER",
"status": "SUCCEEDED",
"actions": null,
"country": "ID",
"created": "2026-08-12T05:24:58.089255Z",
"updated": "2026-08-12T05:24:58.089256Z",
"currency": "IDR",
"metadata": {},
"invoice_id": "",
"payment_id": "qrpy_fa62da5b-ad0e-4046-a69c-ebd5d05ca947",
"channel_code": "XENDIT",
"failure_code": null,
"reference_id": "refundbcav318aug",
"refund_method": "DIRECT",
"refund_fee_amount": null,
"payment_request_id": "pr-d22fea02-7f87-453a-b3dc-7141b1221453",
"payment_method_type": "QR_CODE",
"payout_link_properties": null
},
"api_version": null
}
5. You will then receive a callback of the successful refund where you can check on your callback tab.
6. The refunded transaction will appear in Transactions Tab as "Refund Pending" (if Settlement time hasn't passed) or "Refunded" (if after Settlement time has passed)
Settlement here refers to original payment, meaning:
if transaction paid at 3 Sep, 15:40 then Refund happens at 3 Sep, 16:00 then status will be Refund Pending
original payment has Settlement time 7 Sep, 00:00
so transaction status will be updated to Refunded at 7 Sep ~00:00 -15.40
Despite Refund status is still Pending, End Customer can check their account directly because fund will be processed right after it is requested. Merchant can also check whether Refund is Success or Failed from Webhook tab as well.