payment
Endpoint
POST https://{{host}}/api/v1/payment
Available Request Headers
| Key | Value |
|---|---|
| Content-Type | application/json |
| x-api-key | 51f4b8ad3a4c9f0859253700436f0a343d05602761c306c4cb514215fdf33c5a |
Available Request Query Params
No Params
Available Request Body
{
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"bill_number": "081230000009",
"product_code": "TELKOM_POSTPAID",
"reference_id": "your-unique-id-2025-000123"
}
Sample Request and Response
success
Sample Request
Headers
| Key | Value |
|---|---|
| Content-Type | application/json |
| x-api-key | 51f4b8ad3a4c9f0859253700436f0a343d05602761c306c4cb514215fdf33c5a |
Params
No Params
Body
{
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"bill_number": "081230000009",
"product_code": "TELKOM_POSTPAID",
"reference_id": "your-unique-id-2025-000123"
}
Sample Response
{
"data": {
"biller_code": "200",
"biller_message": "Transaction is being processed",
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"reference_id": "your-unique-id-2025-000123"
},
"status_code": "200",
"status_message": "Transaction successful"
}
error
Sample Request
Headers
| Key | Value |
|---|---|
| Content-Type | application/json |
| x-api-key | 51f4b8ad3a4c9f0859253700436f0a343d05602761c306c4cb514215fdf33c5a |
Params
No Params
Body
{
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"bill_number": "081230000009",
"product_code": "TELKOM_POSTPAID_FAIL",
"reference_id": "your-unique-id-2025-000123"
}
Sample Response
{
"data": null,
"status_code": "404",
"status_message": "Product not found",
"error": "Failed to get product details"
}
Documentation
Executes the payment for a product. Returns an immediate asynchronous acknowledgement (queued / in process) plus a request_id (for one-step flows) or echoes the existing request_id (two-step flows). Final SUCCESS / FAILED / EXPIRED is delivered later via:
- Polling: GET /api/v1/pre-order/payment/status/:request_id
- Callback (if registered)
Do NOT treat the initial 200 as the final transaction result unless business status already terminal (rare). If you provide a reference_id in the request, it will be echoed back in this response, Payment Status, and Callback to help you correlate with your internal order/checkout.
Endpoint
POST /api/v1/pre-order/payment
Headers
| Header | Required | Description |
|---|---|---|
| x-api-key | Yes | Client API key issued by Snapcart |
| Content-Type | Yes | application/json |
Query Parameters
(None)
Request Body
Only send fields relevant to the product. Unused fields must be omitted.
| Field | Type | Length | Required | Description |
|---|---|---|---|---|
| request_id | string | 26 | Conditional | Required for two-step (postpaid/BPJS) from prior Inquiry. Omit for one-step. |
| product_code | string | 1–64 | Yes | Product code being purchased. |
| bill_number | string | 8–18 | Conditional | Billing/destination number. Required for postpaid/BPJS and many prepaid items. |
| user_id | string | 1–32 | Conditional | Game voucher player ID (if product type is game voucher). |
| zone_id | string | 1–16 | Conditional | Game voucher zone/region (if required). |
| item_code | string | 1–64 | Conditional | Specific item SKU if product requires explicit variant at payment. |
| reference_id | string | 1–100 | Optional | Your client‑supplied correlation ID; echoed verbatim in responses, Payment Status, and Callback. Use letters, digits, dash, underscore; case-sensitive. |
Notes:
- Two-step products (e.g. BPJS): Must include request_id returned by Inquiry.
- One-step products (e.g. prepaid top-up, data packet): request_id absent; a new one will be generated internally and returned in response data.
- bill_number may represent a phone/account number for prepaid products.
- Send reference_id to simplify reconciliation; Snapcart returns it verbatim throughout the flow.
Sample Request (PPOB Postpaid / BPJS)
{
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"bill_number": "081230000009",
"product_code": "TELKOM_POSTPAID",
"reference_id": "your-unique-id-2025-000123"
}
Sample Request (PPOB Prepaid: Pulsa / Data Packet)
{
"bill_number": "081230000042",
"product_code": "XL_FLEX_S_10",
"reference_id": "your-unique-id-2025-000123"
}
Successful Acknowledgement Response (BPJS / Postpaid)
{
"data": {
"biller_code": "200",
"biller_message": "Transaction is being processed",
"request_id": "01K9Y5K0YP9B1MPKCEVJCACZ3B",
"reference_id": "your-unique-id-2025-000123"
},
"status_code": "200",
"status_message": "Transaction successful"
}
Explanation:
| Field | Type | Description |
|---|---|---|
| status_code | string | Unified code (200 here = accepted / queued). |
| status_message | string | Unified message (“Transaction successful” initial ack). |
| reference_id | string | Echo of your client-supplied ID for correlation. |
| data.request_id | string | Echo from Inquiry (two-step). Use for status polling. |
| biller_code | string | Upstream biller/vendor code. |
| biller_message | string | Upstream message (often pending context). |
Successful Acknowledgement Response (Prepaid Pulsa / Data Packet)
{
"data": {
"biller_code": "200",
"biller_message": "Transaction is being processed",
"request_id": "01JK8HQJ2K1WMBBFGEV6CEH4WV",
"reference_id": "your-unique-id-2025-000123"
},
"status_code": "200",
"status_message": "Transaction successful"
}
Prepaid notes:
- Newly generated request_id returned in data.request_id (store this).
- biller_message usually indicates pending processing with vendor.
Error Response Examples
Validation Error (missing product_code):
{
"status_code": "400",
"status_message": "Bad request",
"error": "Required field (product_code)"
}
Incorrect request_id (not found / expired):
{
"status_code": "404",
"status_message": "Transaction not found",
"error": "request_id not found"
}
Insufficient Balance (wallet below charge):
{
"status_code": "402",
"status_message": "Insufficient balance",
"error": "Insufficient balance - current balance 50.850"
}
Additional Info
- Some products may include enriched fields (e.g. invoice_id, serial_number) in later status or callback, not typically in initial payment ack.
- additional_info (if present in subsequent status responses) can differ per product_code and may be empty; treat as optional.
- Persist both IDs: request_id (Snapcart) and reference_id (yours) for reconciliation and support.
Next Step After Payment
Perform one (or both):
- Poll: GET /api/v1/pre-order/payment/status/:request_id until terminal (SUCCESS / FAILED / EXPIRED).
- Receive callback: Terminal state posted to your registered endpoint (contains status_code, status_message, order_status).
Recommendations:
- Implement both polling + callback for resilience (callback is strongly recommended in production; polling as fallback).
- Treat initial 200 as QUEUED/PENDING; do not mark transaction as SUCCESS until a final status is received.
- Log: request_id, reference_id, product_code, biller_code, biller_message, status_code.
Notes
- Never reuse a request_id across different product_code flows.
- For one-step products, always capture the generated request_id from the payment response to drive status polling and correlation.
- Handle 402 (Insufficient balance): top-up then initiate a new payment (do not retry same payload blindly).
- For idempotent safety, avoid resubmitting Payment with identical request_id; use status polling instead.