Orders and checkout links

An order is one purchase. Your game server creates it when the player taps buy.

Base URL: https://api.ez2pay.gg

Every request uses your game's API key:

Authorization: Bearer ez2_live_...

Call the API from your server only. Errors are JSON in the form {"error":"CODE"}. See Errors and fixes. Request bodies are limited to 16 KiB.

Create an order

curl -X POST https://api.ez2pay.gg/v1/orders \
  -H "Authorization: Bearer $EZ2PAY_API_KEY" \
  -H "Idempotency-Key: purchase-7f3a9c" \
  -H "Content-Type: application/json" \
  -d '{"sku":"gem_pack_100","buyer":"p_123","customer_email":"[email protected]","return_url":"https://game.example/topup/result"}'
FieldMeaningRules
skuThe SKU code1-100 characters. Must be an active SKU in this game
buyerYour player's ID1-200 characters. This is who you deliver to
customer_emailThe player's email, for the receiptValid email, up to 254 characters. Never returned to AI through MCP
return_urlYour result pageHTTPS, up to 2048 characters, no username or password

There is no price field. EZ2Pay always takes the price from the SKU. Any field not listed here is rejected with 400.

The game must be approved. Otherwise the API answers 409 GAME_APPROVAL_REQUIRED.

Idempotency-Key

This header is required. It stops your server from creating two orders when it retries.

  • Same key and same input: returns the existing order with 200.
  • Same key and changed input: 409 IDEMPOTENCY_CONFLICT.
  • A new purchase always needs a new key.
  • Format: 1-200 printable ASCII characters with no spaces.

The response

A new order answers 201. A replay of the same key answers 200.

{
  "order_id": "ord_00000000-0000-4000-8000-000000000001",
  "sku": "gem_pack_100",
  "buyer": "p_123",
  "status": "CREATED",
  "amount": "100.00",
  "currency": "THB",
  "checkout_url": "https://pay.ez2pay.gg/my-fantasy-town?t=Xk29fQ...",
  "expires_at": "2026-11-09T05:10:00.000Z",
  "paid_at": null,
  "delivered_at": null,
  "paid_channel": null,
  "unlock_at": null,
  "void_reason": null
}
FieldMeaning
order_idord_ followed by a UUID
amountFull retail price the player pays EZ2Pay, as a string with 2 decimals. Not the amount you receive
currencyAlways THB
checkout_urlSend the player here
expires_atWhen the order stops accepting new payments, in UTC
paid_atWhen payment was first confirmed, in UTC. Never changes once set
delivered_atWhen you acknowledged delivery, in UTC
paid_channelpromptpay or card, once paid
unlock_atThe date you can receive payment for this sale, in UTC
void_reasonWhy the order was cancelled, if it was
  1. Send the player to checkout_url.
  2. The checkout page shows your game, the item, the price and Seller: EZ2Pay.
  3. The player pays. PromptPay QR is open now. Card shows "coming soon" until it opens.

An order accepts new payments for 10 minutes. A QR lasts 10 minutes from when it is issued, so a player who starts just before expires_at can still finish. The order shows EXPIRED and then moves to PAID. Treat that webhook as a normal sale.

After expires_at, create a new order with a new Idempotency-Key. Reusing the old key returns the expired order.

return_url is where the player lands afterwards. It is for display only. Arriving there proves nothing, so never deliver goods from it.

Read an order

curl https://api.ez2pay.gg/v1/orders/ord_00000000-0000-4000-8000-000000000001 \
  -H "Authorization: Bearer $EZ2PAY_API_KEY"

Answers the same fields as above. An order that belongs to another game answers 404 ORDER_NOT_FOUND.

Order statuses

StatusMeaning
CREATEDCreated. The player has not started paying
PENDING_PAYMENTPayment issued. Waiting for the player
PAIDPayment confirmed
NOTIFYINGThe webhook is being sent to your server
NOTIFIEDYour server answered 200
DELIVEREDYour server answered 200 and acknowledged delivery
EXPIREDThe payment window ended
NOTIFY_FAILEDEvery webhook attempt failed. The order is still paid. Resend it from the Dashboard
MISMATCHPayment details did not match. The EZ2Pay team reviews it. Never deliver
VOIDEDCancelled by EZ2Pay
FAILEDThe payment could not be created

Only these statuses mean the order is paid: PAID, NOTIFYING, NOTIFIED, NOTIFY_FAILED, DELIVERED.

Cancellations and resending

The API has no endpoint to cancel an order or to resend a webhook. Use the Dashboard: search the order by Order ID or Player ID, resend the notification, or escalate it to EZ2Pay.

Next: Webhooks and delivery