Appearance
Transaction Webhook Payload
When configuring your Callback URL, you will need to specify whether your endpoint expects to receive HTTP GET or HTTP POST requests.
Subsequently, when an event occurs (such as a transaction status update), IIMMPACT will send an HTTP request using your chosen method.
Below is an illustrative example of the data sent in a callback:
IP Allowlist
For these callbacks to reach your system successfully, add the IP addresses for your environment to your allowlist. If you use staging, allowlist the staging IP address together with both production IP addresses.
| Environment | IP Addresses |
|---|---|
| Production | 18.140.170.98, 13.215.6.214 |
| Staging | 3.1.120.89, 18.140.170.98, 13.215.6.214 |
Callback Payload
| Field | Type | Description |
|---|---|---|
data.statusCode | number | Status code — see Payment Errors |
data.status | string | Outcome: Processing, Succesful, or Failed |
data.account | string | Account number |
data.product | string | Product code |
data.productName | string | Customer-facing product name (e.g. "Celcom Prepaid"). Empty string if unavailable |
data.amount | number | Amount paid |
data.sn | string | Serial number from the provider/operator |
data.pin | string | PIN for vouchers, gift cards, etc. |
data.expiry | string | Expiration date of the voucher (yyyymmdd). Empty string if not applicable |
data.cost | number | Your wholesale cost for this transaction (deducted from your IIMMPACT wallet balance). |
data.balance | number | Your current wallet balance after this transaction |
data.remarks | string | Additional notes about the transaction |
data.refid | string | Your unique reference ID |
data.timestamp | string | Transaction timestamp |
data.note | string | Instructions or information for the user regarding the product |
data.voucherlink | string | Link to access or redeem the voucher |
Sample HTTP POST Callback
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"
}
}Sample HTTP GET Callback
The GET callback sends four top-level query parameters: refid, status (status code), price, and message (URL-encoded JSON containing the full transaction data).
GET Parameter Mapping
The GET callback uses different parameter names than the POST payload. Use this mapping:
| GET Query Parameter | Maps To | Type | Note |
|---|---|---|---|
refid | refid | string | Reference ID (same name) |
status | statusCode | number | Not the status string — this is the numeric status code |
price | cost | number | Your wholesale cost (not the face value) |
message | Full response | URL-encoded JSON | Decode with decodeURIComponent() to get all transaction fields |
Recommendation
Use POST callbacks instead of GET. POST delivers the full transaction payload as structured JSON in the request body, avoiding URL encoding issues and parameter name confusion.
html
https://yourdomain.com?refid=1234t&status=48&price=9.73&message=%7B%22statusCode%22%3A48%2C%22status%22%3A%22Failed%22%2C%22account%22%3A%220123456789%22%2C%22product%22%3A%22C%22%2C%22productName%22%3A%22Celcom+Prepaid%22%2C%22amount%22%3A10%2C%22sn%22%3A%22%22%2C%22pin%22%3A%22%22%2C%22expiry%22%3A%22%22%2C%22cost%22%3A9.73%2C%22balance%22%3A50.54%2C%22remarks%22%3A%22HC%22%2C%22refid%22%3A%221234t%22%2C%22timestamp%22%3A%222025-05-21+14%3A29%3A31.710%22%2C%22note%22%3A%22%22%2C%22voucherlink%22%3A%22%22%7DDecoded message parameter:
json
{
"statusCode": 48,
"status": "Failed",
"account": "0123456789",
"product": "C",
"productName": "Celcom Prepaid",
"amount": 10,
"sn": "",
"pin": "",
"expiry": "",
"cost": 9.73,
"balance": 50.54,
"remarks": "HC",
"refid": "1234t",
"timestamp": "2025-05-21 14:29:31.710",
"note": "",
"voucherlink": ""
}Verifying Callback Authenticity
Transaction callbacks do not currently include a cryptographic signature. HMAC signature verification is planned for a future release.
In the meantime, use these verification steps:
- IP Allowlist — Only accept callbacks from IIMMPACT's IP addresses (listed above). Reject requests from unknown IPs.
- Match refid — Verify that the
refidin the callback matches a transaction you initiated. Reject callbacks for unknown reference IDs. - Validate fields — Check that
product,account, andamountmatch your original request. - Re-query for confirmation — For high-value transactions, call
POST /v2/topupwith the samerefidto independently verify the transaction status. - Idempotent handling — Process each
refidonly once. Ignore duplicate callbacks for the same transaction.
Retry Behavior
If your endpoint fails to respond successfully, IIMMPACT retries transaction callbacks up to 3 times with a 60-second delay between attempts.
| Setting | Value |
|---|---|
| Timeout | 30 seconds per request |
| Retry limit | 3 retries |
| Retry delay | 60 seconds between attempts |
| Response | Retried? | Reason |
|---|---|---|
5xx server error | Yes | Transient failure |
408 request timeout | Yes | Transient failure |
429 too many requests | Yes | Rate limited |
| Connection error / DNS failure | Yes | Network issue |
4xx except 408 and 429 | No | Permanent failure |
Permanent Failures
4xx responses, except 408 and 429, are treated as permanent failures and are not retried. Ensure your endpoint returns 2xx after accepting a valid callback.
