GoPay Merchant QRIS data API
GoPay Merchant: QRIS is the shop-side QRIS app from PT. GoTo Gojek Tokopedia Tbk, the Jakarta-based GoTo group formed by Gojek and Tokopedia, for Indonesian merchants that collect payments under Bank Indonesia's national QR standard. A new outlet can print a static QRIS plate the same day, with 0% merchant discount rate on GoPay-funded scans, and staff tap a dynamic-QRIS flow when they want a one-off amount instead of an open plate. Settled funds sit in a GoPay merchant wallet that also tracks a GPTU (GoPay Tabungan untuk Usaha) sub-wallet, with instant bank payouts to BCA, Mandiri, Danamon, BNI, BRI, CIMB Niaga and Bank Jago plus scheduled auto-payouts. Daily sales reports land by email, GoPay Spiker is the optional speaker that calls out each incoming scan, and Pinjam Modal — an OJK-supervised working-capital loan — sits behind a KYC gate for eligible shops. Licensed as a Bank Indonesia payment institution, the app is Indonesia-only, holds a 4.56 rating across 87,875 Google Play ratings and 10 million-plus installs, and competes with GoBiz QRIS, DANA Bisnis, ShopeePay Merchant and LinkAja for the same warungs, kiosks and multi-outlet brands.
NMID-stamped QRIS plates are the root record: each outlet carries nmid with an ASPI EMV payload in aspi_qr_string and a printable aspi_qr_image_url, plus a GoPay deep-link in gopay_qr_string. Dynamic charges mint a time-boxed qr_string for gross_amount with qr_type DYNAMIC and payin.dynamic_qris, then refunds write refund_id against original_transaction_id and leave remaining_gross_amount.
Settled float splits across gopay_balance and gptu_balance; the home card shows spendable effective_balance / resulting_balance and disbursable_amount ready for a manual payout keyed by payout_id onto payout_account, gated by min_payout_amount, is_payout_suspended and gopay_limit. Unified histories page QRIS, refund and payout rows by history_type; the safety meter exposes acc_safety_score next to kyc_status. Finance teams reconciling Indonesian QRIS tills, POS vendors reprinting plates, and lenders underwriting Pinjam Modal-style working capital can wire those fields without re-keying the counter app — openData Studio turns them into callable open data.
Screenshots
API surface
The endpoints and request/response examples below are reconstructed from the app's interface — illustrative, not a live capture.
Merchant wallet balance
GET
/v1/wallets/floatopenbankingReads the signed-in outlet's GoPay merchant wallet and GPTU sub-wallet, including the spendable effective_balance shown on the home balance strip.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-AppId, Gojek-Country-Code, X-User-Locale, X-User-Type, X-Selected-Outlet
- gopay_balance
- gptu_balance
- effective_balance
- show_combined_balance
- show_wallet_balance
- wallet_type
- is_gopay_account_linked
- is_maximum_balance_reached
GET /v1/wallets/float HTTP/1.1 Authorization: Bearer eyJhbGciOi... X-AppVersion: 2.6.0 X-UniqueId: 7c2a9f11-4b8e-4d21 X-AppId: <merchant-app> Gojek-Country-Code: ID X-User-Locale: id_ID X-User-Type: merchant X-Selected-Outlet: OUT-88100214{ "gopay_balance": 18425000, "gptu_balance": 2500000, "effective_balance": 17240000, "show_combined_balance": true, "show_wallet_balance": true, "wallet_type": "GOPAY", "is_gopay_account_linked": true, "is_maximum_balance_reached": false, "currency": "IDR" }Finance home balance
GET
/v1/finance/homeopenfinanceLoads the finance-home card: resulting_balance after holds, disbursable_amount ready to cash out, outstanding_balance still pending, and the last_payout row.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-AppId, Gojek-Country-Code, X-User-Locale, X-Selected-Outlet
- resulting_balance
- disbursable_amount
- outstanding_balance
- last_payout
- payout_id
- mainOutletFlag
- wallet_type
GET /v1/finance/home HTTP/1.1 Authorization: Bearer eyJhbGciOi... X-AppVersion: 2.6.0 X-UniqueId: 7c2a9f11-4b8e-4d21 Gojek-Country-Code: ID X-Selected-Outlet: OUT-88100214{ "resulting_balance": 17240000, "disbursable_amount": 16800000, "outstanding_balance": 440000, "last_payout": { "payout_id": "PO-20261007-4419", "amount": 15120000 }, "mainOutletFlag": true, "wallet_type": "GOPAY" }Multi-wallet finance balance
GET
/v1/finance/walletsopenbankingSplits GoPay and GPTU into separate wallet rows so the finance screen can toggle combined vs per-wallet display.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-AppId, Gojek-Country-Code, X-Selected-Outlet
- wallet_type
- gopay_balance
- gptu_balance
- effective_balance
- gptu_account_no
- gptu_sof_status
- show_combined_balance
- default_selected_wallet
GET /v1/finance/wallets HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID X-Selected-Outlet: OUT-88100214{ "wallets": [ { "wallet_type": "GOPAY", "gopay_balance": 18425000, "effective_balance": 17240000, "show_wallet_balance": true }, { "wallet_type": "GPTU", "gptu_balance": 2500000, "gptu_account_no": "GPTU-998177", "gptu_sof_status": "ACTIVE" } ], "show_combined_balance": true, "default_selected_wallet": "GOPAY" }GoPay wallet limit
GET
/v1/finance/limitsopenfinanceReturns the KYC-gated GoPay float cap and remaining on-demand-payout headroom that block cash-out when the monthly ceiling is hit.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, Gojek-Country-Code, X-Selected-Outlet
- gopay_limit
- odp_remaining_limit
- is_maximum_balance_reached
- monthly_limit_hit
- kyc_status
- is_kyc_approved
GET /v1/finance/limits HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID X-Selected-Outlet: OUT-88100214{ "gopay_limit": 20000000, "odp_remaining_limit": 15750000, "is_maximum_balance_reached": false, "monthly_limit_hit": false, "kyc_status": "APPROVED", "is_kyc_approved": true }Shared QRIS plate
GET
/v1/qris/plateopendataReturns the outlet's static QRIS payload: Bank Indonesia NMID, ASPI EMV string and image URL, plus the GoPay deep-link string used to reprint the plate.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-AppId, Gojek-Country-Code, X-Selected-Outlet
- nmid
- aspi_qr_string
- aspi_qr_image_url
- gopay_qr_string
- qr_string
- aspi_terminal_id
- aspi_onboarding_status
- is_qris_suspended
- outlet_name
- merchant_id
GET /v1/qris/plate HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID X-Selected-Outlet: OUT-88100214{ "nmid": "ID1021234567890", "aspi_qr_string": "0002010102112661ID.CO.QRIS.WWW0118936009141234567890215ID10212345678905204000053033605802ID5914WARUNG MAJU6007JAKARTA6105123406304ABCD", "aspi_qr_image_url": "/v1/media/qris/OUT-88100214.png", "gopay_qr_string": "gopay://merchant/pay?nmid=ID1021234567890", "qr_string": "0002010102112661ID.CO.QRIS.WWW0118936009141234567890215ID10212345678905204000053033605802ID5914WARUNG MAJU6007JAKARTA6105123406304ABCD", "aspi_terminal_id": "A01", "aspi_onboarding_status": "ACTIVE", "is_qris_suspended": false, "outlet_name": "Warung Maju Menteng", "merchant_id": "MCH-88100214" }Charge dynamic QRIS
POST
/v1/chargesopenbankingCreates a one-off dynamic QRIS charge for gross_amount and returns a time-boxed qr_string plus mdr_range used on the amount-input screen.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-Idempotency-Key, X-Request-Id, Gojek-Country-Code, X-Selected-Outlet
- outlet_id
- transaction_id
- gross_amount
- formatted_gross_amount
- qr_string
- qr_type
- expired_at
- mdr_range
- payin.dynamic_qris
POST /v1/charges HTTP/1.1 Authorization: Bearer eyJhbGciOi... X-Idempotency-Key: 9f3c1a22-88b1-4d0e X-Request-Id: 4e11c8aa-21b0 Gojek-Country-Code: ID Content-Type: application/json { "outlet_id": "OUT-88100214", "gross_amount": 75000, "qr_type": "DYNAMIC", "payin": {"dynamic_qris": true} }{ "transaction_id": "TRX-20261008-7721", "gross_amount": 75000, "formatted_gross_amount": "Rp75.000", "qr_string": "0002010102122661ID.CO.QRIS.WWW0118936009141234567890215ID10212345678905204540153033605405750005802ID5914WARUNG MAJU6007JAKARTA6105123406304BEEF", "qr_type": "DYNAMIC", "expired_at": "2026-10-08T10:15:00+07:00", "mdr_range": "0", "payin": {"dynamic_qris": true} }Refund a QRIS charge
POST
/v1/refundsopenbankingPosts a merchant-initiated refund against original_transaction_id and returns remaining_gross_amount plus the estimated settlement timestamp.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-Idempotency-Key, Gojek-Country-Code, X-Selected-Outlet
- refund_id
- original_transaction_id
- gross_amount
- remaining_gross_amount
- refund_process_date_time
- refunded_estimation_date_time
- min_settlement_amount
POST /v1/refunds HTTP/1.1 Authorization: Bearer eyJhbGciOi... X-Idempotency-Key: a1b2c3d4-e5f6 Gojek-Country-Code: ID Content-Type: application/json { "original_transaction_id": "TRX-20261008-7721", "gross_amount": 75000, "outlet_id": "OUT-88100214" }{ "refund_id": "RF-20261008-1192", "original_transaction_id": "TRX-20261008-7721", "gross_amount": 75000, "remaining_gross_amount": 0, "refund_process_date_time": "2026-10-08T10:22:11+07:00", "refunded_estimation_date_time": "2026-10-08T10:30:00+07:00", "min_settlement_amount": 10000 }Manual payout
POST
/v1/payoutsopenbankingStarts an on-demand bank payout of disbursable_amount to payout_account, gated by min_payout_amount, remaining_payout_qty and is_payout_suspended.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-Idempotency-Key, Gojek-Country-Code, X-Selected-Outlet
- payout_id
- payout_account
- wallet_type
- disbursable_amount
- min_payout_amount
- max_settlement_amount
- is_payout_suspended
- remaining_payout_qty
POST /v1/payouts HTTP/1.1 Authorization: Bearer eyJhbGciOi... X-Idempotency-Key: 5c88ee01-aa12 Gojek-Country-Code: ID Content-Type: application/json { "outlet_id": "OUT-88100214", "wallet_type": "GOPAY", "amount": 16800000, "payout_account": "BCA-1234567890" }{ "payout_id": "PO-20261008-8821", "payout_account": "BCA-1234567890", "wallet_type": "GOPAY", "disbursable_amount": 16800000, "min_payout_amount": 10000, "max_settlement_amount": 20000000, "is_payout_suspended": false, "remaining_payout_qty": 2 }Manual payout info
GET
/v1/payouts/previewopenfinancePre-flight for the cash-out form: remaining disbursable_amount, payout_account, available_payout_options and whether payouts are suspended.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, Gojek-Country-Code, X-Selected-Outlet
- disbursable_amount
- min_payout_amount
- max_settlement_amount
- payout_account
- available_payout_options
- is_payout_suspended
- is_payout_amount_reached
- expired_at
GET /v1/payouts/preview?wallet_type=GOPAY HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID X-Selected-Outlet: OUT-88100214{ "disbursable_amount": 16800000, "min_payout_amount": 10000, "max_settlement_amount": 20000000, "payout_account": "BCA-1234567890", "available_payout_options": ["BANK_TRANSFER", "GPTU"], "is_payout_suspended": false, "is_payout_amount_reached": false, "expired_at": "2026-10-08T23:59:59+07:00" }Payout schedules
GET
/v1/payouts/windowsopenfinanceLists auto-payout windows (daily 15:00, weekly, manual-only) and whether payout_schedule_editable lets the merchant change them.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, Gojek-Country-Code, X-Selected-Outlet
- available_schedules
- default_schedules
- current_schedule_time
- daily_schedule_time
- payout_schedule_editable
- payout_account
GET /v1/payouts/windows HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID X-Selected-Outlet: OUT-88100214{ "available_schedules": ["DAILY_15", "WEEKLY_FRI", "MANUAL"], "default_schedules": ["DAILY_15"], "current_schedule_time": "15:00", "daily_schedule_time": "15:00", "payout_schedule_editable": true, "payout_account": "BCA-1234567890" }Unified transaction histories
GET
/v1/activityopenfinancePages the merchant activity feed of QRIS charges, refunds and payouts, filterable by history_type on the Laporan Saya screen.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, Gojek-Country-Code, X-Selected-Outlet
- transaction_id
- history_type
- gross_amount
- formatted_gross_amount
- outlet_id
- outlet_name
- nmid
- wallet_type
- batch_size
GET /v1/activity?history_type=QRIS&limit=20 HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID X-Selected-Outlet: OUT-88100214{ "items": [ { "transaction_id": "TRX-20261008-7721", "history_type": "QRIS", "gross_amount": 75000, "formatted_gross_amount": "Rp75.000", "outlet_id": "OUT-88100214", "outlet_name": "Warung Maju Menteng", "nmid": "ID1021234567890", "wallet_type": "GOPAY" } ], "batch_size": 20 }Transaction report job
POST
/v1/reports/salesopendataQueues the on-demand sales-report export that later lands in the merchant email inbox as a dated transaction workbook.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, X-Request-Id, Gojek-Country-Code, X-Selected-Outlet
- outlet_id
- merchant_id
- job_id
- status
- component_ids
POST /v1/reports/sales HTTP/1.1 Authorization: Bearer eyJhbGciOi... X-Request-Id: 8aa1-21b0 Gojek-Country-Code: ID Content-Type: application/json { "outlet_id": "OUT-88100214", "merchant_id": "MCH-88100214", "start_date": "2026-10-01", "end_date": "2026-10-08" }{ "job_id": "RPT-20261008-331", "outlet_id": "OUT-88100214", "merchant_id": "MCH-88100214", "status": "QUEUED", "component_ids": ["qris", "payout", "refund"] }List merchant outlets
GET
/v1/locationsopendataLists outlets on the signed-in merchant, including address, coordinates, NMID and the mainOutletFlag used by the outlet switcher.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, Gojek-Country-Code, X-User-Type
- outlet_id
- outlet_name
- outlet_address
- outlet_city
- outlet_postal_code
- outlet_latitude
- outlet_longitude
- nmid
- merchant_id
- mainOutletFlag
- is_qris_suspended
GET /v1/locations HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID X-User-Type: merchant{ "outlets": [ { "outlet_id": "OUT-88100214", "outlet_name": "Warung Maju Menteng", "outlet_address": "Jl. Menteng Raya 12", "outlet_city": "Jakarta", "outlet_postal_code": "10310", "outlet_latitude": -6.1944, "outlet_longitude": 106.8294, "nmid": "ID1021234567890", "merchant_id": "MCH-88100214", "mainOutletFlag": true, "is_qris_suspended": false } ] }Account safety meter
GET
/v1/account/safetyosintReads the merchant safety-meter score that gates QRIS and payouts when acc_safety_score drops or KYC is incomplete.
Auth: Bearer access_token from GoTo login; X-AppVersion, X-UniqueId, Gojek-Country-Code
- acc_safety_score
- kyc_status
- is_kyc_approved
- is_qris_suspended
- is_payout_suspended
GET /v1/account/safety HTTP/1.1 Authorization: Bearer eyJhbGciOi... Gojek-Country-Code: ID{ "acc_safety_score": 82, "kyc_status": "APPROVED", "is_kyc_approved": true, "is_qris_suspended": false, "is_payout_suspended": false }Login by OTP
POST
/v1/session/otpopendataExchanges an SMS or WhatsApp OTP for access_token and refresh_token used as Bearer on wallet, QRIS and payout calls.
Auth: Unauthenticated start of merchant login. X-AppVersion, X-UniqueId, X-AppId, Gojek-Country-Code, X-ClientID. Response access_token / refresh_token attach as Bearer on later calls.
- otp_token
- access_token
- refresh_token
- login_access_token
- login_refresh_token
- kyc_status
- merchant_id
POST /v1/session/otp HTTP/1.1 X-AppVersion: 2.6.0 X-UniqueId: 7c2a9f11-4b8e-4d21 X-AppId: <merchant-app> X-ClientID: <merchant-client> Gojek-Country-Code: ID Content-Type: application/json { "phone": "+6281234567890", "otp_token": "482193", "otp_channel": "sms" }{ "access_token": "eyJhbGciOi...", "refresh_token": "rt_9f3c1a22", "login_access_token": "eyJhbGciOi...", "login_refresh_token": "rt_login_9f3c", "kyc_status": "APPROVED", "merchant_id": "MCH-88100214" }
Data categories
- wallet balances
- QRIS plates
- dynamic charges
- refunds
- payouts
- transaction history
- outlets
- account safety
Where teams use this data
Nightly QRIS ledger close
A shop ERP pulls wallet float (gopay_balance, gptu_balance, effective_balance) then pages unified histories by history_type so QRIS gross_amount rows match the day's disbursable_amount before the 15:00 auto-payout.
Reprint NMID plates across outlets
A multi-outlet brand reads nmid, aspi_qr_string and aspi_qr_image_url per outlet_id and regenerates counter stickers whenever aspi_onboarding_status flips or is_qris_suspended trips.
On-demand cash-out bot
Treasury watches disbursable_amount against min_payout_amount and remaining_payout_qty, then posts a manual payout to payout_account when is_payout_suspended is false and odp_remaining_limit still has headroom.
Risk hold on weak safety scores
A compliance job reads acc_safety_score with kyc_status and pauses dynamic charges plus scheduled payouts when is_qris_suspended or is_payout_suspended is raised on the safety meter.
Frequently asked questions
What wallet balances does GoPay Merchant expose?
The wallet call returns gopay_balance and gptu_balance plus spendable effective_balance. The finance-home card adds resulting_balance, disbursable_amount and outstanding_balance, and a multi-wallet split lists wallet_type GOPAY vs GPTU with gptu_account_no.
How is a static QRIS plate represented?
The shared-QRIS call returns Bank Indonesia nmid, the ASPI EMV payload aspi_qr_string, aspi_qr_image_url for reprinting, gopay_qr_string, aspi_terminal_id and is_qris_suspended.
Can I trigger an on-demand bank payout?
Yes. Manual-payout info first returns disbursable_amount, min_payout_amount, payout_account and is_payout_suspended; posting a manual payout then yields payout_id and remaining_payout_qty. Schedules list daily 15:00 and weekly windows via available_schedules.
How does merchant login work?
Login-by-OTP exchanges an SMS or WhatsApp otp_token for access_token and refresh_token. Later calls send Authorization Bearer plus X-AppVersion, X-UniqueId, X-AppId, Gojek-Country-Code, X-User-Locale, X-User-Type and X-Selected-Outlet.
Apps similar to GoPay Merchant: QRIS
- GoBiz — GoTo's broader Indonesian merchant console that also issues QRIS, with catalogue, staff and payout tools beyond the QRIS-only GoPay Merchant app.
- DANA Bisnis — DANA's merchant app for Indonesian shops to accept QRIS, track settlements and cash out to bank accounts.
- ShopeePay Merchant — Shopee's merchant QRIS and ShopeePay acceptance app used by Indonesian kiosks and warungs.
- LinkAja Merchant — State-linked LinkAja's merchant app for QRIS acceptance and payout tracking in Indonesia.
- GoFood Merchant — GoTo's restaurant-side app for GoFood delivery tickets; kitchens often run it beside GoPay Merchant for in-store QRIS.
- Midtrans — GoTo's payment-gateway console (gopaymerchant.midtrans.com) that many online Indonesian merchants use alongside the in-store QRIS app.
Topics
- GoPay Merchant API
- QRIS merchant data
- NMID aspi_qr_string
- GoPay wallet balance
- GPTU merchant payout
- Indonesian QRIS endpoints
- GoPay Merchant QRIS
Need this app's data API integrated?
We deliver scoped integrations for any named app — from USD 500 with source-code handoff, or hosted access billed per call. Tell us the data you need.
- NDA + SOW on every engagement
- Delivery in 3–7 days
- Payment only after acceptance
- Work scoped to authorized use