1. Prerequisites — credentials you need

1. สิ่งที่ต้องเตรียม — credentials

Before you can call any endpoint you need three values issued by your payment gateway admin, plus the API base URL.

ก่อนเริ่มเรียก API คุณต้องมีค่า 3 อย่างจาก Payment gateway admin พร้อม API base URL อีก 1 ค่า

Item Description รายการ คำอธิบาย
API base URL The HTTPS endpoint your requests will hit, e.g. https://<your-api-domain>. The payment gateway admin will provide this value when you sign up. API base URL URL ปลายทางที่จะเรียก เช่น https://<your-api-domain> — Payment gateway admin จะเป็นผู้แจ้งให้คุณทราบตอนสมัครใช้บริการ
merchant_id Identifier of your merchant account. merchant_id รหัส merchant ของคุณ
token API token used for authentication. Sent in the request body of every call. token API token ใช้ยืนยันตัวตน — ส่งไปใน request body ทุกครั้ง
secret Secret key used to sign requests with HMAC-SHA256 and to verify webhook callbacks. Keep it server-side only. secret Secret key สำหรับเซ็น HMAC-SHA256 ของ request และตรวจ signature ของ webhook callback ต้องเก็บไว้ฝั่ง server เท่านั้น
⚠️ Never expose your secret
⚠️ ห้ามเปิดเผย secret

The secret must never appear in client-side code (browser, mobile app), public repositories, log files, or screenshots. If it leaks, request rotation from your payment gateway admin immediately.

ห้ามให้ secret ปรากฏใน client-side code (browser, mobile app) repository สาธารณะ ไฟล์ log หรือ screenshot — ถ้าหลุดให้แจ้ง Payment gateway admin ขอ rotate ใหม่ทันที

2. Base URL

2. Base URL

All endpoints in this documentation are written against the placeholder https://<your-api-domain>. Replace it with the real domain your payment gateway admin gave you.

ทุก endpoint ในเอกสารนี้ใช้ https://<your-api-domain> เป็น placeholder คุณต้องเปลี่ยนเป็น domain จริงที่ Payment gateway admin แจ้งให้คุณตอนใช้งานจริง

Example
POST https://<your-api-domain>/balance
POST https://<your-api-domain>/payment/create
POST https://<your-api-domain>/withdraw/create
Always use HTTPS
ต้องใช้ HTTPS เสมอ

Plain HTTP will be rejected. TLS is required to protect your token and signature.

การเรียกผ่าน HTTP ธรรมดาจะถูกปฏิเสธ — ต้องใช้ TLS เพื่อป้องกัน token และ signature

3. Request rules

3. กติกาการเรียก API

  • Method must be POST for every endpoint (except GET /health).
  • ทุก endpoint ใช้ POST เท่านั้น (ยกเว้น GET /health)
  • Header Content-Type: application/json is required.
  • ต้องส่ง header Content-Type: application/json
  • Header X-SIGNATURE must contain the HMAC-SHA256 of the raw request body using your secret.
  • ต้องส่ง header X-SIGNATURE เป็น HMAC-SHA256 ของ raw request body โดยใช้ secret ของคุณ
  • Body must include merchant_id, token, and time on every authenticated call.
  • Body ต้องมี merchant_id, token, และ time ทุกครั้ง (ยกเว้น health)

4. Typical payment (deposit) flow

4. Flow การฝากเงิน

From order creation through customer payment to webhook delivery.

ตั้งแต่สร้างคำสั่งฝาก ลูกค้าโอนเงิน จนถึง webhook กลับ

sequenceDiagram actor Customer participant Merchant participant PG as Payment Gateway participant Bank autonumber Customer->>Merchant: Request topup Merchant->>PG: Create payment order (with notify_url) PG-->>Merchant: Return QR code or account number Merchant-->>Customer: Show QR code or account number Customer->>Bank: Pay autonumber off PG<<->>Bank: Syncs bank statements autonumber 6 PG->>Merchant: Callback payment completed Merchant-->>PG: HTTP 200 ack Merchant-->>Customer: Credit topup success
  • Create order — call /payment/create with your merchant_order_id, amount, customer bank info, and a notify_url.
  • สร้างคำสั่ง — เรียก /payment/create พร้อมส่ง merchant_order_id, amount, ข้อมูลธนาคารลูกค้า และ notify_url
  • Show payment instruction — display the returned QR code or transfer details to your customer. Note the transfer_amount may be slightly higher than amount for slot uniqueness.
  • แสดงให้ลูกค้า — โชว์ QR หรือข้อมูลโอนเงินให้ลูกค้า — สังเกตว่า transfer_amount อาจมากกว่า amount เล็กน้อยเพื่อแยก slot
  • Wait for callback — when the customer pays, our system POSTs a callback to your notify_url. Always verify the X-Signature header.
  • รอ callback — เมื่อลูกค้าโอนสำเร็จ ระบบจะ POST callback ไปที่ notify_urlต้องตรวจสอบ header X-Signature เสมอ
  • Acknowledge — respond with HTTP 200 to confirm receipt. Anything else triggers a retry (up to 5 attempts, 60s apart).
  • Acknowledge — ตอบ HTTP 200 เพื่อยืนยันว่ารับได้แล้ว ถ้าตอบเป็นค่าอื่นระบบจะ retry (สูงสุด 5 ครั้ง ห่างละ 60 วินาที)
  • Optionally poll — if you don't receive a callback, you can call /payment/query to check status.
  • Poll สถานะ (ทางเลือก) — ถ้ายังไม่ได้ callback คุณเรียก /payment/query เพื่อตรวจสอบได้

5. Typical withdrawal (payout) flow

5. Flow การถอนเงิน

This flow pays out from your merchant balance to an end customer's bank account — e.g. a player cashing out winnings. To withdraw your own merchant balance to your company's bank account instead (periodic settlement), see /thb-settlement/create.

Flow นี้คือการจ่ายเงินจาก merchant balance ไปยังบัญชีของ ลูกค้าปลายทาง — เช่น ลูกค้าถอนเงิน. ถ้าต้องการถอน merchant balance ของคุณ เข้าบัญชี บริษัทตัวเอง (settle เป็นรอบ) ให้ดู /thb-settlement/create

sequenceDiagram actor Customer participant Merchant participant PG as Payment Gateway participant Bank autonumber Customer->>Merchant: Withdraw Merchant->>PG: Create withdraw order (with notify_url) PG-->>Merchant: {platform_order_id, status:'open'} Note over PG: Hold amount + fee from balance (10-min hold) PG->>Bank: Initiate transfer to destination account Bank-->>PG: Confirm (success or fail) PG->>Merchant: Callback withdraw completed (SUCCESS or FAIL) Merchant-->>PG: HTTP 200 ack
  • Create payout — call /withdraw/create with destination bank, account, amount, and notify_url. The order is created with status: 'open' and your balance is placed on a 10-minute hold.
  • สร้างคำสั่งถอน — เรียก /withdraw/create พร้อมข้อมูลธนาคาร, บัญชี, จำนวนเงิน และ notify_url — ระบบจะสร้างคำสั่งสถานะ open และ hold ยอดเงินไว้ 10 นาที
  • Wait for callback — when the payout completes (or fails) we POST a callback to your notify_url. The status field will be SUCCESS or FAIL.
  • รอ callback — เมื่อถอนสำเร็จหรือไม่สำเร็จ ระบบจะ POST callback ไปที่ notify_url โดย status จะเป็น SUCCESS หรือ FAIL
  • Acknowledge with HTTP 200. Same retry rules as payment callback.
  • ตอบ HTTP 200 — กฎการ retry เหมือน Payment callback
Duplicate prevention
การกัน duplicate

Two consecutive withdraw calls with the same bank + account_no + amount within a 3-minute window are blocked as duplicates (when enabled by your account). Use unique merchant_order_id and your own idempotency to be safe.

ถ้าเรียก /withdraw/create ด้วย bank + account_no + amount เดียวกัน ภายใน 3 นาที จะถูกบล็อกเป็น duplicate (ถ้าตั้งค่าเปิดใช้งานสำหรับบัญชีคุณ) ฝั่งคุณควร gen merchant_order_id ไม่ซ้ำและทำ idempotency เองเพิ่มอีกชั้น

6. Quick test — call /balance

6. ทดสอบเร็ว ๆ — เรียก /balance

Once you have your credentials, the simplest end-to-end test is to call /balance. Replace YOUR_* placeholders with your real values, run the script, and you should see a JSON response with your balance.

พอได้ credentials ครบแล้ว วิธีทดสอบที่ง่ายสุดคือเรียก /balance แทนค่า YOUR_* ด้วยค่าจริงของคุณ รัน script แล้วจะได้ response JSON ที่มียอดเงิน

TIME=$(date +%s)
BODY="{\"merchant_id\":\"YOUR_MERCHANT_ID\",\"token\":\"YOUR_TOKEN\",\"time\":$TIME}"
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "YOUR_SECRET" | sed 's/^.* //')

curl -X POST https://<your-api-domain>/balance \
  -H "Content-Type: application/json" \
  -H "X-SIGNATURE: $SIG" \
  -d "$BODY"
import crypto from 'node:crypto';

const BASE   = 'https://<your-api-domain>';
const MID    = 'YOUR_MERCHANT_ID';
const TOKEN  = 'YOUR_TOKEN';
const SECRET = 'YOUR_SECRET';

const body = JSON.stringify({ merchant_id: MID, token: TOKEN });
const sig  = crypto.createHmac('sha256', SECRET).update(body).digest('hex');

const r = await fetch(`${BASE}/balance`, {
  method:  'POST',
  headers: { 'Content-Type': 'application/json', 'X-SIGNATURE': sig },
  body
});
console.log(await r.json());
<?php
$base   = 'https://<your-api-domain>';
$mid    = 'YOUR_MERCHANT_ID';
$token  = 'YOUR_TOKEN';
$secret = 'YOUR_SECRET';

$body = json_encode(['merchant_id' => $mid, 'token' => $token, 'time' => time()],
                    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$sig  = hash_hmac('sha256', $body, $secret);

$ch = curl_init("$base/balance");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST           => true,
  CURLOPT_POSTFIELDS     => $body,
  CURLOPT_HTTPHEADER     => ['Content-Type: application/json', "X-SIGNATURE: $sig"],
]);
echo curl_exec($ch);

Expected response

Response ที่คาดหวัง

JSON
{
  "code":    200,
  "message": "Success",
  "data":    {
    "balance":          1000.00,
    "freeze_balance":   0.00,
    "unsettle_balance": 0.00
  },
  "success": true
}

If you get a 403 with signature-error, double-check that you're signing the exact bytes of your JSON body — not a re-serialized copy. See Authentication & Signature for details.

ถ้าได้ 403 พร้อม error signature-error ให้ตรวจสอบว่า HMAC ที่คำนวณคือของ raw bytes ของ JSON body ตัวเดียวกับที่ส่งจริง ๆ (ไม่ใช่ตัวที่ serialize ใหม่) อ่านเพิ่มที่ Authentication & Signature