Hyronpay

API Docs

Hyronpay API Documentation

Merchant Integration Handbook

มาตรฐานการเชื่อมต่อ (Production Ready) — contract, endpoint, webhook, และ live testing

Contract ของ Public API คงเดิม: ทีมที่เชื่อมต่ออยู่ก่อนหน้าใช้งานต่อได้โดยไม่ต้องปรับ integration
มาตรฐานใหม่: response ที่มี amount จะมี copy.amount และ/หรือ copy.account_number เพื่อให้ UI ทำปุ่มคัดลอกได้ทันที

Public API Base

https://api.hyronpay.com/api/v1

Webhook Direction

Hyronpay → Your Callback URL (POST)

1) Authentication Matrix

เลือก credential ให้ตรง endpoint

Runtime Key Mode Rule

  • ระบบบังคับ key mode ตาม RUNTIME_ENV อัตโนมัติ (ตรวจตอน auth)
  • ตรวจ runtime ปัจจุบันได้จาก GET /api/v1/payout/signature-settings (runtime.mode)
  • ตรวจว่า key ที่ใช้อยู่เป็นโหมดไหนได้จาก GET /api/v1/profile (authenticated_with_mode)
RuntimeDefault KeyAllowedBlockedNote
productionlivelive + legacytestเปิด test key ได้เฉพาะเมื่อ ALLOW_TEST_KEYS_IN_PRODUCTION=true
developmenttestlive + test + legacy-เหมาะกับ local integration test
CredentialHeaderUsed ForRequirement
Merchant Secret API Key (sk_live_ / sk_test_ / sk_legacy)X-API-Key/api/v1/profile, /api/v1/payment/*, /api/v1/payment/accounts, /api/v1/transactions, /api/v1/balance, /api/v1/balance/line-summary, /api/v1/webhooks, /api/v1/webhook/events, /api/v1/payout/signature-settings, /api/v1/payout/*, /api/v1/withdrawal/*จำเป็น (ใช้สร้าง payment page ได้; ควรเก็บฝั่ง backend merchant เท่านั้น)
Merchant Session (Dashboard)Cookie: connect.sid/api/payment/create-link, /api/payment/recent-linksจำเป็นเมื่อเรียก dashboard API โดยตรง
Payout SignatureIdempotency-Key, X-Signature-Timestamp, X-Signature, X-Signature-Nonce(optional)/api/v1/payout/create, /api/v1/payout/bulk, /api/v1/withdrawal/request/create, /api/v1/withdrawal/request/:requestRef/approve, /api/v1/withdrawal/request/:requestRef/rejectสร้างจาก backend merchant เอง (เปิด signature mode = ต้องมี timestamp + signature)
Webhook Signature (Callback Verify)X-Webhook-Signature, X-Webhook-Event, X-Webhook-Timestamp, X-Webhook-Delivery-Id, X-Webhook-Idempotency-Key, X-Webhook-Id(legacy), X-Webhook-VersionWebhook callback ที่ส่งจาก Hyronpay ไปยังระบบของคุณแนะนำอย่างยิ่ง (verify ทุก callback)

2) Endpoint Catalog

รูปแบบนี้อ้างอิงแนว Postman docs: ระบุ method, path, auth, purpose แบบอ่านจบในหน้าเดียว (รวมทั้ง Public API และ Hosted Checkout flow)

MethodPathAuthPurpose
POST/api/v1/payment/createX-API-Key (secret)สร้างรายการรับชำระ และใช้ transaction.id ไปประกอบ hosted checkout URL ได้
POST/api/payment/create-linkSession (merchant dashboard login)สร้างลิงก์ชำระเงินแบบ hosted checkout สำหรับ dashboard/internal tooling
GET/api/payment/pay/:transactionIdPublic (no auth)ดึงข้อมูลหน้าชำระเงินจริง (QR + บัญชีธนาคาร)
GET/api/v1/profileX-API-Keyดึงข้อมูลร้านค้าและ config พื้นฐานของ key ปัจจุบัน
GET/api/v1/webhooksX-API-Keyดู callback webhook ที่ตั้งอยู่ของ merchant ปัจจุบัน
GET/api/v1/webhook/eventsX-API-Keyดึงรายการ webhook event ที่ระบบรองรับ
GET/api/v1/payment/order/:orderIdX-API-Keyเช็กสถานะรายการจาก orderId
GET/api/v1/withdrawal/requestsX-API-Keyดูคำขอถอนจากสมาชิกของร้านค้า
POST/api/v1/withdrawal/request/createX-API-Key + Signature headersสร้างคำขอถอนจากสมาชิก พร้อมเช็กยอดขั้นต่ำและ balance ร้านค้าทันที
POST/api/v1/withdrawal/request/:requestRef/approveX-API-Key + Signature headersอนุมัติคำขอถอน (ใช้ค่า `request.id` จาก endpoint create) และ reserve balance แบบ atomic ก่อนเข้า payout queue
POST/api/v1/withdrawal/request/:requestRef/rejectX-API-Key + Signature headersปฏิเสธคำขอถอนจากสมาชิก (ใช้ค่า `request.id` จาก endpoint create) ก่อนเข้า payout queue
GET/api/v1/payment/accountsX-API-Keyดึงบัญชีรับฝากที่ active ของระบบ
GET/api/v1/payout/ref/:merchantRefX-API-Keyเช็กสถานะ payout รายตัวจาก merchantRef
POST/api/v1/payout/createX-API-Key + Signature headersสร้างคำสั่งถอน 1 รายการ
POST/api/v1/payout/bulkX-API-Key + Signature headersสร้างคำสั่งถอนหลายรายการ
GET/api/payoutMerchant session (dashboard)ดูรายการถอนเงินของร้านค้า (มี copy.amount/copy.account_number)
GET/api/settlementMerchant session (dashboard)ดูรายการขอถอนเครดิต (มี copy.amount/copy.account_number)
GET/api/admin/payoutsAdmin/Payout operator sessionดูรายการ payout ทั้งระบบ (มี copy.amount/copy.account_number)
GET/api/admin/settlementsAdmin sessionดูรายการ settlement ทั้งระบบ (มี copy.amount/copy.account_number)
GET/api/admin/transactionsAdmin/Payout operator sessionดูรายการรับเงินทั้งระบบ (มี copy.amount)
GET/api/admin/bank-accountsAdmin/Payout operator sessionดูบัญชีธนาคารระบบกลาง (มี copy.account_number)
GET/api/v1/transactionsX-API-Keyดึงรายการธุรกรรมย้อนหลังแบบ paginated
GET/api/v1/balanceX-API-Keyเช็กยอดคงเหลือปัจจุบันของ merchant
GET/api/v1/balance/line-summaryX-API-Keyเช็กยอดรวมทั้งสายงาน (self + downline) ของ merchant ปัจจุบัน
GET/api/v1/payout/signature-settingsX-API-Keyดูกติกา signature ปัจจุบันจากระบบจริง
POST<your-webhook-url>X-Webhook-Signature (+ webhook headers)รับสถานะฝาก/ถอนอัตโนมัติจาก Hyronpay (callback)

3) Create Payment Contract

FieldTypeRequiredDescriptionExample
amountnumberRequiredยอดที่ต้องชำระ (> 0) รองรับทศนิยม 2 ตำแหน่ง100.37
orderIdstringRequiredเลขอ้างอิงฝั่งร้านค้า (ไม่ซ้ำต่อ merchant) - production ต้องส่งทุกครั้งORD-10001
descriptionstringOptionalคำอธิบายรายการTopup
metadata.senderAccountNumberstringRequiredเลขบัญชีผู้โอนแบบเต็ม ต้องมีอย่างน้อย 8 หลัก1673585481
metadata.senderAccountLast4stringOptionalเลขท้ายบัญชีผู้โอน 4 หลัก (ถ้าไม่ส่ง ระบบจะเติมให้อัตโนมัติจาก senderAccountNumber)5481
metadata.senderBankCodestringRequiredรหัสธนาคารผู้โอน เช่น SCB, KBANK, KTB, GSBGSB
metadata.memberNamestringRequiredชื่อสมาชิก/เจ้าของบัญชีผู้โอนนาย ทองดี ใจงาม
metadata.memberNameEnstringRecommendedชื่อสมาชิกภาษาอังกฤษ (ช่วยเพิ่มความแม่นยำกรณีชื่อไทยถูกตัด)THONGDEE JAINGAM
metadata.customerIdstringOptionalรหัสสมาชิกฝั่ง merchant เพื่อ traceu_123

[Integration Update] Create Payment Contract (Effective Now)

ต้องส่งฟิลด์ต่อไปนี้ทุกครั้งเมื่อเรียก POST /api/v1/payment/create

  1. orderId
  2. metadata.senderAccountNumber (อย่างน้อย 8 หลัก)
  3. metadata.senderBankCode
  4. metadata.memberName

ถ้าส่งไม่ครบ ระบบจะตอบกลับ 400 PAYMENT_CONTRACT_POLICY_VIOLATION

Recommended & Notes

  • amount รองรับทศนิยม 2 ตำแหน่ง (เช่น 100.37)
  • Recommended: ส่ง metadata.memberNameEn
  • senderAccountNumber ต้องมีอย่างน้อย 8 หลัก
  • ถ้าไม่ส่ง senderAccountLast4 ระบบจะเติมให้อัตโนมัติ
  • ทำ orderId ให้ unique ต่อ merchant เสมอ

No QR Mode (ใช้งานได้)

  • merchant ที่ไม่ใช้ QR สามารถฝากผ่านบัญชีธนาคารได้ โดยดูจาก paymentAccounts.bankAccounts
  • ตรวจจาก response เสมอ: ถ้า transaction.qrCode เป็น null ให้แสดงช่องทางโอนบัญชีแทน
  • ตรวจ paymentAccounts.channels.promptPayEnabled และ bankTransferEnabled ก่อนแสดงปุ่มชำระเงิน
  • สถานะช่องทางจริงเป็นแบบผสม: global switch ของระบบ + ค่า override ราย merchant
POST /api/v1/payment/create
curl -X POST 'https://api.hyronpay.com/api/v1/payment/create' \
-H 'X-API-Key: sk_test_xxxxxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"amount": 100.37,
"orderId": "ORD-10001",
"description": "Topup",
"metadata": {
"customerId": "u_123",
"senderAccountNumber": "1673585481",
"senderBankCode": "GSB",
"memberName": "นาย ทองดี ใจงาม",
"memberNameEn": "THONGDEE JAINGAM"
}
}'
Create Payment Success Response (201)
{
"success": true,
"transaction": {
"id": "uuid",
"orderId": "ORD-10001",
"amount": 100.37,
"fee": 2.01,
"netAmount": 98.36,
"status": "PENDING",
"paymentMethod": "PROMPTPAY",
"qrCode": "data:image/png;base64,...",
"qrExpiry": "2026-03-05T08:15:00.000Z",
"createdAt": "2026-03-05T08:00:00.000Z",
"copy": {
"amount": "100.37"
}
},
"paymentAccounts": {
"channels": {
"promptPayEnabled": true,
"bankTransferEnabled": true
},
"promptPay": {
"id": "payin_pp_uuid",
"type": "PROMPTPAY",
"name": "Hyronpay PromptPay",
"accountNumber": "0812345678",
"bankCode": null,
"bankName": null,
"isDefault": true,
"updatedAt": "2026-03-05T07:58:00.000Z",
"copy": {
"account_number": "0812345678"
}
},
"bankAccounts": [
{
"id": "payin_bank_uuid",
"type": "BANK",
"name": "Hyronpay SCB Main",
"accountNumber": "1234567890",
"accountName": "Hyronpay SCB Main",
"bankCode": "014",
"bankName": "ธนาคารไทยพาณิชย์",
"isDefault": true,
"updatedAt": "2026-03-05T07:59:00.000Z",
"copy": {
"account_number": "1234567890"
}
}
]
},
"paymentContractPolicy": {
"mode": "enforce_all",
"enforceForThisMerchant": true,
"reason": "enforce_all mode",
"enforceNewMerchantFrom": null
},
"integrationWarnings": []
}
Create Payment Response Example (No QR Mode)
{
"success": true,
"transaction": {
"id": "uuid",
"orderId": "ORD-10002",
"amount": 200.55,
"fee": 4.01,
"netAmount": 196.54,
"status": "PENDING",
"paymentMethod": "PROMPTPAY",
"qrCode": null,
"qrExpiry": "2026-03-05T08:25:00.000Z",
"createdAt": "2026-03-05T08:10:00.000Z",
"copy": {
"amount": "200.55"
}
},
"paymentAccounts": {
"channels": {
"promptPayEnabled": false,
"bankTransferEnabled": true
},
"promptPay": null,
"bankAccounts": [
{
"id": "payin_bank_uuid",
"type": "BANK",
"name": "Hyronpay SCB Main",
"accountNumber": "1234567890",
"accountName": "Hyronpay SCB Main",
"bankCode": "014",
"bankName": "ธนาคารไทยพาณิชย์",
"isDefault": true,
"updatedAt": "2026-03-05T07:59:00.000Z",
"copy": {
"account_number": "1234567890"
}
}
]
}
}

4) Payout Contract

FieldTypeRequiredDescriptionExample
amountnumberRequiredยอดถอน (ต้องไม่น้อยกว่า minSettlementAmount ของระบบ)100
destination.bankCodestringRequiredรหัสธนาคารของปลายทาง (ดูตาราง bankCode ด้านล่าง)SCB
destination.bankNamestringOptionalชื่อธนาคารปลายทาง (ถ้าไม่ส่ง ระบบ derive จาก bankCode ที่รองรับให้)ธนาคารไทยพาณิชย์
destination.accountNumberstringRequiredเลขบัญชีปลายทาง (8-20 หลัก)4190621964
destination.accountNamestringRequiredชื่อบัญชีปลายทางเจษฎา
merchantRefstringOptionalถ้าไม่ส่ง ระบบ generate ให้ (แนะนำส่งถ้ามีเลขอ้างอิงฝั่ง merchant); รูปแบบต้องเป็น ^[A-Z0-9]{3,6}-[A-Z0-9]{3,13}$M01-WD240001
metadataobjectOptionalข้อมูลเสริมสำหรับ trace/reconcile{"sourceSystem":"lotto-main"}

Quick Rules ก่อนเรียก POST /api/v1/payout/create

  • ต้องใช้ X-API-Key ที่เป็น secret key (sk_...)
  • ตั้งค่า Idempotency-Key ต่อ 1 คำสั่งถอน (retry รายการเดิมให้ใช้ key เดิม)
  • ต้องส่ง X-Signature-Timestamp และ X-Signature
  • ต้องมี Idempotency-Key (หรือ idempotencyKey ใน body)
  • ระบบจะเช็กยอดขั้นต่ำและ balance ร้านค้าก่อนรับคำสั่งถอน
Payout Headers Quick Start (Who Generates What?)
Merchant headers backend (Hyronpay generate ):
 
1) X-API-Key
- secret key : sk_live_... / sk_test_...
 
2) Idempotency-Key
- 1 ( UUID v4)
- retry key
 
3) X-Signature-Timestamp
- Unix time request
 
4) X-Signature
- hex(HMAC_SHA256(secret_api_key, "<timestamp>.<raw_body_json>"))
 
5) X-Signature-Nonce
- optional, recommended ( replay )
 
Payout Signature Spec
payload = "<X-Signature-Timestamp>.<raw_body_json>"
X-Signature = hex(HMAC_SHA256(secret_api_key, payload))
 
Required Headers:
- X-API-Key (secret key)
- Idempotency-Key
- X-Signature-Timestamp (unix seconds)
- X-Signature
- X-Signature-Nonce (optional, recommended)
 
Tip: GET /api/v1/payout/signature-settings
Node.js: Build Idempotency + Signature Headers
const crypto = require('crypto');
 
const secretApiKey = process.env.HYRONPAY_SECRET_KEY; // sk_live_... sk_test_...
const body = {
amount: 100,
destination: {
bankCode: 'SCB',
accountNumber: '4190621964',
accountName: '',
},
metadata: { sourceSystem: 'merchant-backoffice' },
};
 
const rawBody = JSON.stringify(body);
const timestamp = Math.floor(Date.now() / 1000).toString();
const idempotencyKey = crypto.randomUUID();
const signature = crypto
.createHmac('sha256', secretApiKey)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
 
const headers = {
'X-API-Key': secretApiKey,
'Content-Type': 'application/json',
'Idempotency-Key': idempotencyKey,
'X-Signature-Timestamp': timestamp,
'X-Signature': signature,
};
 
// fetch/axios headers + rawBody sign
POST /api/v1/payout/create
curl -X POST 'https://api.hyronpay.com/api/v1/payout/create' \
-H 'X-API-Key: sk_test_xxxxxxxxx' \
-H 'Idempotency-Key: m01-wd-20260304-0001' \
-H 'X-Signature-Timestamp: <unix_seconds>' \
-H 'X-Signature: <hmac_sha256_hex>' \
-H 'Content-Type: application/json' \
-d '{
"amount": 100,
"destination": {
"bankCode": "SCB",
"accountNumber": "4190621964",
"accountName": "เจษฎา"
},
"metadata": {
"sourceSystem": "merchant-backoffice"
}
}'
Payout Create Success Response (201)
{
"success": true,
"object": "payout",
"idempotent": false,
"payout": {
"object": "payout",
"id": "po_123",
"merchant_id": "m_123",
"merchant_ref": "M01-WD240001",
"amount": 100,
"fee": 0,
"net_amount": 100,
"currency": "THB",
"destination": {
"bank_code": "014",
"bank_name": "ธนาคารไทยพาณิชย์",
"account_number": "4190621964",
"account_name": "เจษฎา"
},
"status": "QUEUED",
"status_reason": null,
"external_ref": null,
"requested_at": "2026-03-05T08:05:00.000Z",
"processed_at": null,
"created_at": "2026-03-05T08:05:00.000Z",
"metadata": {
"sourceSystem": "merchant-backoffice"
},
"copy": {
"amount": "100.00",
"account_number": "4190621964"
}
}
}
Payout Error Response Example
{
"error": "idempotencyKey is required (send Idempotency-Key header or idempotencyKey field)",
"code": "IDEMPOTENCY_KEY_REQUIRED",
"details": null
}

4.5) Dashboard/Admin Copy Contract

สำหรับ endpoint ภายในระบบ (/api/payout, /api/settlement, /api/admin/*) ที่มีจำนวนเงินหรือเลขบัญชี ระบบจะส่ง copy field เพื่อให้ UI ใช้คัดลอกได้ทันที

EndpointFieldTypeAvailabilityDescriptionExample
GET /api/payoutpayouts[].copy.amountstringAlwaysคัดลอกยอด payout เป็นทศนิยม 2 ตำแหน่ง"100.00"
GET /api/payoutpayouts[].copy.account_numberstringAlwaysคัดลอกเลขบัญชีปลายทาง"4190621964"
GET /api/payout/summaryqueued|inProgress|success|failed|cancelled|total.copy.amountstringAlwaysคัดลอกยอดจากข้อมูลสรุป payout-
GET /api/settlementsettlements[].copy.amountstringAlwaysคัดลอกยอดถอนเป็นทศนิยม 2 ตำแหน่ง"1200.50"
GET /api/settlementsettlements[].copy.account_numberstringAlwaysคัดลอก bankAccount ของรายการถอน"1234567890"
GET /api/settlement/summarypending|processing|completed|failed|total.copy.amountstringAlwaysคัดลอกยอดจากข้อมูลสรุป settlement-
GET /api/admin/payoutspayouts[].copy.amount / payouts[].copy.account_numberstringAlwaysคัดลอกยอดและเลขบัญชีในหน้าจัดการ payout-
GET /api/admin/payouts/summarysummary.<status>.copy.amountstringAlwaysคัดลอกยอดในกล่อง summary แยกสถานะ-
GET /api/admin/payouts/batchesbatches[].copy.amountstringAlwaysคัดลอกยอดรวมของแต่ละ batch"2500.00"
GET /api/admin/payouts/batches/:idbatch.copy.amount / batch.payouts[].copy.*stringAlwaysคัดลอกยอด batch และข้อมูล payout ใน batch เดียวกัน-
GET /api/admin/settlementssettlements[].copy.amount / settlements[].copy.account_numberstringAlwaysคัดลอกยอดและเลขบัญชีในหน้าจัดการ settlement-
GET /api/admin/settlements/summarytotal|pending|processing|completed|failed.copy.amountstringAlwaysคัดลอกยอดสรุป settlement ฝั่งแอดมิน-
GET /api/admin/transactionstransactions[].copy.amountstringAlwaysคัดลอกยอดรับเงินในรายการธุรกรรม"100.00"
GET /api/admin/bank-accountsdata[].copy.account_numberstringAlwaysคัดลอกเลขบัญชีระบบกลาง"1234567890"
POST /api/payment/create-linktransaction.copy.amountstringAlwaysคัดลอกยอดสำหรับหน้า dashboard create link"300.00"
Copy Field Contract
copy field contract (internal APIs)
- copy.amount: string 2 "100.00"
- copy.account_number: string
- amount -> copy.amount
- accountNumber/account_number -> copy.account_number
GET /api/payout (merchant dashboard)
{
"payouts": [
{
"id": "po_001",
"merchantId": "m_123",
"merchantRef": "M01-WD240001",
"amount": "100",
"bankCode": "014",
"bankName": "ธนาคารไทยพาณิชย์",
"accountNumber": "4190621964",
"accountName": "เจษฎา",
"status": "QUEUED",
"createdAt": "2026-03-09T10:00:00.000Z",
"copy": {
"amount": "100.00",
"account_number": "4190621964"
}
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
},
"filters": {
"status": "all"
}
}
GET /api/settlement (merchant dashboard)
{
"settlements": [
{
"id": "st_001",
"merchantId": "m_123",
"amount": "1200.5",
"fee": "12.01",
"netAmount": "1188.49",
"bankAccount": "1234567890",
"bankName": "ธนาคารไทยพาณิชย์",
"status": "PENDING",
"createdAt": "2026-03-09T10:05:00.000Z",
"copy": {
"amount": "1200.50",
"account_number": "1234567890"
}
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
},
"filters": {
"status": "all"
}
}
GET /api/admin/payouts
{
"payouts": [
{
"id": "po_001",
"merchantId": "m_123",
"merchantRef": "M01-WD240001",
"amount": "100",
"accountNumber": "4190621964",
"status": "QUEUED",
"merchant": {
"businessName": "Demo Store",
"username": "merchant_demo"
},
"batch": null,
"copy": {
"amount": "100.00",
"account_number": "4190621964"
}
}
],
"pagination": {
"page": 1,
"limit": 100,
"total": 1,
"totalPages": 1
}
}
GET /api/admin/settlements
{
"settlements": [
{
"id": "st_001",
"merchantId": "m_123",
"amount": "1200.5",
"bankAccount": "1234567890",
"bankName": "ธนาคารไทยพาณิชย์",
"status": "PENDING",
"merchant": {
"id": "m_123",
"businessName": "Demo Store",
"username": "merchant_demo",
"balance": "9500"
},
"copy": {
"amount": "1200.50",
"account_number": "1234567890"
}
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
},
"filters": {
"status": "ALL",
"q": ""
}
}
GET /api/admin/transactions
{
"transactions": [
{
"id": "tx_001",
"merchantId": "m_123",
"orderId": "ORD-10001",
"amount": "100",
"status": "PAID",
"referenceId": "ORD-10001",
"confirmedAt": "2026-03-09T10:10:00.000Z",
"copy": {
"amount": "100.00"
}
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 1,
"totalItems": 1,
"totalPages": 1
}
}
GET /api/admin/bank-accounts
{
"success": true,
"data": [
{
"id": "acct_001",
"type": "BANK",
"usage": "PAYOUT",
"name": "SCB Debit Main",
"accountNumber": "1234567890",
"bankCode": "014",
"bankName": "ธนาคารไทยพาณิชย์",
"isDefault": true,
"copy": {
"account_number": "1234567890"
}
}
]
}

5) Bank Code Reference

destination.bankCode ส่งเป็น alias (เช่น SCB, KBANK) หรือเป็นเลข 3 หลักได้

destination.bankName เป็น optional แล้วสำหรับ bankCode ที่ระบบรู้จัก — backend จะเติมชื่อธนาคารให้เองตามตารางด้านล่าง

Input AcceptedNormalized SCB CodeBank Name (TH)Note
SCB014ธนาคารไทยพาณิชย์Siam Commercial Bank
KBANK, KASIKORN004ธนาคารกสิกรไทยKasikorn Bank
KTB, KRUNGTHAI006ธนาคารกรุงไทยKrungthai Bank
BBL, BANGKOK002ธนาคารกรุงเทพBangkok Bank
TTB011ธนาคารทีเอ็มบีธนชาตTMBThanachart Bank
BAY025ธนาคารกรุงศรีอยุธยาBank of Ayudhya
GSB030ธนาคารออมสินGovernment Savings Bank
UOB024ธนาคารยูโอบีUnited Overseas Bank
CIMB022ธนาคารซีไอเอ็มบี ไทยCIMB Thai
BAAC034ธนาคารเพื่อการเกษตรและสหกรณ์การเกษตรBank for Agriculture and Agricultural Cooperatives
GHB033ธนาคารอาคารสงเคราะห์Government Housing Bank
TISCO067ธนาคารทิสโก้TISCO Bank
KKP069ธนาคารเกียรตินาคินภัทรKiatnakin Phatra Bank
LHBANK073ธนาคารแลนด์ แอนด์ เฮ้าส์Land and Houses Bank
SME098ธนาคารพัฒนาวิสาหกิจขนาดกลางและขนาดย่อมแห่งประเทศไทยSME Development Bank
001, 002, 004 ...ตรงตามที่ส่งส่งชื่อธนาคารให้ตรงกับบัญชีปลายทางส่งเป็นเลข 3 หลักตรงๆ ได้เช่นกัน
แนวทางมาตรฐาน: ถ้าฝั่ง merchant มี master bank code อยู่แล้ว ให้ส่งเลข 3 หลักตรงๆ ได้เลย (เช่น 004, 014) เพื่อลดปัญหา alias ไม่ตรงกัน

6) Operational + Webhook

Webhook Setup Checklist

  1. ตั้ง Callback URL ฝั่งระบบของคุณให้รับ POST และตอบ 2xx เมื่อรับสำเร็จ
  2. ตั้งค่า webhook ในระบบ Hyronpay (Dashboard > Webhooks) แล้วเลือก event ที่ต้องการ
  3. บันทึก webhook secret เพื่อตรวจลายเซ็น X-Webhook-Signature ทุกครั้ง
  4. dedupe callback ด้วย X-Webhook-Idempotency-Key และเก็บ deliveryId สำหรับ audit/replay

Firewall / Callback IP Guidance

  • ถ้าปลายทางมี firewall ให้ใช้ source IP allowlist เป็นชั้นเสริมเท่านั้น ไม่ใช่กลไกหลัก
  • การยืนยันหลักต้องตรวจ X-Webhook-Signature จาก raw body ทุกครั้งก่อนประมวลผล
  • ถ้าต้อง allow IP จริง ให้ใช้ public egress IP ของ production runtime/NAT ที่ส่ง callback ออกไปจริง
  • หากมีการย้าย infra หรือเปลี่ยน outbound route ค่า IP อาจเปลี่ยนได้

Balance Scope Guide

แยก endpoint ให้ชัดเจน: /balance = ยอดของร้านค้าปัจจุบันเท่านั้น, /balance/line-summary = สรุปยอดรวมทั้งสายงาน

Self Balance

GET /api/v1/balance

เหมาะกับ flow ตรวจยอดก่อน create payout/request approve

Line Summary

GET /api/v1/balance/line-summary

เหมาะกับ dashboard สรุปเครือข่าย: self, downline, totalLine

GET /api/v1/payment/accounts
curl 'https://api.hyronpay.com/api/v1/payment/accounts' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Payment Accounts Response Example
{
"object": "payment_accounts",
"merchant": {
"id": "merchant_uuid",
"username": "merchant_demo",
"business_name": "Demo Store",
"status": "ACTIVE"
},
"channels": {
"promptpay_enabled": true,
"bank_transfer_enabled": true
},
"promptpay": {
"id": "payin_pp_uuid",
"type": "PROMPTPAY",
"name": "Hyronpay PromptPay",
"account_number": "0812345678",
"bank_code": null,
"bank_name": null,
"is_default": true,
"updated_at": "2026-03-06T09:10:00.000Z"
},
"bank_accounts": [
{
"id": "payin_bank_uuid",
"type": "BANK",
"name": "Hyronpay SCB Main",
"account_number": "1234567890",
"account_name": "Hyronpay SCB Main",
"bank_code": "014",
"bank_name": "ธนาคารไทยพาณิชย์",
"is_default": true,
"updated_at": "2026-03-06T09:12:00.000Z"
}
],
"updated_at": "2026-03-06T09:12:00.000Z"
}
Payment Accounts Response Example (No QR Mode)
{
"object": "payment_accounts",
"merchant": {
"id": "merchant_uuid",
"username": "merchant_demo",
"business_name": "Demo Store",
"status": "ACTIVE"
},
"channels": {
"promptpay_enabled": false,
"bank_transfer_enabled": true
},
"promptpay": null,
"bank_accounts": [
{
"id": "payin_bank_uuid",
"type": "BANK",
"name": "Hyronpay SCB Main",
"account_number": "1234567890",
"account_name": "Hyronpay SCB Main",
"bank_code": "014",
"bank_name": "ธนาคารไทยพาณิชย์",
"is_default": true,
"updated_at": "2026-03-06T09:12:00.000Z"
}
],
"updated_at": "2026-03-06T09:12:00.000Z"
}
GET /api/v1/balance
curl 'https://api.hyronpay.com/api/v1/balance' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Balance Response Example
{
"object": "balance",
"merchant": {
"id": "merchant_uuid",
"username": "merchant_demo",
"businessName": "Demo Store",
"status": "ACTIVE"
},
"balance": 15234.5,
"currency": "THB",
"updatedAt": "2026-03-06T09:15:00.000Z"
}
GET /api/v1/balance/line-summary
curl 'https://api.hyronpay.com/api/v1/balance/line-summary' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Balance Line Summary Response Example
{
"object": "balance_line_summary",
"merchant": {
"id": "merchant_uuid",
"username": "merchant_demo",
"businessName": "Demo Store",
"status": "ACTIVE"
},
"scope": {
"merchantCount": 7,
"downlineCount": 6,
"directChildrenCount": 2
},
"balances": {
"self": 15234.5,
"downline": 48765.5,
"totalLine": 64000
},
"currency": "THB",
"updatedAt": "2026-03-06T09:15:00.000Z",
"lineUpdatedAt": "2026-03-06T09:16:10.000Z"
}
GET /api/v1/profile
curl 'https://api.hyronpay.com/api/v1/profile' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Profile Response Example
{
"object": "profile",
"authenticated_with": "secret",
"authenticated_with_mode": "live",
"merchant": {
"id": "merchant_uuid",
"username": "merchant_demo",
"email": "merchant@example.com",
"business_name": "Demo Store",
"owner_name": "demo.example.com",
"phone": "0812345678",
"status": "ACTIVE",
"fee_percent": 2,
"fee_fixed": 0,
"balance": 15234.5,
"parent_merchant_id": null,
"parent_merchant": null,
"capabilities": {
"can_create_child": false,
"can_child_create_child": false,
"max_child_depth": null,
"max_children": null
},
"counters": {
"child_merchants": 0,
"webhooks": 1
},
"created_at": "2026-03-01T10:00:00.000Z",
"updated_at": "2026-03-06T09:15:00.000Z"
}
}
GET /api/v1/webhooks
curl 'https://api.hyronpay.com/api/v1/webhooks' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Webhooks Response Example
{
"object": "list",
"merchant": {
"id": "merchant_uuid",
"username": "merchant_demo",
"business_name": "Demo Store",
"status": "ACTIVE"
},
"total": 1,
"webhooks": [
{
"object": "webhook",
"id": "wh_123",
"url": "https://merchant.example.com/api/paygate/webhook",
"events": ["payment.success", "payment.failed", "payout.success", "payout.failed"],
"is_active": true,
"created_at": "2026-03-01T10:10:00.000Z",
"updated_at": "2026-03-06T09:20:00.000Z"
}
],
"updated_at": "2026-03-06T09:20:00.000Z"
}
GET /api/v1/webhook/events
curl 'https://api.hyronpay.com/api/v1/webhook/events' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Webhook Events Response Example
{
"object": "list",
"events": [
{ "name": "payment.created", "description": "เมื่อสร้างรายการชำระเงินใหม่" },
{ "name": "payment.success", "description": "เมื่อชำระเงินสำเร็จ" },
{ "name": "payment.failed", "description": "เมื่อชำระเงินล้มเหลวหรือถูกยกเลิก" },
{ "name": "payment.expired", "description": "เมื่อรายการหมดอายุ" },
{ "name": "settlement.created", "description": "เมื่อสร้างรายการถอนเงิน" },
{ "name": "settlement.completed", "description": "เมื่อถอนเงินสำเร็จ" },
{ "name": "payout.success", "description": "เมื่อโอนเงินให้ลูกค้าสำเร็จ" },
{ "name": "payout.failed", "description": "เมื่อโอนเงินให้ลูกค้าล้มเหลว หรือยกเลิกการถอน (status=CANCELLED)" },
{ "name": "*", "description": "รับทุก event" }
]
}
GET /api/v1/payment/order/:orderId
curl 'https://api.hyronpay.com/api/v1/payment/order/ORD-10001' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Payment Order Response Example
{
"transaction": {
"id": "tx_123",
"merchantId": "m_123",
"orderId": "ORD-10001",
"amount": 100,
"fee": 2,
"netAmount": 98,
"paymentMethod": "PROMPTPAY",
"status": "PAID",
"paidAt": "2026-03-05T08:02:10.000Z",
"createdAt": "2026-03-05T08:00:00.000Z"
}
}
GET /api/v1/payout/ref/:merchantRef
curl 'https://api.hyronpay.com/api/v1/payout/ref/M01-WD240001' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Payout Lookup Response Example
{
"payout": {
"object": "payout",
"id": "po_123",
"merchant_id": "m_123",
"merchant_ref": "M01-WD240001",
"amount": 100,
"fee": 0,
"net_amount": 100,
"currency": "THB",
"destination": {
"bank_code": "014",
"bank_name": "ธนาคารไทยพาณิชย์",
"account_number": "4190621964",
"account_name": "เจษฎา"
},
"status": "SUCCESS",
"status_reason": null,
"external_ref": "SCB202603050001",
"requested_at": "2026-03-05T08:05:00.000Z",
"processed_at": "2026-03-05T08:06:10.000Z",
"created_at": "2026-03-05T08:05:00.000Z",
"metadata": {
"sourceSystem": "merchant-backoffice"
},
"copy": {
"amount": "100.00",
"account_number": "4190621964"
}
}
}
GET /api/v1/payout/signature-settings
curl 'https://api.hyronpay.com/api/v1/payout/signature-settings' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Customer Firewall Request Template
Subject: Hyronpay Webhook Firewall Allowlist
 
Please allow inbound HTTPS callback traffic to our webhook endpoint from Hyronpay production egress IP.
 
- Protocol: HTTPS
- Method: POST
- Source IP: <production_egress_ip>
- Path: /api/paygate/webhook
 
Important:
1. Source IP allowlist is an additional control only.
2. Our system will verify X-Webhook-Signature on every callback before processing.
3. If Hyronpay production infrastructure or outbound routing changes, the source IP may need to be updated.
Webhook Headers (Verify Signature)
X-Webhook-Signature: <hmac_sha256_hex>
X-Webhook-Event: payment.success
X-Webhook-Timestamp: 2026-03-05T08:02:11.000Z
X-Webhook-Delivery-Id: 4b50836d-5c5b-4d74-a6e3-70b87f5dfe4f
X-Webhook-Idempotency-Key: payment.success:tx_123
X-Webhook-Id: wh_123
X-Webhook-Version: 1
Webhook Verify Example (Node.js)
import crypto from 'crypto';
 
function verifyWebhook(rawBody, signatureHeader, webhookSecret) {
const expected = crypto.createHmac('sha256', webhookSecret).update(rawBody).digest('hex');
const a = Buffer.from(expected, 'utf8');
const b = Buffer.from(String(signatureHeader || ''), 'utf8');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
 
// :
// 1) verify raw body
// 2) webhook secret ( sk_ API key)

Webhook Event Payloads

Webhook Event: payment.success
{
"event": "payment.success",
"deliveryId": "4b50836d-5c5b-4d74-a6e3-70b87f5dfe4f",
"data": {
"id": "tx_123",
"transactionId": "tx_123",
"orderId": "ORD-10001",
"amount": 100,
"fee": 2,
"netAmount": 98,
"status": "PAID",
"paidAt": "2026-03-05T08:02:10.000Z",
"idempotencyKey": "payment.success:tx_123",
"idempotency_key": "payment.success:tx_123",
"customerId": "u_123",
"customer_id": "u_123",
"memberName": "นาย ทองดี ใจงาม",
"member_name": "นาย ทองดี ใจงาม",
"senderAccountNumber": "1673585481",
"sender_account_number": "1673585481",
"senderAccountLast4": "5481",
"sender_account_last4": "5481",
"senderBankCode": "GSB",
"sender_bank_code": "GSB"
},
"timestamp": "2026-03-05T08:02:11.000Z",
"webhookId": "wh_123"
}
Webhook Event: payment.failed
{
"event": "payment.failed",
"deliveryId": "80b5a8b8-88e2-45ec-8eaa-6a52d69f0d79",
"data": {
"id": "tx_124",
"transactionId": "tx_124",
"orderId": "ORD-10001",
"amount": 100,
"status": "CANCELLED",
"idempotencyKey": "payment.failed:tx_124",
"idempotency_key": "payment.failed:tx_124",
"errorMessage": "Cancelled by merchant"
},
"timestamp": "2026-03-05T08:06:10.000Z",
"webhookId": "wh_123"
}
Webhook Event: payment.expired
{
"event": "payment.expired",
"deliveryId": "1719fbdb-0b72-4c2b-8d18-1c8dcd5fd3b7",
"data": {
"id": "tx_125",
"transactionId": "tx_125",
"orderId": "ORD-10001",
"amount": 100,
"status": "EXPIRED",
"idempotencyKey": "payment.expired:tx_125",
"idempotency_key": "payment.expired:tx_125"
},
"timestamp": "2026-03-05T08:15:01.000Z",
"webhookId": "wh_123"
}
Webhook Event: settlement.created
{
"event": "settlement.created",
"deliveryId": "5dfec3c3-8d24-447f-a60e-8ef4a0d72211",
"data": {
"id": "st_123",
"settlementId": "st_123",
"amount": 500,
"fee": 8,
"netAmount": 492,
"status": "PENDING",
"createdAt": "2026-03-05T08:40:00.000Z",
"note": "Webhook test for Demo Store"
},
"timestamp": "2026-03-05T08:40:01.000Z",
"webhookId": "wh_123"
}
Webhook Event: settlement.completed
{
"event": "settlement.completed",
"deliveryId": "1254b17f-41b0-4c80-a9f1-176dd88d68fd",
"data": {
"id": "st_123",
"settlementId": "st_123",
"amount": 500,
"fee": 8,
"netAmount": 492,
"status": "COMPLETED",
"processedAt": "2026-03-05T09:15:20.000Z",
"reference": "RID-202603050001",
"note": "Batch #B20260305-001"
},
"timestamp": "2026-03-05T09:15:21.000Z",
"webhookId": "wh_123"
}
Webhook Event: payout.success
{
"event": "payout.success",
"deliveryId": "4b50836d-5c5b-4d74-a6e3-70b87f5dfe4f",
"data": {
"id": "po_123",
"payoutId": "po_123",
"merchant_ref": "M01-WD240001",
"merchantRef": "M01-WD240001",
"idempotency_key": "withdrawal-request:req_123",
"idempotencyKey": "withdrawal-request:req_123",
"status": "SUCCESS",
"amount": 100,
"external_ref": "SCB202603050001",
"externalRef": "SCB202603050001"
},
"timestamp": "2026-03-05T08:20:10.000Z",
"webhookId": "wh_123"
}
Webhook Event: payout.failed
{
"event": "payout.failed",
"deliveryId": "21f80419-4f57-4d4a-8cdd-440ad9d548f9",
"data": {
"id": "po_124",
"payoutId": "po_124",
"merchant_ref": "M01-WD240002",
"merchantRef": "M01-WD240002",
"idempotency_key": "withdrawal-request:req_124",
"idempotencyKey": "withdrawal-request:req_124",
"status": "CANCELLED",
"amount": 100,
"external_ref": null,
"externalRef": null,
"errorMessage": "Cancelled by merchant"
},
"timestamp": "2026-03-05T08:21:40.000Z",
"webhookId": "wh_123"
}

Webhook Delivery Policy (Current Behavior: 2026-03-11)

  • Hyronpay ส่ง callback แบบ best effort ต่อ webhook URL ที่ active และรองรับ event นั้น
  • ระบบจะคำนวณ X-Webhook-Signature จาก JSON body ที่ส่งจริง (raw payload เดียวกัน)
  • ทุก callback มี deliveryId ใหม่เสมอเมื่อ replay/manual resend แต่ X-Webhook-Idempotency-Key จะคงเดิมต่อ business event เดิม
  • เมื่อ retry/replay จาก queue ระบบจะ re-sign ด้วย webhook secret ล่าสุดก่อนส่งทุกครั้ง
  • กรณียกเลิกถอน (CANCELLED) จะส่งผ่าน event payout.failed โดย payload มี data.status=CANCELLED
  • Webhook payout ส่งทั้งคีย์ canonical และ alias (id+payoutId, merchant_ref+merchantRef, idempotency_key+idempotencyKey)
  • Timeout ต่อคำขอ default 10 วินาที (ปรับได้ด้วย WEBHOOK_TIMEOUT_MS)
  • มี retry แบบ exponential backoff ตามค่า WEBHOOK_MAX_ATTEMPTS (default 3)
  • ฝั่ง merchant ควร queue งานภายในและตอบ 2xx ให้เร็วที่สุด

7) Webhook Field Matrix

ตารางนี้สรุป field ที่ควรรองรับใน callback payload แยกตาม event เพื่อให้ทีม backend mapping ได้ชัดเจน

EventFieldTypeRequiredDescriptionExample
* (all events)eventstringRequiredชื่อ event ที่ส่งมาpayment.success
* (all events)deliveryIdstringRequiredรหัส delivery ของ callback ครั้งนี้ (ใหม่ทุก replay/send)4b50836d-5c5b-4d74-a6e3-70b87f5dfe4f
* (all events)timestampstring (ISO-8601)Requiredเวลาที่สร้าง callback payload2026-03-05T08:02:11.000Z
* (all events)webhookIdstringRequiredID ของ webhook config ในระบบ Hyronpaywh_123
payment.successdata.idstringRequiredID รายการรับชำระ (alias ของ transactionId)tx_123
payment.successdata.transactionIdstringRequiredID รายการรับชำระtx_123
payment.successdata.orderIdstringRequiredorderId จากฝั่ง merchantORD-10001
payment.successdata.amountnumberRequiredยอดที่ชำระ100
payment.successdata.statusstringRequiredสถานะรายการPAID
payment.successdata.paidAtstring (ISO-8601)Requiredเวลาชำระสำเร็จ2026-03-05T08:02:10.000Z
payment.successdata.customerId | data.customer_idstringOptionalรหัสสมาชิก/ลูกค้าที่ merchant ส่งมาตอน create payment ถ้ามีu_123
payment.successdata.idempotency_key | data.idempotencyKeystringRecommendedคีย์กันซ้ำฝั่ง callback (รูปแบบ `payment.success:<transactionId>`)payment.success:tx_123
payment.successdata.memberName | data.member_namestringOptionalชื่อสมาชิกที่ merchant ส่งมาตอน create payment ถ้ามีนาย ทองดี ใจงาม
payment.successdata.senderAccountNumber | data.sender_account_numberstringOptionalเลขบัญชีผู้โอนที่ merchant ส่งมาตอน create payment ถ้ามี1673585481
payment.successdata.senderAccountLast4 | data.sender_account_last4stringOptionalเลขท้ายบัญชีผู้โอน 4 หลัก ระบบจะเติมให้อัตโนมัติเมื่อคำนวณได้จาก senderAccountNumber5481
payment.successdata.senderBankCode | data.sender_bank_codestringOptionalรหัสธนาคารผู้โอนที่ merchant ส่งมาตอน create payment ถ้ามีGSB
payment.failed | payment.expireddata.idstringRequiredID รายการรับชำระ (alias ของ transactionId)tx_124
payment.failed | payment.expireddata.transactionIdstringRequiredID รายการรับชำระtx_124
payment.failed | payment.expireddata.orderIdstringRequiredorderId จากฝั่ง merchantORD-10002
payment.failed | payment.expireddata.amountnumberRequiredยอดรายการ100
payment.failed | payment.expireddata.idempotency_key | data.idempotencyKeystringRecommendedคีย์กันซ้ำฝั่ง callback (รูปแบบ `<event>:<transactionId>`)payment.failed:tx_124
payment.failed | payment.expireddata.statusstringRequiredสถานะรายการ (FAILED / CANCELLED / EXPIRED)FAILED / CANCELLED / EXPIRED
payment.faileddata.errorMessagestringRecommendedเหตุผลล้มเหลวหรือยกเลิกCancelled by merchant
settlement.created | settlement.completeddata.id | data.settlementIdstringRequiredID รายการถอนเครดิต (alias กันเอง)st_123
settlement.created | settlement.completeddata.amountnumberRequiredยอดถอนเครดิต500
settlement.created | settlement.completeddata.fee | data.netAmountnumberRecommendedค่าธรรมเนียมและยอดสุทธิ (มีใน payload มาตรฐานของระบบ)fee=8, netAmount=492
settlement.createddata.status | data.createdAt | data.notestringRecommendedสถานะเริ่มต้น, เวลาเริ่มรายการ, และหมายเหตุ (ถ้ามี)status=PENDING
settlement.completeddata.status | data.processedAt | data.reference | data.notestringRecommendedสถานะสำเร็จ, เวลาที่ประมวลผลเสร็จ, เลขอ้างอิง, หมายเหตุstatus=COMPLETED
payout.success | payout.failed (includes CANCELLED)webhookIdstringRequiredID ของ webhook endpoint ที่ถูกใช้ส่ง callbackwh_123
payout.success | payout.failed (includes CANCELLED)data.idstringRequiredID payoutpo_123
payout.success | payout.failed (includes CANCELLED)data.payoutIdstringRequiredID payout (alias ของ data.id)po_123
payout.success | payout.failed (includes CANCELLED)data.merchant_refstringRequiredmerchant reference ของคำสั่งถอนM01-WD240001
payout.success | payout.failed (includes CANCELLED)data.merchantRefstringRequiredmerchant reference (alias ของ data.merchant_ref)M01-WD240001
payout.success | payout.failed (includes CANCELLED)data.idempotency_key | data.idempotencyKeystring | nullRecommendedidempotency key เดิมจากตอน create payout/request approve ถ้ามีwithdrawal-request:req_123
payout.success | payout.failed (includes CANCELLED)data.statusstringRequiredสถานะ payoutSUCCESS / FAILED / CANCELLED
payout.success | payout.failed (includes CANCELLED)data.amountnumberRequiredยอดถอน100
payout.failed (FAILED/CANCELLED)data.errorMessagestringRecommendedเหตุผลความล้มเหลวหรือการยกเลิกCancelled by merchant
payout.success | payout.failed (includes CANCELLED)data.external_ref | data.externalRefstring | nullOptionalเลขอ้างอิงภายนอกของการโอน (ถ้ามี)SCB202603050001

8) Error Catalog (Payment + Payout)

สรุป error ที่พบบ่อยจาก endpoint หลัก เพื่อให้ทำ error handling ได้ครบตั้งแต่รอบแรก

POST /api/v1/payment/create

CodeHTTPWhen
Invalid amount400amount ไม่ถูกต้องหรือ <= 0
ยอดชำระขั้นต่ำคือ <min> บาท400amount ต่ำกว่าค่า minPaymentAmount
ยอดชำระสูงสุดคือ <max> บาท400amount เกินค่า maxPaymentAmount
PAYMENT_CONTRACT_POLICY_VIOLATION400ไม่ส่งข้อมูลตาม Create Payment Contract ที่ระบบบังคับ
Order ID already exists400orderId ซ้ำภายใน merchant เดียวกัน
Forbidden403ใช้ key ที่ไม่ใช่ secret key (sk_...) กับ endpoint แบบเขียนข้อมูล
Failed to create payment500ข้อผิดพลาดภายในระบบ

GET /api/v1/payment/order/:orderId

CodeHTTPWhen
Transaction not found404ไม่พบรายการตาม orderId ของ merchant นี้
Failed to get payment500ข้อผิดพลาดภายในระบบ

Payout Endpoints

CodeHTTPWhen
IDEMPOTENCY_KEY_REQUIRED400ไม่ส่ง Idempotency-Key สำหรับ payout endpoint
INVALID_MERCHANT_REF_FORMAT400merchantRef ไม่ตรงรูปแบบ ^[A-Z0-9]{3,6}-[A-Z0-9]{3,13}$ (PREFIX 3-6, REFERENCE 3-13)
VALIDATION_ERROR400ข้อมูล request ไม่ครบหรือไม่ถูกต้อง
INSUFFICIENT_BALANCE400ยอดคงเหลือ merchant ไม่พอ
DUPLICATE_PAYOUT_REQUEST409merchantRef/idempotency ซ้ำกับคำขอเดิม

9) End-to-End Integration Flow

  1. 1Merchant backend สร้าง payment ผ่าน POST /api/v1/payment/create
  2. 2เมื่อมีผลชำระ Hyronpay ส่ง webhook callback (payment.success|failed|expired) ไปยัง callback URL
  3. 3Merchant backend ยืนยันสถานะซ้ำผ่าน GET /api/v1/payment/order/:orderId ก่อน credit/fulfillment
  4. 4เมื่อมีคำสั่งถอน ให้เรียก POST /api/v1/payout/create พร้อม signature และ idempotency
  5. 5รอ webhook payout.success|failed แล้วค่อยอัปเดตสถานะฝั่งสมาชิก (ยกเลิกถอนจะมาเป็น payout.failed + status=CANCELLED)
Step 1: Create Payment
curl -X POST 'https://api.hyronpay.com/api/v1/payment/create' \
-H 'X-API-Key: sk_test_xxxxxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"amount": 100.37,
"orderId": "ORD-10001",
"description": "Topup",
"metadata": {
"customerId": "u_123",
"senderAccountNumber": "1673585481",
"senderBankCode": "GSB",
"memberName": "นาย ทองดี ใจงาม",
"memberNameEn": "THONGDEE JAINGAM"
}
}'
Step 2: Receive payment.success Webhook
{
"event": "payment.success",
"deliveryId": "4b50836d-5c5b-4d74-a6e3-70b87f5dfe4f",
"data": {
"id": "tx_123",
"transactionId": "tx_123",
"orderId": "ORD-10001",
"amount": 100,
"fee": 2,
"netAmount": 98,
"status": "PAID",
"paidAt": "2026-03-05T08:02:10.000Z",
"idempotencyKey": "payment.success:tx_123",
"idempotency_key": "payment.success:tx_123",
"customerId": "u_123",
"customer_id": "u_123",
"memberName": "นาย ทองดี ใจงาม",
"member_name": "นาย ทองดี ใจงาม",
"senderAccountNumber": "1673585481",
"sender_account_number": "1673585481",
"senderAccountLast4": "5481",
"sender_account_last4": "5481",
"senderBankCode": "GSB",
"sender_bank_code": "GSB"
},
"timestamp": "2026-03-05T08:02:11.000Z",
"webhookId": "wh_123"
}
Step 3: Confirm By OrderId
curl 'https://api.hyronpay.com/api/v1/payment/order/ORD-10001' \
-H 'X-API-Key: sk_test_xxxxxxxxx'
Step 4: Create Payout
curl -X POST 'https://api.hyronpay.com/api/v1/payout/create' \
-H 'X-API-Key: sk_test_xxxxxxxxx' \
-H 'Idempotency-Key: m01-wd-20260304-0001' \
-H 'X-Signature-Timestamp: <unix_seconds>' \
-H 'X-Signature: <hmac_sha256_hex>' \
-H 'Content-Type: application/json' \
-d '{
"amount": 100,
"destination": {
"bankCode": "SCB",
"accountNumber": "4190621964",
"accountName": "เจษฎา"
},
"metadata": {
"sourceSystem": "merchant-backoffice"
}
}'
Step 5: Receive payout.success Webhook
{
"event": "payout.success",
"deliveryId": "4b50836d-5c5b-4d74-a6e3-70b87f5dfe4f",
"data": {
"id": "po_123",
"payoutId": "po_123",
"merchant_ref": "M01-WD240001",
"merchantRef": "M01-WD240001",
"idempotency_key": "withdrawal-request:req_123",
"idempotencyKey": "withdrawal-request:req_123",
"status": "SUCCESS",
"amount": 100,
"external_ref": "SCB202603050001",
"externalRef": "SCB202603050001"
},
"timestamp": "2026-03-05T08:20:10.000Z",
"webhookId": "wh_123"
}

10) Interactive Docs (Try API Live)

ใช้สำหรับทดสอบเชื่อมต่อแบบเร็วจากหน้า docs โดยตรง (ควรใช้ test key/สภาพแวดล้อมทดสอบ)

Response

ยังไม่มีผลลัพธ์

กด Send Request เพื่อทดสอบ

11) Integration Starter Pack

สำหรับทีม dev ที่ต้องการเชื่อมระบบเร็ว: ใช้ SDK + Postman ด้านล่าง แล้วเริ่ม flow แบบ create payment → /pay/:id → webhook

Starter Flow (Hosted Checkout UI)
Quick Flow ():
 
1) Merchant backend POST /api/v1/payment/create
2) transaction.id response
3) : https://hyronpay.com/pay/<transaction.id>
4) UI Hyronpay
5) merchant webhook payment.success/payment.failed/payment.expired
 
:
- UI
- /api/payment/create-link route dashboard session public API key flow
Node.js Starter: Create Payment + Build /pay/:id URL
const HyronpayClient = require('./paygate-node');
 
const client = new HyronpayClient({
apiKey: process.env.HYRONPAY_API_KEY, // sk_live_...
baseUrl: 'https://api.hyronpay.com/api/v1',
});
 
async function createDepositLink() {
const result = await client.createPayment({
amount: 100,
orderId: 'ORD-10001',
description: 'Topup',
metadata: {
senderAccountNumber: '1673585481',
senderBankCode: 'GSB',
memberName: ' ',
memberNameEn: 'THONGDEE JAINGAM',
customerId: 'u_123',
},
});
 
const paymentUrl = HyronpayClient.buildHostedPaymentUrl({
frontendBaseUrl: 'https://hyronpay.com',
transactionId: result.transaction.id,
});
 
return {
paymentUrl,
transactionId: result.transaction.id,
orderId: result.transaction.orderId,
};
}
Node.js Starter: Verify Webhook Signature
const express = require('express');
const HyronpayClient = require('./paygate-node');
 
const app = express();
app.use(
express.json({
verify: (req, _res, buf) => {
req.rawBody = buf.toString('utf8');
},
})
);
 
app.post('/api/paygate/webhook', (req, res) => {
const signatureHeader = req.header('X-Webhook-Signature') || '';
const ok = HyronpayClient.verifyWebhookSignature({
rawBody: req.rawBody || '',
signatureHeader,
webhookSecret: process.env.HYRONPAY_WEBHOOK_SECRET,
});
 
if (!ok) return res.status(401).json({ error: 'invalid signature' });
 
// TODO: dedupe X-Webhook-Idempotency-Key (fallback: event+transactionId deliveryId)
// map payoutId/orderId
return res.status(200).json({ received: true });
});
Node.js Starter: Create Payout (auto sign)
const HyronpayClient = require('./paygate-node');
const client = new HyronpayClient({ apiKey: process.env.HYRONPAY_API_KEY });
 
async function createPayout() {
return client.createPayout({
amount: 100,
destination: {
bankCode: 'SCB',
accountNumber: '4190621964',
accountName: '',
},
metadata: {
sourceSystem: 'merchant-backoffice',
memberId: 'member_1001',
},
});
}

12) Security Baseline

  • 🔑เก็บ sk_... เฉพาะฝั่ง server (เช่น backend) ห้ามฝังใน frontend/browser
  • 🔒เปิดใช้ HTTPS และจำกัด IP/Origin ตามโครงสร้างระบบของคุณ — สำหรับ webhook ให้ถือ signature verification เป็นชั้นหลัก และ IP allowlist เป็นชั้นรอง
  • 🔄ใช้ idempotency และ signature ทุกคำสั่งถอนเงิน
  • 📋กำหนด rotation policy สำหรับ API key และ webhook secret/signature key