Complete API Documentation for Payment Processing
This API provides payment processing capabilities including deposits, withdrawals, balance queries, and order management.
All API requests require authentication using API key and JWT signature.
All requests must include a valid JWT signature for security.
// Example parameters (exclude 'signature' field)
const params = {
merchantId: "your_merchant_id",
transactionId: "unique_transaction_id",
bankAccountNumber: "1234567890",
bankName: "KBANK",
name: "John Doe",
amount: 1000,
callbackUrl: "https://your-domain.com/callback",
type: "QR",
timestamp: 1640995200
};
// Sort parameters alphabetically by key
const sortedParams = {};
Object.keys(params)
.sort()
.forEach(key => {
sortedParams[key] = params[key];
});
// Using jsonwebtoken library
const jwt = require('jsonwebtoken');
const signature = jwt.sign(sortedParams, apiKey, {
algorithm: 'HS256',
noTimestamp: true
});
// Add signature to your parameters
const requestData = {
...params,
signature: signature
};
Core payment processing functionality
Content-Type: application/json and x-api-key.
| Parameter | Type | Required | Description |
|---|---|---|---|
| merchantId | string | Yes | Must match the merchant bound to x-api-key (main_username) |
| transactionId | string | Yes | Your unique reference; rejected if already used for this merchant |
| bankAccountNumber | string | Yes | Customer / payer bank account number |
| bankName | string | Yes | Payer bank code (e.g. KBANK, SCB, BBL) |
| name | string | Yes | Account holder name |
| amount | number | Yes | Requested deposit amount (THB) |
| callbackUrl | string | Yes | Your server URL for status callbacks |
| type | string | Yes | e.g. QR, BANK_TRANSFER |
| signature | string | Yes | JWT (HS256) over the other fields — see /jwt/create |
| timestamp | number | Yes | Unix time; must match the signed payload (seconds or ms, consistent with signing) |
signature. Use POST /api/v1/jwt/create with a params object that matches the body fields you will send.
{
"merchantId": "testmerchant",
"transactionId": "MERCHANT20241009001",
"bankAccountNumber": "9876543210",
"bankName": "SCB",
"name": "John Doe",
"amount": 1000,
"callbackUrl": "https://yourdomain.com/api/payment/deposit-callback",
"type": "QR",
"timestamp": 1728470400000,
"signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
HTTP 200. Envelope: status is "success", message e.g. "Create Success", and data as below.
Important: referenceId is the internal order id (DP…) for payment links and order query. amount and depositAmount are the exact transfer amount the customer must pay (may differ from the requested amount for uniqueness). qrcode is the raw PromptPay payload string, or null if the platform account has no PromptPay id. url is the hosted payment page (QRPAYPLUS_URL?ref=…), not payment_url.
{
"status": "success",
"message": "Create Success",
"data": {
"merchantId": "testmerchant",
"referenceId": "DP1640995200ABC123",
"transactionId": "MERCHANT20241009001",
"status": "pending",
"amount": 999.99,
"depositAmount": 999.99,
"qrcode": "0002010102123853000066...",
"url": "https://pay.example.com/?ref=DP1640995200ABC123",
"bankAccountNumber": "1234567890",
"bankAccountName": "Platform Bank Account",
"bankName": "KBANK",
"promptpayNumber": "0812345678",
"expireDate": "2024-01-01T12:05:00.000Z",
"platformBankId": "550e8400-e29b-41d4-a716-446655440000",
"is_api": true,
"customerData": {
"bankAccountNumber": "9876543210",
"bankName": "SCB",
"name": "John Doe"
}
}
}
Most errors return status: "error", a message, and a numeric code (body may still be HTTP 200). Some handlers return only code and message without status.
{
"status": "error",
"message": "Invalid signature",
"code": 400
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_order_no | string | Yes | Unique order identifier |
| amount | number | Yes | Amount in THB |
| bank_code | string | Yes | Bank code (e.g., KBANK, SCB) |
| account_no | string | Yes | Bank account number |
| account_name | string | Yes | Account holder name |
| callback_url | string | Yes | Webhook callback URL |
| timestamp | string | Yes | Unix timestamp |
| signature | string | Yes | JWT signature |
{
"code": 200,
"message": "Success",
"data": {
"order_no": "WD1640995200XYZ789",
"agent_order_no": "unique_order_id",
"amount": 1000,
"fee": 15,
"transfer_amount": 985,
"status": "pending"
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| timestamp | number | Yes | Unix timestamp |
| signature | string | Yes | JWT signature |
{
"code": 200,
"message": "Success",
"data": {
"balance": 50000,
"currency": "THB"
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| order_no | string | No | Platform order number |
| agent_order_no | string | No | Agent order number |
| timestamp | number | Yes | Unix timestamp |
| signature | string | Yes | JWT signature |
{
"code": 200,
"message": "Success",
"data": {
"order_no": "DP1640995200ABC123",
"agent_order_no": "unique_transaction_id",
"status": "completed",
"amount": 1000,
"fee": 5,
"actual_amount": 995,
"created_at": "2024-01-01T12:00:00.000Z",
"completed_at": "2024-01-01T12:03:00.000Z"
}
}
Helper endpoints for common operations
| Parameter | Type | Required | Description |
|---|---|---|---|
| params | object | Yes | Parameters to sign (excluding 'signature') |
| api_key | string | No | API key (uses header if not provided) |
{
"code": 200,
"message": "Success",
"data": {
"signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"algorithm": "HS256",
"payload": {
"amount": 1000,
"bankAccountNumber": "9876543210",
"bankName": "SCB",
"callbackUrl": "https://yourdomain.com/callback",
"merchantId": "testmerchant",
"name": "John Doe",
"timestamp": 1728470400000,
"transactionId": "MERCHANT20241009001",
"type": "QR"
}
}
}
{
"code": 200,
"message": "Success",
"data": {
"banks": [
{
"code": "KBANK",
"name": "Kasikorn Bank",
"name_th": "ธนาคารกสิกรไทย",
"active": true
},
{
"code": "SCB",
"name": "Siam Commercial Bank",
"name_th": "ธนาคารไทยพาณิชย์",
"active": true
}
]
}
}
{
"code": 200,
"message": "OK",
"data": {
"status": "healthy",
"timestamp": "2024-01-01T12:00:00.000Z",
"uptime": 3600.5
}
}
Our server will send HTTP POST requests to your callback URLs when payment status changes.
The status field in the callback body depends on type (deposit vs withdrawal). Use the tables below to interpret callback payloads.
Deposit callbacks use a single terminal status when funds are confirmed:
| Status | Meaning |
|---|---|
completed |
Deposit successful; payment is complete. |
Withdrawal callbacks may use one of the following values during the withdrawal lifecycle:
| Status | Meaning |
|---|---|
waiting |
Waiting to be processed. |
processing |
Withdrawal order is being processed. |
created |
Withdrawal order was created and is waiting to enter processing. |
in batch |
Withdrawal order is queued in a withdrawal batch before payout. |
completed |
Withdrawal completed successfully (payout done). |
cancelled |
Withdrawal was cancelled; it will not be retried. |
failed |
Withdrawal failed; it will not be retried. |
Sent when a deposit is matched and confirmed (type is always deposit, status is completed).
POST https://your-domain.com/callback
Content-Type: application/json
{
"order_no": "DP1640995200ABC123",
"agent_order_no": "unique_transaction_id",
"status": "completed",
"amount": 1000,
"transfer_amount": 995,
"actual_amount": 995,
"fee": 5,
"type": "deposit",
"trans_date": "2026-07-10T05:12:30.000Z",
"to_account_name": "สมชาย ใจดี",
"timestamp": 1640995380,
"signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
| Parameter | Type | Description |
|---|---|---|
| order_no | string | Platform order number |
| agent_order_no | string | Your transaction ID (transactionId from create deposit) |
| status | string | Always completed for deposit callbacks — see Deposit callback status |
| amount | number | Original deposit amount |
| transfer_amount | number | Net amount after fee |
| actual_amount | number | Actual matched / received amount |
| fee | number | Processing fee |
| type | string | Always deposit |
| trans_date | string / datetime | Transaction datetime from bank matching |
| to_account_name | string | Depositor / account name from matching |
| timestamp | number | Unix timestamp (seconds) when callback was generated |
| signature | string | JWT signature for verification (signed with your API key) |
Sent when withdrawal status changes (type is always withdrawal). Common statuses: completed, failed, cancelled — see status table above.
POST https://your-domain.com/callback
Content-Type: application/json
{
"order_no": "WD1640995200XYZ789",
"agent_order_no": "unique_withdrawal_id",
"status": "completed",
"amount": 1000,
"transfer_amount": 995,
"actual_amount": 995,
"fee": 5,
"type": "withdrawal",
"trans_date": "2026-07-10 12:30:00",
"to_account_name": "สมชาย ใจดี",
"timestamp": 1640995380,
"signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
| Parameter | Type | Description |
|---|---|---|
| order_no | string | Platform order number |
| agent_order_no | string | Your transaction ID (order_id from create withdrawal) |
| status | string | Withdrawal status — see Withdraw callback status |
| amount | number | Original withdrawal amount |
| transfer_amount | number | Net amount after fee |
| actual_amount | number | Actual payout amount |
| fee | number | Processing fee |
| type | string | Always withdrawal |
| trans_date | string / datetime | Transaction datetime (order created time or callback time) |
| to_account_name | string | Payee account name |
| timestamp | number | Unix timestamp (seconds) when callback was generated |
| signature | string | JWT signature for verification (signed with your API key) |
// Your server should respond with:
{
"code": 200,
"message": "Success"
}
Common error responses and their meanings
| Code | Message | Description |
|---|---|---|
| 200 | Success | Request completed successfully |
| 400 | Invalid signature | JWT signature verification failed |
| 400 | transactionId already exists | Transaction ID is already used |
| 401 | Invalid API key | API key is invalid or missing |
| 403 | IP not in whitelist | Your IP address is not authorized |
| 403 | merchantId does not match API key | Merchant ID doesn't match the API key |
| 500 | Internal server error | Server encountered an unexpected error |