Skip to content

Make Payment ​

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
X-API-VersionAPI version date for opting into upcoming response format changes (e.g. 2026-04-01). Optional.No

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 | numberYesTransaction face value or quantity. For a pricing select, send the selected option's numeric denomination, not price.amount; for a direct money field, send the entered amount. Internally parsed as decimal. The response always returns a number (integer if whole, decimal otherwise).
extrasobjectNoAdditional parameters required by specific products (see below)
extras.subproduct_codestringConditionalExact option code from /v2/options for the product's pricing field. Required for mobile internet products. Must correspond to the plan whose denomination equals amount.
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---

Plan code validation

A supplied plan code must exactly match (case-sensitive) an active option code for the product's pricing field. The option's denomination must equal amount.

Validation failures return HTTP 400 with data.statusCode 44, create no transaction, and leave the refid available for reuse. The possible remarks are:

  • Multiple plans are available for this amount. Please provide a plan code.
  • unknown or inactive option code '<code>'. Select an available plan and try again.
  • option code '<code>' does not match amount <amount>. Select the plan for this amount and try again.

This validation does not depend on X-API-Version.

Backward compatibility

Existing integrations that send amount only continue to work while the amount identifies exactly one active plan. New integrations must send subproduct_code.

JomPAY Testing

For staging test biller codes that simulate JomPAY payment outcomes, see JomPAY Test Biller Codes.

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 ​

HTTPStatusFinal?Transaction Created?What To Do
400FailedYesNoFix input, retry with same refid
200AcceptedNoYesRe-query with same refid
200ProcessingNoYesRe-query with same refid
200SuccesfulYesYesDone
200FailedYesYesFinal failure — use new refid
200RefundYesYesTransaction was voided

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