Developers

Integrate in an afternoon

Signed REST endpoints, retried webhooks, and docs your AI assistant can read whole. Production endpoints are issued at onboarding.

Create a payment with FLEX

Sign the JSON body with HMAC-SHA256 using your merchant secret, send it in X-Signature, and get back a hosted payment_url.

curl -X POST https://api.example.com/payment-flex/create \
  -H "Content-Type: application/json" \
  -H "X-Signature: $SIGNATURE" \
  -d '{
    "merchant_id": "AA12345678",
    "token": "YOUR_AUTH_TOKEN",
    "time": 1785312000,
    "merchant_order_id": "ORDER-2026-000123",
    "amount": "1000.00",
    "bank": "KBANK",
    "account_name": "John Doe",
    "account_no": "1234567890",
    "notify_url": "https://merchant.com/webhooks/payment",
    "redirect_url": "https://merchant.com/thank-you",
    "payment_theme": "halo"
  }'
// response
{
  "success": 200,
  "data": {
    "platform_order_id": "THBP20260806104512A7K2M9X4",
    "merchant_order_id": "ORDER-2026-000123",
    "payment_method": "TRANSFER",
    "payment_url": "https://pay.example.com/THBP20260806104512A7K2M9X4/9f2c...e81a"
  }
}
Code samples use api.example.com — your production endpoint is issued at onboarding.

Handle the webhook — verified & idempotent

We retry until your server answers HTTP 200. status: "PAID" is always authoritative.

// payload we send you
{
  "merchant_id": "AA12345678",
  "platform_order_id":
    "THBP20260806104512A7K2M9X4",
  "client_order_id":
    "ORDER-2026-000123",
  "mode": "PAYMENT",
  "amount": "1000.00",
  "status": "PAID",
  "timestamp": 1785312245
}
app.post('/webhooks/payment', async (req, res) => {
  const raw = req.body.toString('utf8');

  // 1) verify signature first, always
  const expected = crypto.createHmac('sha256', process.env.WW_SECRET)
                         .update(raw).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(expected),
      Buffer.from(req.get('X-Signature') || ''))) {
    return res.sendStatus(401);
  }

  const e = JSON.parse(raw);

  // 2) idempotent — we retry until you answer 200
  if (e.mode === 'PAYMENT' && e.status === 'PAID') {
    await creditOnce(e.platform_order_id,
                     e.client_order_id, e.amount);
  }

  // 3) answer 200 fast, do heavy work async
  res.sendStatus(200);
});

API surface

EndpointPurpose
/payment-flex/createCreate deposit order (recommended)
/payment/queryCheck deposit status
/payment/cancelCancel an order
/withdraw/createCreate payout
/withdraw/queryCheck payout status
/usdt-withdraw/createUSDT settlement (TRC20)
/slip/uploadSubmit transfer slip
/balanceCheck balance
/blacklist · /whitelistManage blocked/allowed accounts
/records/*Payments, withdraws, statements, summary report

Error codes

CodeMeaning
200Success
403Authentication failed — merchant_id / token / signature
409Customer has a pending order (returns pending_order_id)
422Invalid payload format
429Rate limit exceeded
500Other errors, e.g. "amount must be greater than 20"
Sandbox

Full sandbox with mock success / failure endpoints — available on merchant onboarding.

Feed the whole API to your AI

One file, the full spec — English and Thai. Paste it into ChatGPT, Claude, Cursor, or Copilot and let it write your integration.