How to create a direct top-up order
direct_top_up products credit a buyer account (player ID, phone, etc.) — no gift card codes are returned. This guide covers validate → purchase → poll until complete.
Prerequisites
- Load the SKU — confirm
product_typeisdirect_top_upand readrequired_fields. - Check availability — same
item_codeandquantity. - Validate fields (recommended) — confirm buyer inputs before payment.
Step 1: Create the order
Endpoint: POST https://api.cardpluspay.com/v1/orders
Body (JSON):
item_code(required)quantity(optional, default 1)fields(required fordirect_top_up) — Same object you validated; keys must match catalogrequired_fields[].key.email(optional)
Header: Idempotency-Key — One stable UUID (or your own stable string) per purchase attempt. Retries after timeout must reuse the same key and same body including fields. Use a new key when the buyer changes account details.
Example request
curl -X POST "https://api.cardpluspay.com/v1/orders" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"item_code": "PUBG-60UC-TOPUP-XXXX",
"quantity": 1,
"fields": {
"player_id": "5123456789"
}
}'
Set your HTTP client timeout to at least 90 seconds (180 seconds is safer for some SKUs). A client timeout does not mean the order failed — see order status & polling.
Step 2: Interpret the response
Completed in the same response
{
"success": true,
"message": "Order completed successfully",
"data": {
"order_id": 456,
"order_no": "ORD-2026-042",
"status": "completed",
"state": "completed",
"amount": "0.87",
"quantity": 1,
"codes": [],
"delivery": {
"mode": "direct_top_up",
"status": "completed"
}
}
}
- codes — Always empty (or omitted) for direct top-up. Success is
delivery.status = completedorstatus = completed. - delivery — Present on direct top-up orders:
modeisdirect_top_up;statusiscompleted,pending, orfailed.
Still processing (pending)
{
"success": true,
"message": "Order is being processed",
"data": {
"order_id": 457,
"order_no": "ORD-2026-043",
"status": "pending",
"state": "pending",
"amount": "0.87",
"quantity": 1,
"codes": [],
"delivery": {
"mode": "direct_top_up",
"status": "pending"
}
}
}
This is success, not failure. Your API wallet has been debited. Do not create a duplicate order. Poll GET /orders/{order_id} until status and delivery.status become completed or failed. See order status & polling.
Terminal failure
When fulfillment cannot complete, you may receive HTTP 400 with data.order_id and data.order_no for support. If you already have an order_id, call GET /orders/{id} before treating the purchase as final — the order may still be pending.
Error handling
- 422 —
missing_fields,invalid_fields— Fix thefieldsobject before retrying with a new Idempotency-Key. - 400 —
invalid_quantity,out_of_stock— Same as voucher orders; wallet not debited for stock failures. - 409 —
idempotency_conflict— Same key with a different body, or the original order is still processing. Whendata.order_idis present, callGET /orders/{id}instead of starting a new purchase. - 501 —
not_supported— SKU is not yet available for API purchase. - 402 — Insufficient API wallet balance.
Idempotency and fields
The idempotency scope includes item_code, quantity, and normalized fields. Changing the player ID (or any required field) is a new purchase — use a new Idempotency-Key.
← Validate fields · Integration Guide · Order status & polling →