Appearance
Step 5: Make Payment
This is the central step in your integration — processing transactions via a single unified endpoint (POST /v2/topup) that handles all product types, including JomPAY, mobile recharge, gift cards, vouchers, eSIM purchases, and more.
API Reference
For the full endpoint specification (headers, request body, response schema, and examples), see Make Payment API Reference.
How It Works
- Initiate payment — Call
POST /v2/topupwith a uniquerefid, the product code, account number, and amount. - Handle the response — Check the HTTP status code first, then
data.status:- HTTP 400 +
Failed— Validation error (invalid amount, insufficient balance, etc.). No transaction was created. Fix the input and retry with the samerefid. - HTTP 200 +
Accepted— Transaction accepted, processing will begin. - HTTP 200 +
Processing— Transaction still in progress. Re-query with the samerefidand parameters. - HTTP 200 +
Succesful— Transaction completed. Display the result to the user. - HTTP 200 +
Failed— Transaction was created but failed at the provider. Use a newrefidfor the next attempt.
- HTTP 400 +
- Check final status — If the response was
Processingor you encountered a network error, re-call the same endpoint with the identicalrefidand parameters.
Spelling Note
The success status value is spelled Succesful (single 's'), not Successful. This is a legacy quirk that cannot be changed. Match this exact string in your code.
| Stage | HTTP | Status | Transaction Created? | Retry? |
|---|---|---|---|---|
| Validation fails (invalid amount, account, denomination, insufficient balance, etc.) | 400 | Failed | No | Yes — same refid, fix input |
| Request accepted, pending processing | 200 | Accepted | Yes | Re-query same refid |
| Still processing | 200 | Processing | Yes | Re-query same refid |
| Transaction completed | 200 | Succesful | Yes | No |
| Transaction failed at provider (via re-query/callback) | 200 | Failed | Yes | No — use new refid |
| Transaction voided | 200 | Refund | Yes | No |
Retries and refid Reuse
The API is idempotent: calling POST /v2/topup with the same refid will return the existing transaction, never create a duplicate. Always reuse the original refid and parameters when retrying — generating a new refid on retry will create a duplicate charge. Only generate a new refid for a genuinely new transaction.
When to reuse the same refid vs. generate a new one:
- HTTP 400 +
Failed— No transaction was created,refidnot consumed. Fix the input and retry with the samerefid. - HTTP 200 +
Processing/ network error — Transaction may be in progress. Re-query with the samerefid. - HTTP 200 +
Failed— Transaction was created and failed at the provider level. This is final — use a newrefid.
Recommended Polling Strategy
When a transaction returns Processing, poll every 5-10 seconds by re-querying with the same refid. Most transactions resolve within 30 seconds. Always combine polling with callbacks — polling provides immediate UX feedback, while callbacks are the reliable final status delivery mechanism.
Extras Parameters by Product
The extras object in the request body has different requirements depending on the product:
| Parameter | JomPAY | PTPTN | Mobile Data | Others |
|---|---|---|---|---|
subproduct_code | - | Mandatory | Mandatory | - |
ic_number | Mandatory (payee IC) | Mandatory (recipient IC) | - | - |
biller_code | Mandatory | - | - | - |
ref2 | Conditional | - | - | - |
ref2 is required by some JomPAY billers. The ref2 value is typically printed on the user's JomPAY bill. Use bill presentment to validate. The API returns an error if ref2 is required but not provided.
AMLA Compliance — JomPAY
DANGER
Due to AMLA (Anti-Money Laundering Act 2001) requirements, it is mandatory to perform eKYC on your end-users for all JomPAY transactions. Pass the verified IC number (Malaysians) or Passport number (non-Malaysians) via the ic_number field. Failure to comply, or providing fictitious/invalid numbers, may lead to account suspension.
Success UX
After a successful transaction, display the following fields to the user:
| Field | Description |
|---|---|
sn | Serial number or identifier generated by the provider/operator. Include a Copy button. |
pin | PIN for vouchers, gift cards, and similar products. Include a Copy button. |
voucherlink | A URL to open in a web view for voucher redemption. |
| Share button | Allow the user to share the transaction via WhatsApp, email, SMS, etc. |
DANGER
If a field (sn, pin, expiry, voucherlink) is not returned by the API, do not display that label or field to the user.

Failure UX
After a failed transaction, display the failure reason so the user understands what went wrong:
| Field | Description |
|---|---|
remarks | The failure reason returned by the API. |

Error Handling
Error codes for failed transactions can be found in the Payment Errors reference.
WARNING
Staging server statuses and failure reasons might not match production due to limited validation.
