Signed REST endpoints, retried webhooks, and docs your AI assistant can read whole. Production endpoints are issued at onboarding.
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"
}'
import crypto from 'node:crypto';
const payload = JSON.stringify({
merchant_id: 'AA12345678',
token: process.env.WW_TOKEN,
time: Math.floor(Date.now() / 1000),
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',
payment_theme: 'halo',
});
const signature = crypto.createHmac('sha256', process.env.WW_SECRET)
.update(payload).digest('hex');
const res = await fetch('https://api.example.com/payment-flex/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Signature': signature },
body: payload,
});
console.log(await res.json());
<?php
$secret = 'YOUR_SECRET_KEY';
$payload = json_encode([
'merchant_id' => 'AA12345678',
'token' => 'YOUR_AUTH_TOKEN',
'time' => time(),
'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',
'payment_theme' => 'halo',
]);
$signature = hash_hmac('sha256', $payload, $secret);
$ch = curl_init('https://api.example.com/payment-flex/create');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Signature: ' . $signature,
],
]);
echo curl_exec($ch);
import hmac, hashlib, json, time, requests
secret = "YOUR_SECRET_KEY"
payload = json.dumps({
"merchant_id": "AA12345678",
"token": "YOUR_AUTH_TOKEN",
"time": int(time.time()),
"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",
"payment_theme": "halo",
}, separators=(",", ":"))
signature = hmac.new(secret.encode(), payload.encode(),
hashlib.sha256).hexdigest()
r = requests.post(
"https://api.example.com/payment-flex/create",
data=payload,
headers={"Content-Type": "application/json",
"X-Signature": signature},
)
print(r.json())
{
"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"
}
}
We retry until your server answers HTTP 200. status: "PAID" is always authoritative.
{
"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);
});
Full sandbox with mock success / failure endpoints — available on merchant onboarding.
One file, the full spec — English and Thai. Paste it into ChatGPT, Claude, Cursor, or Copilot and let it write your integration.