Appearance
Step 5: Track Results
Use webhooks for updates and these reads for browser returns, missing notifications, or on-demand checks.
Request headers
All three GET endpoints use these headers. Sign an empty body.
| Field | Type | Required | Description |
|---|---|---|---|
X-Api-Key | string | Yes | Your API key; keep it on your backend. |
X-Timestamp | string | Yes | Current Unix time in seconds; within five minutes of server time. |
X-Nonce | string | Yes | Fresh identifier for every request, including retries. |
X-Signature | string | Yes | v1= followed by the request's HMAC signature. |
Follow API Key Authentication. Sign the exact body, or an empty body for bodyless requests, and the sorted query when present.
Get order detail
http
GET https://api.iimmpact.com/v2/orders/{order_id}Path fields
| Field | Type | Required | Description |
|---|---|---|---|
order_id | string | Yes | Order ID from creation. No query fields. |
Request example
bash
curl "https://api.iimmpact.com/v2/orders/$ORDER_ID" \
--header "X-Api-Key: $API_KEY" \
--header "X-Timestamp: $TIMESTAMP" \
--header "X-Nonce: $NONCE" \
--header "X-Signature: v1=$SIGNATURE"Response fields
Fields below are inside data.
Order detail includes one item per purchased unit, using the same result fields as order webhook data. No separate per-unit detail request is needed. A webhook is a snapshot at its event time; a fresh GET can show later order or refund progress.
| Field | Type | Description |
|---|---|---|
order_id | string | Order identifier. |
external_reference | string | Your order reference. |
status | string | payment_pending, payment_processing, transaction_processing, completed, or expired. |
currency | string | MYR. |
items_subtotal | string | Frozen item sale subtotal. |
items | array | One row per unit purchased; see item fields below. |
refunds | array | Refund summaries for this order. Each entry contains payment_id, status, and the total amount for that payment and status; empty when none exist. |
metadata | object or null | null unless supplied on order creation. |
created_at | string | UTC order creation time. |
updated_at | string | UTC time of the latest public change, including fulfillment/refund changes. |
expires_at | string | UTC cutoff for admitting new payments, 24 hours after order creation. Existing attempts, settlement, fulfillment, and refunds continue afterward. |
Item fields
Each item is one unit of a purchased product. An order with quantity: 3 produces three rows. Rows exist from order creation; fulfillment fields appear once dispatch starts.
A successful or failed unit does not change afterward. Order results omit unit_price; this does not change the frozen sale subtotal, payment total or refund amounts.
| Field | Type | Description |
|---|---|---|
product | string | Product code. |
product_name | string | Product display name. |
account | string | Recipient's account number or identifier; may be "" for an account-optional product. |
amount | string | Requested topup face value for this unit. |
status | string | awaiting_payment, accepted, processing, successful, or failed. |
refid | string or null | Fulfillment reference; null until dispatch. |
status_code | integer | Transaction result code, such as 20 for success; present after dispatch. |
sn | string | Serial number, when the product returns one. |
pin | string | Redemption PIN, when the product returns one. |
expiry | string | Provider expiry text, when the product returns one; not necessarily RFC3339. |
cost | string | Recorded wholesale cost, when available. Preserves up to four decimal places; never substitute the requested face value or sale price. |
remarks | string | Result text, when the provider returns it. |
note | string | Instructions, when the product returns them. |
voucherlink | string | Redemption URL, when the product returns one. |
timestamp | string | UTC time this unit's recorded state/result last changed. Not the supplier's transaction-entry time. Reads and retries do not advance it. |
Unavailable result strings normally use "". Where a definitive rejection has no downstream transaction, downstream details may be null. An unknown result code or cost is not reported as zero. Hosted checkout responses omit serial numbers, PINs, voucher links and wholesale cost.
Order detail has no payer identity, payment fees, or redirect destination. Authorize customer access before exposing it.
Response example — 200
json
{
"data": {
"order_id": "ord_example",
"external_reference": "ORD-00042",
"status": "completed",
"currency": "MYR",
"items_subtotal": "100.00",
"items": [
{
"product": "TNB",
"product_name": "Tenaga Nasional Berhad",
"account": "220012345679",
"amount": "60.00",
"status": "successful",
"status_code": 20,
"refid": "ORD-00042-1",
"cost": "58.1234",
"timestamp": "2026-09-14T02:10:43.000Z"
},
{
"product": "TNB",
"product_name": "Tenaga Nasional Berhad",
"account": "220012345678",
"amount": "40.00",
"status": "failed",
"status_code": 52,
"refid": "ORD-00042-2",
"cost": "39.1250",
"remarks": "Invalid Account No",
"timestamp": "2026-09-14T02:10:44.000Z"
}
],
"refunds": [
{
"payment_id": "pay_example",
"amount": "40.00",
"status": "successful"
}
],
"metadata": null,
"created_at": "2026-09-14T02:00:00.000Z",
"updated_at": "2026-09-14T02:18:00.000Z",
"expires_at": "2026-09-15T02:00:00.000Z"
}
}Errors
| HTTP | Code | Action |
|---|---|---|
| 404 | order_not_found | Check the order ID; foreign orders also return 404. |
See shared errors.
Order states
| Status | Meaning |
|---|---|
payment_pending | Unpaid and awaiting payment before the order's expires_at cutoff. |
payment_processing | Collection or cancellation is unresolved. |
transaction_processing | Winning collection verified; fulfillment is in progress. |
completed | All units have final results, including any failures. Refunds may still be pending. |
expired | New-payment cutoff passed with no winner or unresolved attempt. Continue reconciliation of known late verified collections. |
Get payment detail
http
GET https://api.iimmpact.com/v2/payments/{payment_id}Path fields
| Field | Type | Required | Description |
|---|---|---|---|
payment_id | string | Yes | Payment ID retained from creation, browser return, or events. No query fields. |
Request example
bash
curl "https://api.iimmpact.com/v2/payments/$PAYMENT_ID" \
--header "X-Api-Key: $API_KEY" \
--header "X-Timestamp: $TIMESTAMP" \
--header "X-Nonce: $NONCE" \
--header "X-Signature: v1=$SIGNATURE"Response fields
Returns the payment schema inside data, with current status and action. Refunds are read from the order. A failed payment still returns HTTP 200.
Response example — 200
json
{
"data": {
"payment_id": "pay_example",
"order_id": "ord_example",
"external_reference": "ORD-00042",
"customer_external_id": "CUS-1042",
"transaction_refids": [],
"status": "processing",
"currency": "MYR",
"payment_method_code": "CARD",
"customer_fee_percent": "50.00",
"fee": {
"type": "percentage",
"value": "1.70"
},
"totals": {
"items_subtotal": "100.00",
"fee": {
"total": "1.70",
"customer": "0.85",
"merchant": "0.85"
},
"payment_total": "100.85"
},
"action": {
"type": "redirect",
"url": "https://payments.example/checkout/session",
"method": "GET"
},
"created_at": "2026-09-14T02:05:00.000Z",
"updated_at": "2026-09-14T02:05:00.000Z",
"expires_at": "2026-09-14T02:35:00.000Z"
}
}For a failed payment, action is omitted and a failure object appears inside data (excerpt):
json
{
"status": "failed",
"failure": {
"code": "AUTHENTICATION_FAILED"
},
"updated_at": "2026-09-14T02:06:00.000Z"
}Errors
| HTTP | Code | Action |
|---|---|---|
| 404 | payment_not_found | Check the payment ID; foreign payments also return 404. |
See shared errors.
Payment failure codes
failure.code preserves the provider or system code. Examples include:
| Code | Meaning |
|---|---|
AUTHENTICATION_FAILED | Customer authentication failed. |
provider_validation_error | The provider rejected the submitted details. |
TIMEOUT_ERROR, PARTNER_TIMEOUT_ERROR | Provider-reported timeout on a confirmed failed payment request. |
SERVER_ERROR, ISSUER_UNAVAILABLE, CHANNEL_UNAVAILABLE | Provider-reported service or channel failure on a confirmed failed payment request. |
payment_expired | The payment was finalized as expired. |
payment_preparation_interrupted | Payment preparation was finalized without submitting a collection. |
This is not an exhaustive provider-code list. Use the payment's status to decide whether an attempt is final, not a code alone. An HTTP timeout, malformed response or uncertain outcome does not prove failure. Once confirmed failed, the attempt stops status reconciliation; an eligible replacement requires a new key and payment ID on the same order.
Fulfillment is separate: an accepted or processing unit keeps its existing reference while being checked. A confirmed successful or failed unit stops requerying. Retry exhaustion does not manufacture a failed unit or refund.
List orders
http
GET https://api.iimmpact.com/v2/ordersQuery fields
| Field | Type | Required | Description |
|---|---|---|---|
external_reference | string | No | Exact order reference. |
status | string | No | One order state. |
created_from | string | No | Inclusive RFC3339 start. |
created_to | string | No | Exclusive RFC3339 end, later than start. |
limit | integer | No | 1–100; defaults to 20. |
cursor | string | No | Opaque token; send data.next_cursor from the previous response to get the next page. |
Date ranges are at most 90 days; one bound implies a 90-day range. With neither bound, all dates are eligible. Results are newest first by creation time then order ID. A cursor is bound to the request's filters: keep them unchanged when paging, though limit may differ. Percent-encode values, including + in timezone offsets.
Unfiltered history includes all orders in your account. Keep customer-to-order ownership in your backend and authorize customer-facing reads; the payer on a payment does not establish order ownership.
Request example
bash
curl 'https://api.iimmpact.com/v2/orders?external_reference=ORD-00042&limit=20' \
--header "X-Api-Key: $API_KEY" \
--header "X-Timestamp: $TIMESTAMP" \
--header "X-Nonce: $NONCE" \
--header "X-Signature: v1=$SIGNATURE"Response fields
| Field | Type | Description |
|---|---|---|
data.items | array | Order summaries; empty when none match. This list does not contain per-unit fulfillment results. |
items[].order_id | string | Order identifier. |
items[].external_reference | string | Your order reference. |
items[].status | string | Current order state. |
items[].items_subtotal | string | Frozen item sale subtotal. |
items[].created_at | string | RFC3339 creation time. |
items[].updated_at | string | RFC3339 latest public order change. |
data.next_cursor | string or null | Next page cursor; null on the final page. |
Response example — 200
json
{
"data": {
"items": [
{
"order_id": "ord_example",
"external_reference": "ORD-00042",
"status": "completed",
"items_subtotal": "100.00",
"created_at": "2026-09-14T02:00:00.000Z",
"updated_at": "2026-09-14T02:18:00.000Z"
}
],
"next_cursor": null
}
}Errors
| HTTP | Code | Action |
|---|---|---|
| 400 | validation_error | Correct filters or date bounds; see validation details. |
| 400 | invalid_cursor | The cursor does not match these filters; restart pagination without it. |
See shared errors. Retry reads with bounded backoff and fresh HMAC headers; routine polling is not required.

