Skip to content

Make Payment

Legacy Endpoint Name

The endpoint path /v2/topup is a legacy name. This single endpoint processes all transaction types: mobile reload, bill payments, vouchers, gift cards, eSIM, and more.

Process transactions across the IIMMPACT platform. This is a unified endpoint for all product offerings, including JomPAY, mobile reload, gift cards, vouchers, eSIM purchases, and more.

TIP

For a step-by-step integration walkthrough, see the Make Payment Guide.

Idempotency

The API supports idempotency — you can safely retry requests without creating duplicate transactions. Store and re-use the same refid for the same transaction.

Check Final Transaction Status: Call this API again with the identical request parameters and the original refid used during initiation. The API will return the current status of the transaction.

API Endpoint

http
POST https://api.iimmpact.com/v2/topup

DANGER

Staging server statuses and failure reasons might not match production due to limited validation.

Request Headers

HeaderDescriptionRequired
X-Api-KeyYour API keyYes
X-TimestampUnix timestamp in secondsYes
X-NonceUnique request identifierYes
X-SignatureHMAC-SHA256 signature (v1=...)Yes

See API Key Authentication for how to sign your requests.

Request Body

ParameterTypeRequiredDescription
refidstringYesYour unique reference ID for this transaction. See refid constraints.
productstringYesProduct code
remarksstringNoOptional field for any additional remarks
accountstringYesRecipient's account number or identifier (e.g., bill account number, mobile number)
amountstring | numberYesAccepts both string and number in the request body. Internally parsed as decimal. The response always returns a number (integer if whole number, decimal otherwise).
extrasobjectNoAdditional parameters required by specific products (see below)
extras.subproduct_codestringNoSub-product code
extras.ic_numberstringNoIC number without dashes
extras.biller_codestringNoBiller code
extras.ref2stringConditionalRequired 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.

refid Constraints

ConstraintValue
Max length50 characters
Allowed charactersAny non-empty string
Uniqueness scopePer reseller account (not global)
IdempotencyPermanent — re-querying with an existing refid always returns the original transaction

Example Request Body

jsonc
{
  "refid": "321479-0-30f4f209-ee",
  "product": "GC",
  "account": "0123456789",
  "amount": 10.00, // Strings also work, e.g. "10.00"
  "remarks": "",
  "extras": {}
}

Extras Requirements by Product

ParameterJomPAYPTPTNMobile DataOthers
subproduct_code-MandatoryMandatory-
ic_numberMandatory (payee IC)Mandatory (recipient IC)--
biller_codeMandatory---
ref2Conditional---

AMLA Compliance — JomPAY

Due to AMLA (Anti-Money Laundering Act 2001) requirements, it is mandatory to perform eKYC (electronic Know Your Customer) 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.

Response 200

FieldTypeDescription
dataobjectTransaction result
data.statusCodenumberStatus code — see Payment Errors
data.statusstringOutcome: Accepted, Processing, Succesful, or Failed
data.accountstringAccount number
data.productstringProduct code
data.productNamestringProduct name
data.amountnumberAmount paid
data.snstringSerial number from the provider/operator
data.pinstringPIN for vouchers, gift cards, etc.
data.expirystringVoucher expiration date (yyyymmdd)
data.costnumberYour wholesale cost for this transaction (deducted from your IIMMPACT wallet balance).
data.balancenumberCurrent wallet balance
data.remarksstringAdditional notes about the transaction
data.refidstringYour unique reference ID
data.timestampstringTransaction timestamp
data.notestringInstructions or information for the user regarding the product
data.voucherlinkstringLink to access or redeem the voucher

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.

Example Response:

json
{
  "data": {
    "statusCode": 20,
    "status": "Succesful",
    "account": "0123456789",
    "product": "GC",
    "productName": "Grab Gift Code",
    "amount": 5,
    "sn": "106648697",
    "pin": "MPHE39G3WL",
    "expiry": "20251116",
    "cost": 5,
    "balance": 50.54,
    "remarks": "",
    "refid": "321479-0-30f4f209-ee",
    "timestamp": "2025-05-20 13:09:34",
    "note": "Insert voucher code into Use Grab Gifts under Use Offers section upon check out",
    "voucherlink": "https://api.grab.com/gifts/v2/go?id=7464957319334bb0afbd5980738a2b50"
  }
}

Response 400

Pre-transaction validation errors (invalid product, insufficient balance, invalid denomination, invalid account, etc.) return HTTP 400 with the same {"data": {...}} body shape as HTTP 200.

Key Difference from HTTP 200

HTTP 400 means no transaction was created and the refid is not consumed. You can safely retry with the same refid after correcting the input. This is different from an HTTP 200 Failed response, where a transaction was created.

FieldTypeDescription
dataobjectValidation error result
data.statusCodenumberStatus code — see Payment Errors
data.statusstringAlways Failed for validation errors
data.accountstringAccount number from the request
data.productstringProduct code from the request
data.amountnumberAmount from the request
data.costnumberAlways 0 (no transaction was processed)
data.balancenumberCurrent wallet balance (unchanged)
data.remarksstringReason for the validation failure (e.g., Invalid_Denomination, Insufficient_Balance)
data.refidstringYour reference ID (not consumed — can be reused)
data.timestampstringTimestamp of the response

Example Response:

json
{
  "data": {
    "statusCode": 58,
    "status": "Failed",
    "account": "0123456789",
    "product": "DB",
    "amount": 22.23,
    "cost": 0,
    "balance": 50.54,
    "remarks": "Invalid_Denomination",
    "refid": "my-ref-id",
    "timestamp": "2026-03-16 13:09:34"
  }
}

Transaction Status Values

The behavior of the Failed status depends on the HTTP status code:

StageHTTPStatusTransaction Created?Retry?
Validation fails (invalid amount, account, denomination, insufficient balance, etc.)400FailedNoYes — same refid, fix input
Request accepted, pending processing200AcceptedYesRe-query same refid
Still processing200ProcessingYesRe-query same refid
Transaction completed200SuccesfulYesNo
Transaction failed at provider (via re-query/callback)200FailedYesNo — use new refid
Transaction voided200RefundYesNo

Distinguish HTTP 400 Failed vs HTTP 200 Failed

  • HTTP 400 + Failed = no transaction was created, refid not consumed. Retry with the same refid after fixing the input.
  • HTTP 200 + Failed = a transaction was created and failed at the provider level. This is final — use a new refid for the next attempt.

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.

IIMMPACT API Documentation