GoBiz Link
GoBiz Link is an optional, free, live-mode-only second payment-detection source. Link the merchant’s GoPay Merchant (GoBiz) account once with an SMS OTP, and the gateway’s own poller watches that account’s transaction feed server-side whenever you have unpaid transactions — covering the App Listener’s blind spots: phone off, notification missed, the listener app killed by battery savers.
Both detectors feed the exact same matching pipeline, so they can’t conflict: whichever sees the
payment first marks the transaction paid and fires your webhook; the other is recorded as
ignored in the inbound audit log. Poller matches show
payment_source: "gobiz_poll" there, plus the GoBiz transaction id when the feed provides one —
so you can see, per transaction, which detector won.
Unofficial API notice. The poller talks to the same private GoBiz API the GoBiz dashboard uses — not an official integration. GoBiz may change authentication, add rate limits, or invalidate sessions at any time, and accounts driven by automated clients risk suspension. Link at your own discretion. If the session breaks, nothing about payments breaks: the tenant simply degrades to App-Listener-only detection until re-linked (see Session health below).
Coverage is GoPay only. Payments arriving through DANA, ShopeePay, or other apps are still detected exclusively by the App Listener — keep it running even with GoBiz linked. The two are complements, not alternatives.
Endpoints
Section titled “Endpoints”All four require your live X-API-Key — a sandbox key gets VALIDATION_ERROR (sandbox has
simulate-payment instead).
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/gobiz-link/request-otp | Ask GoBiz to SMS an OTP to the merchant’s number |
POST | /v1/gobiz-link/verify-otp | Verify the OTP; stores the session encrypted and activates polling |
GET | /v1/gobiz-link | Link status |
DELETE | /v1/gobiz-link | Unlink (idempotent) — deletes the stored session |
1. Request the OTP
Section titled “1. Request the OTP”request-otp is capped at 5 calls/minute — every call triggers a real SMS.
curl -X POST https://api-qris-gateway.laboon.id/v1/gobiz-link/request-otp \ -H "X-API-Key: your_live_api_key" \ -H "Content-Type: application/json" \ -d '{ "phone_number": "08123456789" }'{ "success": true, "message": "OTP sent by GoBiz — verify it to finish linking", "data": { "phone_masked": "62812•••789", "otp_token": "…", "device_id": "…", "expires_in": 720 }}otp_token and device_id are passthroughs: hold them client-side and send both back on
verify. GoBiz binds the OTP to the device_id that requested it, so a verify without it is
rejected as an invalid OTP. Nothing is stored server-side until the OTP is verified.
2. Verify the OTP
Section titled “2. Verify the OTP”curl -X POST https://api-qris-gateway.laboon.id/v1/gobiz-link/verify-otp \ -H "X-API-Key: your_live_api_key" \ -H "Content-Type: application/json" \ -d '{ "phone_number": "08123456789", "otp_token": "…", "device_id": "…", "otp": "123456" }'{ "success": true, "message": "GoBiz account linked", "data": { "linked": true, "status": "active", "phone_masked": "62812•••789", "gobiz_merchant_id": "G-…", "outlet_name": "…" }}A wrong or expired OTP returns 400 VALIDATION_ERROR; request a new OTP and try again.
Re-verifying while already linked simply replaces the stored session (there is at most one GoBiz
link per tenant).
The GoBiz tokens are stored encrypted (AES-256-GCM) and are never returned by any endpoint.
3. Status and unlink
Section titled “3. Status and unlink”curl https://api-qris-gateway.laboon.id/v1/gobiz-link -H "X-API-Key: your_live_api_key"curl -X DELETE https://api-qris-gateway.laboon.id/v1/gobiz-link -H "X-API-Key: your_live_api_key"GET returns { "linked": false } or the link’s status, phone_masked,
gobiz_merchant_id, and timestamps. DELETE is idempotent — unlinking twice is still a 200.
How polling behaves
Section titled “How polling behaves”- The poller only runs for a tenant while it has at least one unpaid live transaction — an idle tenant costs GoBiz nothing.
- A feed settlement is matched with the same by-amount rules as the App Listener, but with two extra freshness guards on the poller’s side: a transaction is only reported if it’s newer than everything already scanned and falls inside a currently-unpaid transaction’s own time window. Yesterday’s same-amount settlement can never pay today’s transaction.
- If GoBiz rate-limits the account (HTTP 429), that tenant’s polling pauses for a minute and resumes on its own. Other tenants are unaffected.
- Idle links are kept warm: even with no transactions for weeks, the gateway periodically refreshes a near-expiry session in the background so the link doesn’t die of disuse — you should rarely need to re-link outside of an actual credential change on GoBiz’s side.
Session health
Section titled “Session health”GET /v1/gobiz-link reports one of:
active— polling normally.needs_relink— GoBiz rejected the stored session (rotated/expired refresh token). The poller has stopped for this tenant; the App Listener keeps detecting as usual. Run the OTP flow again to restore polling — re-verifying replaces the dead session in place.
There is no error state that affects payment processing: every GoBiz-side failure degrades to App-Listener-only detection, never to lost payments.