QRIS, virtual accounts, e-wallets and Bank Indonesia's SNAP standard, explained for the developer wiring them into an app. Every rule and date here was checked against Bank Indonesia, ASPI and the gateways' own documentation.
By Matthews WongResearched on
Key takeaway
Credit cards reached 1.6 percent of Indonesian adults in the World Bank's 2021 data, so apps built for Indonesia lead with QRIS, virtual accounts and e-wallets, through a licensed gateway or bank APIs on Bank Indonesia's SNAP standard. Confirm payment only from a verified webhook, store rupiah as integers, and note the QRIS MDR change of 1 October 2026.
QRIS is Bank Indonesia's national QR standard, launched on 17 August 2019 and mandatory for every payment QR code from 31 December 2019. One code can be paid from any bank or e-wallet app registered as an issuer, funded from deposits, debit or credit cards, credit facilities or e-money, up to Rp10,000,000 per transaction. In merchant-presented mode the customer scans: a static code is printed once and the customer types the amount, while a dynamic code is generated after the merchant sets the amount. Software wants the dynamic kind, because each code carries one order's value.
Virtual accounts are the other workhorse: the customer transfers to a number issued for that payment, by mobile banking, internet banking or ATM. E-wallets such as GoPay, OVO, DANA and ShopeePay are approved inside the wallet app after a redirect or deeplink. Cards are a minority rail. The World Bank's data put credit card ownership at 1.6 percent of Indonesian adults in 2021, and even the domestic Indonesia Credit Card that BI and ASPI launched on 17 August 2026 is spent through QRIS, by scan or tap.
SNAP, the Standar Nasional Open API Pembayaran, comes from PADG 23/15/PADG/2021, issued on 16 August 2021. It covers interoperability, information security, governance and risk management for payment APIs, with specifications for registration, balance information, transaction history, credit transfer and debit transfer. Providers had to move existing APIs onto SNAP by 30 June or 31 December 2022, depending on whether they helped draft it, and integrate their service users by 30 June 2024, with micro, small and medium businesses and non-profits by 30 June 2025. ASPI has managed the standard and its Developer Site since 1 September 2023.
In code, SNAP is recognisable. ASPI's virtual-account specification groups services under a versioned transfer-va path (create-va, inquiry, payment, status), carries headers such as X-TIMESTAMP, X-SIGNATURE, X-PARTNER-ID, X-EXTERNAL-ID and CHANNEL-ID, and builds each seven-digit response code from the HTTP status, a service code and a case code, so 2002400 is a successful VA inquiry. DOKU's documentation shows the signing step: an HMAC-SHA512, keyed with the client secret, over the method, path, access token, a SHA-256 of the minified body and the timestamp. You write this yourself only when integrating a bank's SNAP API or a gateway's SNAP endpoints.
BI requires every payment provider and switching institution that processes QRIS to hold its approval first, so a merchant app reaches the network through a licensed acquirer or gateway rather than joining it. Xendit, Midtrans and DOKU each put QRIS, virtual accounts, e-wallets and cards behind one API and one notification endpoint. Integrating banks directly over SNAP suits a business that already banks with them, at the price of a separate integration, credential set and test cycle per bank.
QRIS pricing is regulated. BI's rules say the merchant discount rate (MDR) is borne by the merchant and may not be charged to the customer. Under the table in force from March 2025, micro merchants pay 0% up to Rp500,000 and 0.3% above, other regular merchants 0.7%, education 0.6% and fuel stations 0.4%. From 1 October 2026, BI extended 0% to small, medium and large merchants for transactions up to Rp100,000. BI's QRIS page still showed a flat 0.7% for those merchants on 12 October 2026, so keep merchant category and thresholds in configuration, not code. Gateway fees for each method are on the fee comparison page.
Payment is confirmed asynchronously, and every gateway documents duplicate notifications. Midtrans signs each one as SHA512 of order_id, status_code, gross_amount and the server key, retries failed deliveries up to five times across roughly 2 to 210 minutes, and warns that a settlement can arrive before its pending notification. Xendit authenticates with an x-callback-token header, retries up to six times with exponential backoff and guarantees no order. The common rule: verify the sender, return 2xx quickly, and make processing idempotent on the provider's payment or order ID.
Reconciliation is a separate job, because money lands after the webhook. Xendit lists QRIS settlement at T+1 business days and notes that QRIS refunds depend on the issuer: GoPay accepts only full refunds. Customers can generally dispute a QRIS payment through their issuer within 90 days. Store the provider reference on the invoice row so each settlement line can be matched.
QRIS and virtual accounts are push payments: the customer starts every transfer, and Xendit marks neither as supporting merchant-initiated transactions. Scheduled charges need something tokenised. Cards qualify, as do linked e-wallets: Xendit lists saved, merchant-initiated payments for OVO, DANA, ShopeePay and a GoPay recurring channel that needs extra activation. Midtrans's Subscription API accepts only credit_card and gopay, in IDR, and by default retries a failed charge three times, an hour apart. DOKU documents a recurring direct-debit scheme for BRI.
Everyone else renews by invoice: a fresh QRIS code or virtual account each cycle, sent before the period ends, with the webhook extending access. Model past-due and grace states explicitly, because the usual failure is a customer who has not paid yet, not a decline you can retry.
Providers disagree on how an amount looks on the wire. Midtrans types gross_amount as an integer in its request schema but returns it as a two-decimal string such as 275000.00. Xendit publishes per-channel ranges, from Rp1 to Rp10,000,000 for QRIS. Store rupiah as integers, parse every provider string explicitly at the boundary, and keep the gross amount, the fee and the settled amount in separate fields, because the settled sum will not equal the invoice total.
| Method | How the customer pays | What your backend handles | Charge without the customer? | Limits and settlement (Xendit's published figures) |
|---|---|---|---|---|
| QRIS (dynamic, merchant-presented) | Scans the code with any bank or e-wallet app registered as a QRIS issuer | Request a QR from the gateway, render it, confirm payment by webhook | No. The customer approves every payment | Bank Indonesia cap of Rp10,000,000 per transaction; settles T+1 business days |
| Virtual account (bank transfer) | Transfers to an issued account number by mobile banking, internet banking or ATM | Create the VA number and wait for the payment notification; SNAP defines the bank-side VA APIs | No. A VA number can be reusable, but the customer still sends each transfer | BCA VA: Rp10,000 to Rp50,000,000; settles T+1 business days |
| E-wallet (GoPay, OVO, DANA, ShopeePay) | Approves in the wallet app after a redirect or deeplink; OVO also by push notification | Create a payment request and redirect, or link the account once and keep a token | Yes, after account linking; GoPay's recurring channel needs extra activation | Up to Rp20,000,000 (OVO, DANA, ShopeePay) or Rp50,000,000 (GoPay recurring); T+1 to T+2 days |
| Card (credit or debit) | Enters card details and completes the issuer's authentication | Tokenise the card on the first payment, then charge the saved token | Yes, once the card is tokenised | Rp5,000 to Rp200,000,000; settles T+2 business days |
| Direct debit (linked bank account) | Links a debit card or account once, then confirms payments with OTP or PIN | Bind the account, store the token, charge through the provider | Only on a recurring scheme: DOKU lists BRI; its other banks ask for OTP or PIN each time | Not listed by Xendit for Indonesia; DOKU documents Allo Bank, BRI and CIMB |
| Retail outlet (Alfamart, Indomaret) | Pays cash at the counter with a payment code | Generate the code and wait for the payment notification | No | Alfamart: Rp10,000 to Rp5,000,000; code valid 48 hours; settles T+5 business days |
The dated changes a developer had to act on, oldest first, each linked to its official source.
Every payment QR code had to follow QRIS from 31 December 2019, so one code is payable from any registered issuer's app.
Source:Bank Indonesia: Quick Response Code Indonesian Standard (QRIS)Payment providers had to move existing APIs onto SNAP by 30 June or 31 December 2022 and integrate their service users by 30 June 2024, so bank payment APIs now share one signing and response-code contract.
Source:Bank Indonesia: PADG 23/15/PADG/2021 on the national payment Open API standardReal-time interbank credit transfers run 24/7, starting with individual transfers, which matters for refunds and payouts that leave by bank transfer.
Source:Bank Indonesia: BI Launches Bank Indonesia Fast Payment (23/334/DKom)Customers of participating institutions can pay by scanning QRIS or DuitNow QR codes in either country.
Source:Bank Negara Malaysia: Commercial launch of the Indonesia-Malaysia cross-border QR payment linkageASPI now runs the SNAP Developer Site, verification and updates to the standard, so the current specification documents are published there rather than on bi.go.id.
Source:Bank Indonesia: Mulai 1 September 2023 Pengelolaan SNAP Dilakukan oleh ASPI (25/240/DKom)Customers of participating institutions scan QRIS or NETS QR codes with their existing mobile banking apps in either country.
Source:Bank Indonesia: Launch of Cross-border QR Payments Linkage between Indonesia and Singapore (25/310/DKom)BI set this date for launching QRIS Tap, NFC payment without scanning, and for moving BLU and PSO merchants' QRIS pricing from 0.4% to 0%.
Source:Bank Indonesia: Siaran Pers Hasil RDG Februari 2025 (27/36/DKom)A domestically processed credit card, issued by eight providers at launch, is spent through QRIS by scan or tap, so it reaches merchants through their existing QRIS acceptance.
Source:Bank Indonesia: Indonesia Credit Card and 0% MDR Policy (28/159/DKom)Small, medium and large merchants pay 0% on QRIS transactions up to Rp100,000, down from 0.7%, while micro merchants keep 0% up to Rp500,000. Expected-fee checks in reconciliation need the new threshold.
Source:Bank Indonesia: Indonesia Credit Card and 0% MDR Policy (28/159/DKom)Each one is a hands-on write-up of a problem I worked through. Start with the one that matches where you are.
Short answers, consistent with the sources on this page as of the research date.
Primary sources checked on the research date. Follow them for the current version.
The other hubs, the reference pages and the calculators in this section.