Skip to main content

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_key is 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

  1. The customer selects QRIS as their payment method at checkout.
  2. A QR code is displayed on the merchant's checkout page.
  3. The customer opens their preferred bank app or e-wallet (GoPay, OVO, DANA, ShopeePay, or any QRIS-participating app) and scans the QR code.
  4. The customer reviews the payment amount and confirms the transaction in their app.
  5. The merchant receives a success notification after confirmation.

Mobile flow

  1. The customer selects QRIS as their payment method at checkout.
  2. A QR code is displayed on screen. The customer downloads or takes a screenshot of the QR code.
  3. 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.
  4. The customer reviews the payment amount and confirms the transaction in their app.
  5. The merchant receives a success notification after confirmation.
Mobile UX

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/direct endpoint 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.

  1. 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
  2. Create a QRIS payment

    To create a QRIS payment, define the parameters in your request.


    Defining API parameters

    You must provide required parameters for payment requests. These parameters ensure successful completion of transactions.

    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 currency
    • payment.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 the
    API Reference Guide chevron_right

    The following tables outline the key parameters specific to QRIS.

    Basic parameters

    ParameterRequirementDescription
    integration_keyRequiredYour EBANX integration key
    operationRequiredSet to request
    payment_type_codeRequiredSet to qris
    countryRequiredSet to id for Indonesia

    Customer data

    ParameterRequirementDescription
    nameRequiredCustomer name
    emailRequiredCustomer email
    phone_numberOptionalCustomer phone number

    Charge parameters

    ParameterRequirementDescription
    merchant_payment_codeRequiredUnique merchant payment code
    currency_codeRequiredSupported value: IDR
    amount_totalRequiredTotal amount to be charged
    redirect_urlOptionalMerchant URL to redirect the customer after payment
    Transaction limits

    QRIS 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 amounts

    When 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.

  3. 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_value contains 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_date indicates 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 behavior

    When testing in sandbox, a simulator environment will be rendered, allowing you to accept or decline the payment without communicating directly with the QRIS network.

  4. Monitor payment for status changes

    Notifications

    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).

  5. Congratulations!

    You have successfully integrated QRIS.

    For more information, refer to the
    Direct 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-WalletFull RefundPartial RefundPartial Refund Count
DANAYesYesMultiple
ShopeePayYesYesMultiple
PermataYesYesMultiple
BTPNYesYesMultiple
BSIYesYesMultiple
CIMBYesYes1x only
BLUYesYesMultiple
JagobankYesYesMultiple
BNCYesYesMultiple
LinkAJAYesYesMultiple
BRIYesYesMultiple
Bank DanamonYesNo
Bank BCAYesNo
Bank MaybankYesNo
Bank SinarmasYesNo
OVOYesNo
GoPayYesNo
Bank JabarYesNo
Bank BPD JatimYesNo
JeniusYesNo
KasproYesNo
BimasaktiYesNo
BPD D.I YogyakartaYesNo
UOBYesNo
AstrapayYesNo
Bank Digital BCAYesNo
Bank BCA SyariahYesNo
Bank PapuaYesNo
Bank Neo CommerceYesNo
Bank JatengYesNo
VirgoYesNo
SeabankYesNo
Mandiri TaspenYesNo
Bank BPD BengkuluYesNo
Bank SulutGoYesNo
Krom BankYesNo
SuperbankYesNo
Showing 37 of 37 rows
Partial refund notes
  • 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.

Still need help?

Help Image

We hope this article was helpful. If you still have questions, you can explore the following options: