Skip to main content

callback

Endpoint

POST {{YourHost}}

Available Request Headers

KeyValue
Content-Typeapplication/json

Available Request Query Params

No Params

Available Request Body

No body defined.


Sample Request and Response

No samples found.

Documentation

Callback

Snapcart sends a POST request to the client’s registered callback URL when a transaction reaches (or reports) a terminal or intermediate status (Success / Failed / Pending — depending on implementation).

This document describes the body structure the client will RECEIVE (not an API you call). If you include a reference_id in your Inquiry/Payment request, Snapcart will echo it in callback payloads to help correlate with your internal orders.

Endpoint (Client Side)

POST https://{{YourHost}}

(You can customize the path; ensure it matches what was registered with Snapcart.)

Headers

HeaderRequiredDescription
Content-TypeYesapplication/json
(Optional Auth)ConditionalHMAC/API key if agreed

No query parameters.

Request Body Fields

FieldTypeLengthRequiredDescription
request_idstring26YesCorrelation ID for the transaction flow (Inquiry→Payment or one-step Payment). Use this as the primary key for status checks and idempotency.
reference_idstring1–100OptionalClient-supplied correlation ID. Echoed verbatim when sent in Inquiry/Payment; useful to join with your internal order/checkout.
product_codestring1–64YesProduct code associated with the order. Derived from item_code in worker mapping.
bill_amountnumber-ConditionalTotal amount billed (multi-step BPJS/Postpaid) or amount paid (if available). May be 0.0 for pure validation (game voucher).
bill_numberstring8–18ConditionalBilling / destination number for BPJS/Postpaid or prepaid products. Omitted for game voucher if not applicable.
status_codestring-YesUnified code (e.g. 200, 400, 402, 404, 500, etc.).
status_messagestring-YesUnified message mapped from vendor/internal state (e.g. "Transaction successful", "Transaction failed").
request_atstringISO8601ConditionalOriginal request timestamp (if propagated). May be empty if upstream did not include.
updated_atstringISO8601YesFinal (or latest) update time when status was set internally.
additional_infoobject-OptionalProduct-specific enrichment; can be empty . Keys differ per product_code.

Notes:

  • There is currently NO dedicated error field in the callback body. Failure semantics are inferred from status_code / status_message.
  • There is currently NO explicit order_status (SUCCESS/FAILED/PENDING) field — can be derived by client from status_code mapping.
  • additional_info may be empty {} and should be treated as optional. Never assume a fixed schema across products.
  • request_id is authoritative for Snapcart side tracing and Payment Status queries.
  • reference_id is an optional client field echoed for your reconciliation.

About request_id vs reference_id

  • request_id: generated by Snapcart; use for Payment Status, idempotency checks, and matching callbacks.
  • reference_id: supplied by you; echoed in responses/callbacks when sent; use to join with your internal order or checkout IDs. Do not rely on it for API status queries (use request_id instead).

Product-Specific additional_info Keys

Product Group / Example CodePossible Keys (as sent)
BPJS Kesehatan VA (BPJS-KS)customer_name, number_of_month, member_total, transaction_id
BPJS Ketenagakerjaan PUbulan_tagihan, nama_perusahaan, kode_iuran
BPJS Ketenagakerjaan BPUcustomer_name, bulan_periode, kantor_cabang, kode_iuran
BPJS KS Dendacustomer_name, nama_perusahaan, jenis_tagihan, keterangan
Pulsa XLcustomer_id, xl_prepaid_code, bill, period, pulsa, serial_number
Three Prepaidcustomer_id, three_prepaid_code, bill, amount, serial_number, transaction_id
Smartfren Prepaidcustomer_id, smartfren_prepaid_code, bill, window_period, amount, serial_number
Smartfren Paket Data (Mochan)customer_id, smartfren_prepaid_code, bill, get_reff_no, amount, serial_number
Indosat Paket Datacustomer_id, kode_paket, bill, window_period, amount, serial_number, trx_id
Indosat Prepaidcustomer_id, product_code, bill, window_period, amount, serial_number, trx_id
Game Voucher (Generic)invoice_id, reference, total_amount, sn, trx_date, callback_url, user_id, zone_id
PPOB generic (default mapping)(often empty )

If a key is absent or empty, treat it as not provided — do not fail parsing.


Sample Callback Payloads (Success)

BPJS / Postpaid (Success)

{
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"reference_id": "your-unique-id-2025-000123",
"product_code": "TELKOM_POSTPAID",
"bill_number": "081230000009",
"bill_amount": 5500,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T03:40:05Z",
"updated_at": "2025-11-21T03:41:12Z",
"additional_info": {
"serial_number": "03357875092/112023/05/0003",
"idtrx": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"balance": "50.850"
}
}

BPJS Kesehatan VA

{
"request_id": "01HFAXYZABCDEF1234567890",
"reference_id": "your-unique-id-2025-000123",
"product_code": "BPJS-KS",
"bill_number": "888880000001234501",
"bill_amount": 105000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:12:10Z",
"updated_at": "2025-11-21T02:13:44Z",
"additional_info": {
"customer_name": "JOHN DOE",
"number_of_month": "1",
"member_total": "3",
"transaction_id": "TRX-BPJS-991122"
}
}

BPJS TK PU

{
"request_id": "01HFAXYZPUABCDEF123456789",
"reference_id": "your-unique-id-2025-000123",
"product_code": "BPJS-TK-PU",
"bill_number": "012345678901",
"bill_amount": 250000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:15:00Z",
"updated_at": "2025-11-21T02:16:05Z",
"additional_info": {
"bulan_tagihan": "202511",
"nama_perusahaan": "PT Sukses Abadi",
"kode_iuran": "IURAN-01"
}
}

BPJS TK BPU

{
"request_id": "01HFAXYZBPUABCDEF1234567",
"reference_id": "your-unique-id-2025-000123",
"product_code": "BPJS-TK-BPU",
"bill_number": "9876543210",
"bill_amount": 110000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:18:00Z",
"updated_at": "2025-11-21T02:19:02Z",
"additional_info": {
"customer_name": "ADI SAPUTRA",
"bulan_periode": "202511",
"kantor_cabang": "Jakarta Pusat",
"kode_iuran": "KDR-778"
}
}

BPJS KS Denda

{
"request_id": "01HFAXYZDENDA12345678901",
"reference_id": "your-unique-id-2025-000123",
"product_code": "BPJS-KS-DENDA",
"bill_number": "888880000009999999",
"bill_amount": 35000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:22:00Z",
"updated_at": "2025-11-21T02:23:11Z",
"additional_info": {
"customer_name": "SRI HANDAYANI",
"nama_perusahaan": "PT Prima",
"jenis_tagihan": "Denda",
"keterangan": "Late payment adjustment"
}
}

Pulsa XL Prepaid

{
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH4WV",
"reference_id": "your-unique-id-2025-000123",
"product_code": "XL_FLEX_S_10",
"bill_number": "081230000042",
"bill_amount": 10000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:30:00Z",
"updated_at": "2025-11-21T02:30:20Z",
"additional_info": {
"customer_id": "081230000042",
"xl_prepaid_code": "FLEX-S-10",
"bill": "10000",
"period": "202511",
"pulsa": "10",
"serial_number": "SN-XL-88997766"
}
}

Three Prepaid

{
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH4WZ",
"reference_id": "your-unique-id-2025-000123",
"product_code": "THREE_PREPAID",
"bill_number": "089912340001",
"bill_amount": 20000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:35:00Z",
"updated_at": "2025-11-21T02:35:19Z",
"additional_info": {
"customer_id": "089912340001",
"three_prepaid_code": "THR-20K",
"bill": "20000",
"amount": "20000",
"serial_number": "SN-3-112233",
"transaction_id": "TRX-3-8899"
}
}

Smartfren Prepaid

{
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH500",
"reference_id": "your-unique-id-2025-000123",
"product_code": "SMARTFREN_PREPAID",
"bill_number": "088812345678",
"bill_amount": 15000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:40:00Z",
"updated_at": "2025-11-21T02:40:22Z",
"additional_info": {
"customer_id": "088812345678",
"smartfren_prepaid_code": "SF-15K",
"bill": "15000",
"window_period": "202511",
"amount": "15000",
"serial_number": "SN-SF-556677"
}
}

Smartfren Paket Data (Mochan)

{
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH501",
"reference_id": "your-unique-id-2025-000123",
"product_code": "SMARTFREN_DATA_MOCHAN",
"bill_number": "088899991111",
"bill_amount": 60000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:42:00Z",
"updated_at": "2025-11-21T02:42:33Z",
"additional_info": {
"customer_id": "088899991111",
"smartfren_prepaid_code": "SF-DATA-60",
"bill": "60000",
"get_reff_no": "REF-778812",
"amount": "60000",
"serial_number": "SN-SF-DATA-123"
}
}

Indosat Paket Data

{
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH502",
"reference_id": "your-unique-id-2025-000123",
"product_code": "INDOSAT_PAKET_DATA",
"bill_number": "085712345678",
"bill_amount": 50000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:45:00Z",
"updated_at": "2025-11-21T02:45:30Z",
"additional_info": {
"customer_id": "085712345678",
"kode_paket": "ID-PKT-50",
"bill": "50000",
"window_period": "202511",
"amount": "50000",
"serial_number": "SN-ID-1122",
"trx_id": "TRX-ID-9988"
}
}

Indosat Prepaid

{
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH503",
"reference_id": "your-unique-id-2025-000123",
"product_code": "INDOSAT_PREPAID",
"bill_number": "085799991111",
"bill_amount": 25000.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:48:00Z",
"updated_at": "2025-11-21T02:48:15Z",
"additional_info": {
"customer_id": "085799991111",
"product_code": "INDOSAT_PREPAID",
"bill": "25000",
"window_period": "202511",
"amount": "25000",
"serial_number": "SN-ID-P-2233",
"trx_id": "TRX-IP-2211"
}
}

Game Voucher

{
"request_id": "01JK8HQJ2K1WMBBFGEV6GAME01",
"reference_id": "your-unique-id-2025-000123",
"product_code": "ML-DIAMONDS-86",
"bill_amount": 0.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:50:00Z",
"updated_at": "2025-11-21T02:50:19Z",
"additional_info": {
"invoice_id": "INV-ML-5566",
"reference": "REF-998877",
"total_amount": "15000",
"sn": "SERIAL-ML-112233",
"trx_date": "2025-11-21T02:50:15Z",
"callback_url": "https://client.example.com/callback",
"user_id": "Player123",
"zone_id": "SEA"
}
}

Generic PPOB (Empty additional_info)

{
"request_id": "01JK8HQJ2K1WMBBFGEV6PPOB01",
"reference_id": "your-unique-id-2025-000123",
"product_code": "PPOB-ELECTRIC",
"bill_number": "012345678000",
"bill_amount": 112500.0,
"status_code": "200",
"status_message": "Transaction successful",
"request_at": "2025-11-21T02:55:00Z",
"updated_at": "2025-11-21T02:55:35Z",
"additional_info": {}
}

Pending Callback Example

(If system emits a pending state; some deployments only send terminal states.)

{
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH4WV",
"reference_id": "your-unique-id-2025-000123",
"product_code": "XL_FLEX_S_10",
"bill_number": "081230000042",
"bill_amount": 10000.0,
"status_code": "200",
"status_message": "Transaction is being processed",
"request_at": "2025-11-21T03:00:00Z",
"updated_at": "2025-11-21T03:00:04Z",
"additional_info": {
"customer_id": "081230000042",
"xl_prepaid_code": "FLEX-S-10"
}
}

Failure Examples

Incorrect Bill Number (BPJS/Postpaid)

{
"request_id": "01HFAXYZABCDEF1234567890",
"reference_id": "your-unique-id-2025-000123",
"product_code": "TELKOM_POSTPAID",
"bill_number": "081230000009",
"bill_amount": 0.0,
"status_code": "400",
"status_message": "Incorrect bill number",
"request_at": "2025-11-21T02:10:10Z",
"updated_at": "2025-11-21T02:10:22Z",
"additional_info": {}
}

Insufficient Balance (After Inquiry)

{
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"reference_id": "your-unique-id-2025-000123",
"product_code": "TELKOM_POSTPAID",
"bill_number": "081230000009",
"bill_amount": 5500,
"status_code": "402",
"status_message": "Insufficient balance",
"request_at": "2025-11-21T03:10:05Z",
"updated_at": "2025-11-21T03:10:05Z",
"additional_info": {
"serial_number": "03357875092/112023/05/0003"
}
}

Transaction Failed (Vendor Failure)

{
"request_id": "01JK8HQJ2K1WMBBFGEV6FAIL01",
"reference_id": "your-unique-id-2025-000123",
"product_code": "XL_FLEX_S_10",
"bill_number": "081230000042",
"bill_amount": 10000.0,
"status_code": "400",
"status_message": "Transaction failed",
"request_at": "2025-11-21T03:12:00Z",
"updated_at": "2025-11-21T03:12:40Z",
"additional_info": {
"customer_id": "081230000042",
"xl_prepaid_code": "FLEX-S-10"
}
}

Transaction Not Found

{
"request_id": "01JK8H_UNKNOWN_REQUEST_ID",
"reference_id": "",
"product_code": "ML-DIAMONDS-86",
"bill_amount": 0.0,
"status_code": "404",
"status_message": "Transaction not found",
"request_at": "",
"updated_at": "2025-11-21T03:20:10Z",
"additional_info": {}
}

Inquiry Expired (Two-Step)

{
"request_id": "01HFAXYZABCDEF1234567890",
"reference_id": "your-unique-id-2025-000123",
"product_code": "BPJS-KS",
"bill_number": "888880000001234501",
"bill_amount": 105000.0,
"status_code": "410",
"status_message": "Inquiry expired",
"request_at": "2025-11-21T02:00:00Z",
"updated_at": "2025-11-21T02:30:05Z",
"additional_info": {
"customer_name": "JOHN DOE",
"number_of_month": "1"
}
}

Third Party Error (Vendor)

{
"request_id": "01JK8HQJ2K1WMBBFGEV6ERR500",
"reference_id": "your-unique-id-2025-000123",
"product_code": "INDOSAT_PREPAID",
"bill_number": "085799991111",
"bill_amount": 25000.0,
"status_code": "500",
"status_message": "Third party error",
"request_at": "2025-11-21T03:25:00Z",
"updated_at": "2025-11-21T03:25:11Z",
"additional_info": {
"customer_id": "085799991111",
"product_code": "INDOSAT_PREPAID"
}
}

Idempotency & Handling

ConcernGuidance
Duplicate callbackTreat as idempotent: check request_id; ignore repeats after first persistence. Optionally also match on reference_id if you send it.
Missing optional keysSafely ignore; never hard fail parsing.
Empty additional_infoAccept as valid; may occur for products with no enrichment.
Unknown status_codeFallback to generic error handling; escalate with raw payload.
Out-of-order arrivalAlways rely on updated_at; store latest and discard older timestamps for same request_id.
  1. Receive POST
  2. Validate JSON structure & mandatory fields (request_id, product_code, status_code, status_message).
  3. Persist record (audit log + transactional save), joining with your order using reference_id if present.
  4. Apply business classification (Success / Pending / Failed) based on status_code.
  5. If status_code indicates Pending, continue polling Payment Status API (if implemented).
  6. If success/failure terminal: stop polling & finalize settlement logic.
  7. Emit internal event / notify downstream systems.

Mapping Terminal vs Non-Terminal (Suggested)

status_codestatus_messageTerminal?Notes
200 + “Transaction successful”SuccessYesFinal success.
200 + “Transaction is being processed”PendingNoContinue polling.
402Insufficient balanceYesFailed due to balance; requires top-up then new flow.
400 / 404 / 410Various failuresYesTerminal; analyze cause & possibly restart flow.
500+Third party / internal errorsYes (usually)Investigate; may allow re-initiation with new request_id.

Additional Info Variability

  • Treat all additional_info keys as optional.
  • Do not rely on one product’s keys existing in another product.
  • Unknown keys should be preserved for logging but safely ignored in core logic.

Next Step After Receiving Callback

  • If terminal: update transaction state & stop polling.
  • If pending: continue periodic GET /pre-order/payment/status/:request_id until terminal.
  • For failures like Insufficient balance (402): instruct wallet top-up before new Payment.
  • For Inquiry expired (410): restart from Inquiry.

Notes

  • This format reflects current implementation.
  • Any schema evolution should remain backward-compatible; clients should ignore unknown fields (forward compatibility).