QRIS
QRIS (Quick Response Code Indonesian Standard) is Indonesia's national unified QR code payment standard, mandated by Bank Indonesia. It enables customers to pay merchants using any participating Indonesian bank or e-wallet app — including GoPay, OVO, DANA, ShopeePay, and LinkAja — by scanning a single standardized QR code. QRIS payments are real-time, irrevocable, and widely adopted across Indonesia, with over 50 million merchants registered on the network.
By integrating QRIS, merchants can accept payments from the widest range of Indonesian digital payment users through a single payment method, simplifying checkout and maximizing payment coverage across the Indonesian market.
This guide outlines the key concepts and implementation details required to integrate QRIS via API. It covers essential steps such as creating a payment request, rendering the QR code, and monitoring payment status.
Requirements
- API authentication - All API requests must be authenticated using JWS (JSON Web Signature). The legacy
integration_keyis being deprecated — if you still use it, follow the Migration Guide to transition to JWS. If you don't have credentials yet, complete the Merchant Signup Form. - Familiarity with EBANX Direct - This setup follows the same general structure as other payment methods, with a few unique parameters. See EBANX Direct for more info.
- Local tax ID (NPWP) - QRIS is currently only supported for merchants registered with a local Indonesian tax ID (NPWP — Nomor Pokok Wajib Pajak). This is a Bank Indonesia regulatory requirement: all QRIS merchant accounts must be registered under a legal Indonesian business entity. Merchants without a local tax ID or legal presence in Indonesia are not eligible to accept QRIS payments. Contact your EBANX account manager to discuss alternative onboarding options.
How it works
Web flow
- The customer selects QRIS as their payment method at checkout.
- A QR code is displayed on the merchant's checkout page.
- The customer opens their preferred bank app or e-wallet (GoPay, OVO, DANA, ShopeePay, or any QRIS-participating app) and scans the QR code.
- The customer reviews the payment amount and confirms the transaction in their app.
- The merchant receives a success notification after confirmation.
Mobile flow
- The customer selects QRIS as their payment method at checkout.
- A QR code is displayed on screen. The customer downloads or takes a screenshot of the QR code.
- The customer opens their preferred bank app or e-wallet and uses the QR upload or gallery scan feature to load the downloaded QR image.
- The customer reviews the payment amount and confirms the transaction in their app.
- The merchant receives a success notification after confirmation.
Unlike payment methods that use deep links, QRIS on mobile requires the customer to download and upload the QR image manually — there is no automatic app redirect. Display a clear "Download QR" button and instructions for how to upload it in the preferred app.
Payment confirmation
Once the transaction is successful, the customer receives a confirmation in their bank app or e-wallet, and the merchant is updated with the transaction status. EBANX sends a notification confirming the successful transaction, allowing you to fulfill your customer's order.
Technical flow
-
Request payment - Call the
ws/directendpoint with the parameters defined below. -
Payment instructions - In response, EBANX returns a QR code image (base64-encoded) that the merchant must render on the checkout page.
-
Customer completes the payment - The customer has 10 minutes to scan and complete the payment. During this time, the transaction status is pending (PE).
-
Payment confirmation - Once the customer completes the transaction, EBANX changes the status to confirmed (CO). If the QR code expires without payment, the status changes to canceled (CA).
-
EBANX notification - EBANX sends you a webhook notification confirming the status change, allowing you to fulfill your customer's order.
Instructions
Follow the steps below.
- Select your environment
Select the appropriate environment for your integration. Use the sandbox environment for testing, or the production environment for live transactions. Use the URL for your HTTP requests based on your selection.
https://sandbox.ebanx.com/ws/direct - Create a QRIS payment
To create a QRIS payment, define the parameters in your request.
You must provide required parameters for payment requests. These parameters ensure successful completion of transactions.Defining API parameters
Essential parameters
payment.payment_type_code- Specifies the payment method to be used for the transaction.payment.currency_code- Three-letter code of the payment currencypayment.amount_total- Total amount to be charged.
Additional parameters
- EBANX Integration Key - Used to authenticate and authorize API requests.
- Customer Information
- Includes details such as the customer name, email, address and document number (Depends on the requirements of the payment method or local regulations).
- While not mandatory for all countries or payment methods, providing this information can enhance security and increase the likelihood of successful processing.
- Additional Context - Extra data for specific methods or countries.
To learn more about API parameters, please refer to theAPI Reference Guide chevron_rightThe following tables outline the key parameters specific to QRIS.
Basic parameters
Parameter Requirement Description integration_keyRequired Your EBANX integration key operationRequired Set to requestpayment_type_codeRequired Set to qriscountryRequired Set to idfor IndonesiaCustomer data
Parameter Requirement Description nameRequired Customer name emailRequired Customer email phone_numberOptional Customer phone number Charge parameters
Parameter Requirement Description merchant_payment_codeRequired Unique merchant payment code currency_codeRequired Supported value: IDRamount_totalRequired Total amount to be charged redirect_urlOptional Merchant URL to redirect the customer after payment Transaction limitsQRIS has a minimum amount of IDR 1 and a maximum of IDR 10,000,000 (ten million Rupiah) per transaction, as set by Bank Indonesia.
Best practice for amountsWhen possible, send integer (whole number) amounts for QRIS. Some issuers and e-wallets may not accept decimal values — amounts with decimal points could be rejected at the issuer level.
- Send payment request
Send the following request to initiate a QRIS payment.
curl -X POST 'https://sandbox.ebanx.com/ws/direct' \
-H 'Content-Type: application/json' \
-d '{
"integration_key": "{{integration_key}}",
"operation": "request",
"payment": {
"name": "John Doe",
"email": "john.doe@example.com",
"country": "id",
"payment_type_code": "qris",
"merchant_payment_code": "{{unique_merchant_code}}",
"currency_code": "IDR",
"amount_total": 100,
"redirect_url": "https://merchant.example.com/callback"
}
}'A successful request returns a response similar to the example below.
{
"status": "SUCCESS",
"payment": {
"hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
"country": "id",
"merchant_payment_code": "{{unique_merchant_code}}",
"order_number": null,
"status": "PE",
"status_date": "{{YYYY-MM-DD HH:mm:ss}}",
"open_date": "{{YYYY-MM-DD HH:mm:ss}}",
"confirm_date": null,
"transfer_date": null,
"amount_br": "100.00",
"amount_ext": "100.00",
"amount_iof": "1",
"currency_rate": "1",
"currency_ext": "IDR",
"due_date": "{{YYYY-MM-DD HH:mm:ss}}",
"instalments": "1",
"payment_type_code": "qris",
"pre_approved": false,
"capture_available": null,
"qris": {
"qr_code_value": "{{qr_code_value}}",
"expiration_date": "{{YYYY-MM-DD HH:mm:ss}}"
}
}
}The
qr_code_valuecontains a base64-encoded QR code image. Render this on the checkout page for the customer to scan on desktop, or provide a download option on mobile.The
expiration_dateindicates when the QR code expires. Display a countdown timer on your checkout page so customers know how long they have to complete the payment. The timeout for QRIS is 10 minutes.Sandbox behaviorWhen testing in sandbox, a simulator environment will be rendered, allowing you to accept or decline the payment without communicating directly with the QRIS network.
- Monitor payment for status changes
Notifications
-
EBANX will send a notification whenever a payment status changes.
-
Make sure your system is set up to receive notifications from EBANX for any changes in payment status.
Status
-
After receiving a notification that the status has changed, retrieve the payment status.
-
When a payment is confirmed, the status will change from pending (PE) to confirmed (CO). If the customer does not complete the payment before the QR code expires, the status will change to canceled (CA).
-
- Congratulations!
You have successfully integrated QRIS.
For more information, refer to theDirect API reference guidechevron_right
Refunds
Refunds for QRIS payments are supported but limited to specific issuers and e-wallets. Not all participants in the QRIS network support refunds — capability depends on the issuer the customer used to make the payment.
A refund can only be processed when the payment is in confirmed (CO) status. Payments in pending (PE) status cannot be refunded — use the ws/cancel endpoint for pending payments instead.
To initiate a refund, call the ws/refund endpoint with the original payment hash, the amount to refund, a description, and a unique merchant_refund_code.
Refund capability by issuer
The table below shows which issuers support full and/or partial refunds. Use the filters to find a specific issuer. Issuers not listed do not support refunds at this time.
| Issuer / E-Wallet | Full Refund | Partial Refund | Partial Refund Count |
|---|---|---|---|
| DANA | Yes | Yes | Multiple |
| ShopeePay | Yes | Yes | Multiple |
| Permata | Yes | Yes | Multiple |
| BTPN | Yes | Yes | Multiple |
| BSI | Yes | Yes | Multiple |
| CIMB | Yes | Yes | 1x only |
| BLU | Yes | Yes | Multiple |
| Jagobank | Yes | Yes | Multiple |
| BNC | Yes | Yes | Multiple |
| LinkAJA | Yes | Yes | Multiple |
| BRI | Yes | Yes | Multiple |
| Bank Danamon | Yes | No | — |
| Bank BCA | Yes | No | — |
| Bank Maybank | Yes | No | — |
| Bank Sinarmas | Yes | No | — |
| OVO | Yes | No | — |
| GoPay | Yes | No | — |
| Bank Jabar | Yes | No | — |
| Bank BPD Jatim | Yes | No | — |
| Jenius | Yes | No | — |
| Kaspro | Yes | No | — |
| Bimasakti | Yes | No | — |
| BPD D.I Yogyakarta | Yes | No | — |
| UOB | Yes | No | — |
| Astrapay | Yes | No | — |
| Bank Digital BCA | Yes | No | — |
| Bank BCA Syariah | Yes | No | — |
| Bank Papua | Yes | No | — |
| Bank Neo Commerce | Yes | No | — |
| Bank Jateng | Yes | No | — |
| Virgo | Yes | No | — |
| Seabank | Yes | No | — |
| Mandiri Taspen | Yes | No | — |
| Bank BPD Bengkulu | Yes | No | — |
| Bank SulutGo | Yes | No | — |
| Krom Bank | Yes | No | — |
| Superbank | Yes | No | — |
- CIMB only supports a single partial refund per transaction — multiple partial refunds are not permitted.
- For all other issuers supporting partial refunds, multiple partial refund requests can be made against the same transaction as long as the total refunded amount does not exceed the original payment amount.
- Refund availability is subject to change as issuers update their QRIS capabilities. Contact EBANX support for the latest issuer status.
Resources
Use the following resources when testing in your sandbox environment.
API Reference
Click here to access detailed API documentation to integrate efficiently.
Mock Customer Data
Click here to view mock customer data for testing and validating user flows.
Error Codes
Click here to review common error codes to troubleshoot and resolve issues quickly.
Still need help?
We hope this article was helpful. If you still have questions, you can explore the following options:
- Merchant support: Contact our support team at sales.engineering@ebanx.com for assistance.
- Not a partner yet? Please complete the Merchant Signup Form, and our commercial team will reach out to you.