GoPay Merchant: QRIS icon

GoPay Merchant QRIS data API

PT. GoTo Gojek Tokopedia Tbk · Payments 4.6 ★

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

  • GoPay Merchant: QRIS screenshot 1
  • GoPay Merchant: QRIS screenshot 2
  • GoPay Merchant: QRIS screenshot 3
  • GoPay Merchant: QRIS screenshot 4
  • GoPay Merchant: QRIS screenshot 5

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/float openbanking

    Reads 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/home openfinance

    Loads 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/wallets openbanking

    Splits 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/limits openfinance

    Returns 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/plate opendata

    Returns 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/charges openbanking

    Creates 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/refunds openbanking

    Posts 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/payouts openbanking

    Starts 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/preview openfinance

    Pre-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/windows openfinance

    Lists 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/activity openfinance

    Pages 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/sales opendata

    Queues 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/locations opendata

    Lists 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/safety osint

    Reads 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/otp opendata

    Exchanges 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

Get a quote