ALL1PAY API v1

ALL1PAY
API Documentation

Integrate seamless payment processing into your application with our powerful REST API. Support for Payin, Payout, and Real-time Webhooks.

Secure Authentication

Merchant API calls verify HMAC-SHA256 signatures and timestamp freshness. Keep signing secrets on your server.

Transaction Tracking

Follow payment status using its reference and distinguish processing from confirmed completion.

Real-time Webhooks

Configure a signing secret to receive signed transaction callbacks, with bounded retries when delivery fails.

Multi-Provider

Routing considers configured priorities, enabled payment flows, amount limits and observed availability.

IP Whitelist

Restrict API access to specific IP addresses or CIDR ranges for enhanced security.

REST API Examples

Ready-to-use code examples in JavaScript, Python, PHP, and cURL.

Quick Start

Prepare your account and integration

1

Create API Keys

Generate your API key pair from the merchant dashboard.

2

Save Your Secret

Store your secret key securely — it's shown only once.

3

Set Callback URL

Configure the callback URL and signing secret in Webhooks (older release: Settings → Integration).

4

Make Your First Call

Confirm the enabled flow, then use the examples. Requests with live credentials create real transactions.

Base URL

bash
https://service.all1pay.cloud/api/v1

Required Headers

HeaderDescription
x-api-keyYour merchant API key (server-side)
x-secret-keyYour secret key
x-timestampUnix timestamp (ms)
x-signatureHMAC-SHA256 signature

Authentication

Secure your API requests with HMAC-SHA256

Signature Calculation

The signature is calculated using your secret key and a combination of request details:

bash
signature = HMAC-SHA256(secret_key, message)

where message = timestamp + method + path + body

Example:
  timestamp = "1706745600000"
  method    = "POST"
  path      = "/api/v1/payin"
  body      = '{"amount":1000,"currency":"THB"}'

  message   = "1706745600000POST/api/v1/payin{\"amount\":1000,\"currency\":\"THB\"}"
  signature = hmac_sha256(secret_key, message)

Important

The timestamp must be within 5 minutes of server time. Sign the path including /api and any query string. For GET requests with no body, use an empty string. For JSON requests, sign compact JSON and send the same body.

Merchant API v1 · 2026-10-01

คู่มือนี้อ้างอิงแอปรุ่นที่เผยแพร่พร้อมกัน การแปลง CIMB, error Payin แบบแยก code และ Test Webhook ต้องใช้ API รุ่นที่รองรับ ระบบรุ่นเก่าอาจตอบ error แบบเดิมหรือยังไม่มีหน้าทดสอบ วันที่เอกสารไม่ใช่การเปลี่ยน URL จาก v1

https://service.all1pay.cloud/api

ตัวอย่างเป็นข้อมูลจำลอง เมื่อใช้ key จริงจะสร้างรายการจริง Postman ปิด POST ไว้จนกว่าจะเปิด allow_live_requests ด้วยตัวเอง

การยืนยันตัวตนและข้อจำกัดคำขอ

Base URL: https://service.all1pay.cloud/api API สำหรับเชื่อมต่อร้านใช้ API credentials ไม่ใช่ JWT ของหน้าแผงควบคุม ทุกคำขอต้องส่ง x-api-key, x-secret-key, x-timestamp, x-signature เก็บ credentials ฝั่ง server ไม่ฝังใน browser/app ลูกค้า

x-timestamp เป็น Unix milliseconds 13 หลัก คลาดจาก server ไม่เกิน ±5 นาที ลายเซ็น hex HMAC-SHA256(secret, timestamp + METHODตัวใหญ่ + pathพร้อมqueryจริง + JSONแบบcompact) รวม /api ด้วย GET และ body ที่ไม่มีหรือ object ว่างใช้ข้อความว่าง เซ็น query ตามลำดับ/encoding ที่ส่งจริง

การเซ็นคำขอ API ฝั่ง server ใช้ JavaScript JSON.stringify(parsedBody) ไม่ใช้ช่องว่างหรือ escape จาก body ดิบ ต้องจัด JSON และลำดับ key ให้ตรง เก็บข้อความ Unicode เป็น UTF-8 (Python ใช้ ensure_ascii=False) และระวังรูปตัวเลข 1000.0 ต่างจาก 1000 ห้ามเรียง key ใหม่เอง ส่วนการรับ webhook ต้องตรวจจาก bytes ดิบเดิม ตัวอย่าง JavaScript และ Postman ใช้ JSON.stringify ให้แล้ว

ร้านต้อง ACTIVE และ IP ต้องผ่านรายการอนุญาต API หากตั้งไว้ credentials/ลายเซ็น/เวลาผิดได้ 401 ร้านปิดหรือ IP ไม่ผ่านได้ 403 รายการ IP ของ API แยกจากหน้าแผงควบคุม

จำกัดต่อร้าน นับรวม API key ทุกชุด: คำขอสร้างรายการ (payin, payout, verify-slip, transfer) 100 ครั้งที่ผ่านการตรวจต่อนาที และคำขออ่าน (สถานะ, รายการ, ยอดเงิน) อีก 200 ครั้งต่อนาทีแยกกัน การอ่านสถานะถี่จึงไม่ทำให้สร้าง payin หรือส่งสลิปไม่ได้ 429 ให้รอตามวินาทีใน Retry-After ใช้ backoff และ webhook แทน polling ถี่ JSON ปกติไม่เกิน 1 MiB; verify-slip ไม่เกิน 8 MiB เกินได้ 413

ส่งยอดเป็น JSON number และเลขบัญชี/รหัสธนาคารเป็น string ค่ายอดที่อ่านอาจเป็นข้อความทศนิยม ใช้วิธีคำนวณทศนิยมที่ไม่ตัดเศษ ตัวอย่างเป็นข้อมูลจำลองและเรทตัวอย่าง POST จาก Playground/Postman ทำงานจริงบน environment ที่เลือก

รหัสธนาคาร Payin และชื่อฟิลด์

Payin ใช้ bankName + bankNumber ระบุบัญชีต้นทางลูกค้า Payout ใช้ bankCode + accountNumber + accountName ระบุผู้รับ ต้อง map ชื่อไทยหรือ ID ภายในร้านเป็นรหัสธนาคาร ห้ามส่ง boolean, ID ตัวเลข หรือข้อความ false

Payin รองรับ alias ที่ยืนยันแล้วเฉพาะ CIMB → CIMBT ตัดช่องว่างหัวท้ายและปรับตัวพิมพ์ตามตาราง รวม Mizuho และ LH BANK alias อื่นที่ไม่รองรับถูกปฏิเสธ การละ/null ยังเป็นทางเลือกของ flow ที่ไม่ต้องใช้ ไม่ใช่วิธีเลี่ยงข้อมูลธนาคารที่ไม่ทราบ

ตารางคือรหัสที่ Payin รับ ไม่ได้รับประกันว่าทุกธนาคาร/flow เปิดอยู่ในทุก Provider ส่วน Payout ใช้สัญญารหัสตาม Provider ห้ามนำ mapping จ่ายเงินเฉพาะ Sandpay ไปใช้กับเจ้าอื่นหรือสมมติว่า alias Payin ใช้กับ Payout ด้วย

รหัสที่ Payin รับ — ยังขึ้นกับการเปิดใช้ของ Provider
bankNameธนาคาร
KBANKกสิกรไทย
SCBไทยพาณิชย์
BBLกรุงเทพ
KTBกรุงไทย
BAYกรุงศรีอยุธยา
TTBทีเอ็มบีธนชาต
GSBออมสิน
BAACธ.ก.ส.
GHBอาคารสงเคราะห์
KKPเกียรตินาคินภัทร
TISCOทิสโก้
CIMBTซีไอเอ็มบี ไทย
UOBTยูโอบี
LH BANKแลนด์ แอนด์ เฮ้าส์
TCRBไทยเครดิต
ISBTอิสลามแห่งประเทศไทย
SMEเอสเอ็มอี พัฒนา
EXIMเพื่อการส่งออกและนำเข้า
SCBTสแตนดาร์ดชาร์เตอร์ด (ไทย)
CITIซิตี้แบงก์
HSBCเอชเอสบีซี
DBดอยซ์แบงก์
BNPPบีเอ็นพี พารีบาส์
JPMเจพีมอร์แกน เชส
BANAแบงก์ออฟอเมริกา
BOCแบงก์ออฟไชน่า (ไทย)
ICBCไอซีบีซี (ไทย)
MEGAเมกะ สากลพาณิชย์
OCBCโอซีบีซี
RHBอาร์เอชบี
IOBอินเดียนโอเวอร์ซีส์
SMBCซูมิโตโม มิตซุย
SMTBซูมิโตโม มิตซุย ทรัสต์
Mizuhoมิซูโฮ

HTTP error และผลธุรกรรม

แยกคำขอ HTTP สำเร็จ การสร้างรายการ และเงินสำเร็จ HTTP 201 ของ POST ไม่ใช่หลักฐานรับเงิน Payin/Payout ต้องดู status/errorMessage ส่วนสลิปดู success ห้ามเครดิตจากลิงก์ HTTP status หรือ providerData เพียงอย่างเดียว

400 อาจเป็นข้อมูลผิด การตั้งค่า รายการซ้ำ หรือเงินไม่พอ message อาจเป็นข้อความหรือรายการข้อความ เฉพาะ error Payin ที่ระบุด้านล่างรับประกัน code ห้ามใช้การตัดข้อความไทย/อังกฤษเป็นรหัสถาวรหรือสมมติว่าทุก error มี code

409 อาจหมายถึงหลักฐานต้องตรวจ ไม่ได้แปลว่าไม่มีการเปลี่ยนแปลงใด ๆ ถ้ามี referenceId/reviewRequired ให้เก็บและหยุดส่งซ้ำอัตโนมัติ 5xx/timeout ก็ยังสรุปไม่ได้ ส่วนข้อมูลผิด 400 ต้องแก้ข้อมูล ไม่ใช่ยิงเดิมซ้ำ

HTTP 400 · Payin
codeฟิลด์เพิ่มเติมการจัดการ
INVALID_BANK_CODEsupportedBankCodesรหัสธนาคาร Payin ที่ส่งไม่ถูกต้อง ดู supportedBankCodes การปฏิเสธนี้ยังไม่สร้างธุรกรรม
PAYIN_AMOUNT_BELOW_MINIMUMminimumAmountต่ำกว่าขั้นต่ำเส้นทางที่ใช้ได้ อ่าน minimumAmount ไม่กำหนดค่าตายตัวทุกร้าน
PAYIN_PROVIDER_UNAVAILABLE—ไม่มีเส้นทางรับเงินที่เปิดและใช้ได้สำหรับร้าน ให้ support ตรวจการผูก/สถานะ
PAYIN_FLOW_NOT_SUPPORTED—เส้นทางที่ใช้ได้ไม่รองรับ flow ที่ขอ
PAYIN_AMOUNT_ABOVE_MAXIMUMmaximumAmountเกินยอดสูงสุดของเส้นทางที่ใช้ได้
PAYIN_AMOUNT_OUT_OF_RANGE—อยู่นอกช่วงยอดที่เส้นทางรองรับ เช่น ช่องว่างระหว่างสองช่วง ให้ support ตรวจ
HTTP 400 · JSON
{
  "statusCode": 400,
  "code": "PAYIN_AMOUNT_BELOW_MINIMUM",
  "message": "ยอดเงินต่ำกว่าขั้นต่ำ: กรุณาสร้างรายการรับเงินตั้งแต่ 300 บาท",
  "minimumAmount": 300
}

HTTP 409 · Payout review · JSON
{
  "message": "พักรายการเพื่อตรวจสอบข้อมูล Provider ยังไม่ลงเงินหรือคืนเงิน กรุณาติดต่อทีมดูแล (SETTLEMENT_REVIEW_REQUIRED)",
  "referenceId": "TXN-EXAMPLE-PAYOUT",
  "reviewRequired": true
}

ตรวจปัญหาและปรับระบบเดิม

ถ้าบางลูกค้าใช้ได้แต่บางรายไม่ได้ ให้เทียบ JSON ที่ส่งและผลตอบของแต่ละรายการ ชื่อธนาคารที่แสดงเหมือนกันอาจ map เป็นรหัสคนละค่า กรุงศรีใช้ BAY; CIMB ไทยใช้ CIMBT แก้ mapping และหยุดที่ฝั่งร้านหากหาไม่เจอ ห้ามส่ง false หรือแทนเป็นธนาคารอื่น อายุบัญชีเพียงอย่างเดียวไม่บอกสาเหตุ

Send Test Order ในเครื่องมือ Provider ของแอดมินเรียกต้นทางโดยตรง ไม่ได้ทดสอบขั้นตอนเลือกเส้นทาง/ค่าธรรมเนียม/กระเป๋าของร้านครบ การดูเส้นทางใหม่เป็นการอ่านเงื่อนไข ไม่ได้สร้างออเดอร์หรือลิงก์จ่ายเงินจริง ต้องตรวจผ่าน API ของร้านที่ผูก Provider และส่ง flowType ชัดเจน

แยกข้อความให้ลูกค้า: ธนาคารผิดให้แก้ธนาคารต้นทาง; ต่ำกว่าขั้นต่ำให้แสดง minimumAmount; ไม่มี Provider ให้ทีมงานตรวจการผูกร้าน สถานะ Provider/บัญชีและความพร้อม อย่าแปลง error ทุกชนิดเป็นไม่มีผู้ให้บริการ หากได้ paymentUrl แล้วลูกค้ายังไม่ชำระ การหมดอายุภายหลังต่างจากการสร้างไม่ผ่าน

ก่อนเปลี่ยนระบบเดิม ตรวจชื่อ/ชนิดฟิลด์ รหัสธนาคาร slip/qr เลข order ที่คงเดิม การคิดทศนิยม การตรวจลายเซ็น และ webhook ซ้ำ/มาช้า ทดสอบธนาคารผิด/ต่ำกว่าขั้นต่ำ/เส้นทางปิดในสภาพแวดล้อมแยกที่ตกลงกัน webhook.test ต้องไม่เปลี่ยนยอดเงิน ยืนยันรุ่น API ที่ deploy กับ ALL1PAY ก่อนพึ่ง error code ใหม่

แจ้ง support ด้วยรหัสร้าน referenceId ถ้าได้รับ orderId เวลาส่งพร้อมเขตเวลา ยอด flowType รหัสธนาคาร HTTP status และ code/message ปิดเลขบัญชีและข้อมูลส่วนตัว ห้ามส่ง API secret, webhook secret หรือ header ยืนยันตัวตนเต็ม ตรวจรายการเดิมก่อนสร้างการชำระซ้ำ

ค่าธรรมเนียมและผลต่อกระเป๋า

เลือกเรทร้านแยกรับและจ่าย หากตั้งเปอร์เซ็นต์ร้านไว้รวม 0 ใช้เปอร์เซ็นต์และค่าคงที่ของร้าน มิฉะนั้นใช้เรทการผูก Provider ที่เลือก เลือกหนึ่งแหล่งไม่บวกสองเรท และต้นทุน Provider ไม่ใช่ค่าธรรมเนียมร้านอีกชั้น

ค่าธรรมเนียม = ยอด × เปอร์เซ็นต์ / 100 + ค่าคงที่ ปัดสองตำแหน่ง Payin สำเร็จเครดิตยอดหักค่าธรรมเนียม Payout พักยอดบวกค่าธรรมเนียม ผู้รับได้เงินต้น amount รายการบันทึกยอด/ค่าธรรมเนียม/เรทของตัวเอง การเปลี่ยนเรทปัจจุบันไม่แก้รายการย้อนหลัง

ตัวอย่างเท่านั้น: 1,000 บาท เรทรับ 1.5% ไม่มีค่าคงที่ ค่าธรรมเนียม 15 สุทธิ 985 ส่วนจ่าย 1,000 เรท 0.2% ค่าธรรมเนียม 2 totalDebit 1,002 อ่านค่าธรรมเนียมรายการจริง ไม่ตั้งเรทตัวอย่างตายตัว

รายการซ้ำ timeout และการติดตามผล

Payout ต้องมี orderId ส่วน Payin แนะนำอย่างยิ่ง เลขไม่ซ้ำภายในร้านทั้งสองประเภท สร้างซ้ำได้ HTTP 400 ไม่ได้ตอบผลเดิมกลับมา และไม่รองรับ header Idempotency-Key การเซ็นเวลาใหม่ไม่ได้เปลี่ยนรายการธุรกิจเดิมให้เป็นรายการใหม่

บันทึก orderId/คำขอก่อนส่งและ referenceId ทันทีที่ได้รับ หาก timeout ให้ตรวจ reference เดิมหรือหา merchantOrderId ในรายการแบบแบ่งหน้า หากไม่ชัดให้ติดต่อ support ห้ามออก orderId Payout ใหม่เพื่อข้ามรายการซ้ำ/error/ผลที่ไม่ทราบ

PENDING/PROCESSING ไม่ใช่ล้มเหลวสุดท้าย และ EXPIRED ไม่ยืนยันว่าไม่มีคนโอน Payin EXPIRED อาจเป็น COMPLETED ภายหลังเมื่อยืนยันหลักฐาน ต้องรองรับ callback ช้า/ซ้ำและการแก้สถานะ เวลาข้อความใหม่ไม่ใช่เงินรายการใหม่

กันส่งซ้ำด้วย webhook-id และกันบันทึกเงินซ้ำระดับรายการด้วย referenceId/type ในฐานข้อมูล การส่งใหม่ด้วยมืออาจมี webhook ID ใหม่แต่เป็นรายการเดิม ถ้าลำดับสถานะขัดกันให้ตรวจ status/support ห้ามย้อนเครดิตที่ยืนยันแล้วจากข้อความเก่า

สถานะธุรกรรม
statusความหมาย
PENDINGสร้างแล้วหรือรอดำเนินการ/ตรวจสอบ Payout อาจพักเงินแล้ว
PROCESSINGกำลังดำเนินการ ยังไม่ยืนยันเงินสำเร็จ
COMPLETEDALL1PAY บันทึกสำเร็จแล้ว
FAILEDบันทึกล้มเหลว อย่าสับสนกับ timeout/รอตรวจ ตรวจรายการเดิมก่อนชำระใหม่
EXPIREDหมดอายุ ไม่ใช่หลักฐานว่าไม่มีการโอน อาจกู้ Payin ด้วยหลักฐานที่ตรวจแล้ว
REFUNDEDรายการสำเร็จเดิมถูกคืนเงินผ่านกระบวนการที่ได้รับอนุญาต

Webhook รายการเงินจริง

ตั้ง callback URL และ Webhook Secret ที่ Webhooks → Settings (รุ่นเก่า: Settings → Integration) callbackUrl เฉพาะรายการมีลำดับก่อนค่าเริ่มต้น นี่คือสัญญา callback ของ ALL1PAY ไม่ใช่ payload order.paid/payout.approved ของต้นทาง

รับ POST JSON มี referenceId, merchantOrderId, status, amount, currency, type ฟิลด์เวลาแตกต่างกัน: การเปลี่ยนสถานะอาจมี completedAt ส่งซ้ำด้วยมืออาจมี resent=true, resentAt ห้ามใช้เวลาตัดสินเงินสำเร็จ ไม่รับประกัน callback ทุกสถานะกลางหรือการปฏิเสธสร้างรายการ ต้องเก็บ/ตรวจผล create ด้วย

Header มี Content-Type: application/json และ x-webhook-id ส่วน x-webhook-signature เป็น hex HMAC-SHA256(JSON body ดิบ, webhook secret ร้าน) ส่งเมื่อมี secret ตั้งไว้เท่านั้น ต้องตั้ง secret ก่อนใช้งานรับลายเซ็น และปลายทางต้องปฏิเสธลายเซ็นหาย/ผิด

ตรวจลายเซ็นจาก bytes เดิมก่อนแปลง/จัดรูป JSON แล้วบันทึกหรือเข้าคิวอย่างคงทนและตอบ 2xx โดยเร็ว ส่งจริงมี HTTP timeout 10 วินาที ไม่ตาม redirect หากล้มเหลว/ไม่ใช่ 2xx ส่งซ้ำหลัง 1, 5, 15, 60 นาที รวมไม่เกิน 5 ครั้ง เวลาจริงอาจช้าตาม outage/load URL ที่ไม่ปลอดภัยหยุดส่งซ้ำ

ส่ง webhook ไม่สำเร็จไม่ได้แปลว่าเงินล้มเหลว ตรวจ Webhooks → Delivery Logs (เมนูเก่า Webhook Logs) และ status API ห้ามสร้าง Payout ใหม่เพียงเพราะปลายทาง callback ล้มเหลว

Payment event · JSON
{
  "referenceId": "TXN-EXAMPLE-PAYIN",
  "merchantOrderId": "PAYIN-EXAMPLE-001",
  "status": "COMPLETED",
  "amount": 1000,
  "currency": "THB",
  "type": "PAYIN",
  "completedAt": "2026-09-16T07:00:00.000Z"
}

ตรวจลายเซ็นจาก body ดิบก่อนประมวลผล

ใช้ x-webhook-signature และ webhook secret ที่ตั้งไว้ ไม่ใช่ API secret เมื่อตั้งการลงลายเซ็นแล้วให้ปฏิเสธลายเซ็นผิด/ไม่มี บันทึก event อย่างทนทานและกันซ้ำก่อนตอบ 2xx แยก event ทดสอบโดยไม่เปลี่ยนยอดเงิน

JavaScript
const crypto = require('node:crypto');

// rawBody is the original request body, before JSON parsing.
function verifyWebhook(rawBody, signature, webhookSecret) {
  if (!/^[a-f0-9]{64}$/i.test(signature || '')) return false;
  const expected = crypto.createHmac('sha256', webhookSecret).update(rawBody).digest();
  return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), expected);
}

Test Webhook — ทดสอบการเชื่อมต่อ

ใช้ได้เมื่อเปิดรุ่น Webhooks hub และเป็นเจ้าของร้านที่ active ส่ง webhook.test, test=true และ ID ขึ้นต้น TEST- ไม่มีจำนวนเงิน/สถานะชำระ ตรวจลายเซ็น JSON ดิบแล้วตอบรับ ห้ามเพิ่ม/หักยอดกระเป๋าจากเหตุการณ์นี้

ระบุ URL ทดสอบ HTTPS สาธารณะ port 443 โดยไม่เปลี่ยนค่าเริ่มต้นที่บันทึก รอทดสอบ 5 วินาที ไม่มี retry อัตโนมัติ บันทึกใน Test history แยก HTTP 2xx แปลว่าปลายทางรับคำขอ ไม่ยืนยันว่าโค้ดตรวจลายเซ็น/บันทึกเงินถูกต้อง

จำกัดรายการทดสอบใหม่ 1 ครั้งต่อ 30 วินาที และ 10 ครั้งต่อชั่วโมงต่อร้าน รวมทั้งความจุส่วนกลาง หากผลหายให้ตรวจ Test history/ผลรายการเดิมก่อนส่งใหม่

Test event · JSON
{
  "event": "webhook.test",
  "test": true,
  "id": "TEST-example",
  "createdAt": "2026-09-16T07:00:00.000Z",
  "message": "ALL1PAY connection test. No payment is associated with this event."
}

API Endpoints

สร้างรายการรับเงิน

POST /v1/payin
JSON request body
FieldTypeจำเป็นคำอธิบาย
amountnumberใช่จำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม
currencystringไม่ค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน
orderIdstringไม่แนะนำให้ระบุและไม่ซ้ำภายในร้านทั้ง Payin และ Payout หากละจะไม่มีการกันสร้างซ้ำด้วยเลขร้านนี้
providerAccountIdstringไม่ละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้
callbackUrlstringไม่ปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน
customerNamestringไม่ชื่อลูกค้า ไม่ใช่หลักฐานยืนยันเจ้าของบัญชี
customerEmailstringไม่อีเมลลูกค้า
bankNamestringไม่รหัสธนาคารต้นทางของลูกค้า ส่งคู่ bankNumber สำหรับช่องทาง slip ที่ผูกบัญชีผู้โอน ดูตารางธนาคาร Payin; CIMB แปลงเป็น CIMBT ไม่ใช่ธนาคารปลายทางและไม่ใช่ฟิลด์ bank_name
bankNumberstringไม่เลขบัญชีต้นทางลูกค้า ส่งตัวเลขเป็นข้อความและเก็บศูนย์นำหน้า การตรวจความยาว/เจ้าของบัญชียังขึ้นกับ Provider
customerPhonestringไม่เบอร์ลูกค้าหากเส้นทางนั้นต้องใช้
flowTypeslip | qrไม่ค่าเริ่มต้น slip ควรส่ง slip หรือ qr ชัดเจน metadata.channel ไม่ใช้เลือก flow กลาง และร้านต้องเปิดช่องทางนั้นไว้
metadataobjectไม่ข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ
Request · JSON
{
  "amount": 1000,
  "currency": "THB",
  "orderId": "PAYIN-EXAMPLE-001",
  "flowType": "slip",
  "bankName": "SCB",
  "bankNumber": "0012345678"
}

Response example · HTTP 201 · JSON
{
  "referenceId": "TXN-EXAMPLE-PAYIN",
  "status": "PROCESSING",
  "paymentUrl": "https://payment.example.com/order/example",
  "amount": 1000,
  "currency": "THB",
  "providerRefId": "ORD-EXAMPLE",
  "providerData": {}
}

ฟิลด์ผลลัพธ์: referenceId, status, paymentUrl?, amount, currency, providerRefId?, providerData, errorMessage?

  • HTTP 201 อาจมี status FAILED และ errorMessage เมื่อต้นทางปฏิเสธ PROCESSING พร้อมลิงก์หมายถึงสร้างรายการ ไม่ใช่ชำระแล้ว ตรวจ body ก่อนแสดงหน้าจ่ายเงิน
  • QR: ส่ง flowType=qr เมื่อร้านเปิดใช้ ละข้อมูลธนาคารได้ในเส้นทางที่ไม่ต้องใช้ ส่วน slip ให้แสดงหน้าชำระ/บัญชีปลายทางที่ได้รับและส่งสลิปจริง ห้ามสร้างข้อมูลปลายทางเอง
  • paymentUrl/providerRefId อาจไม่มี providerData มีรูปแบบตาม Provider ไม่รับประกัน qrCode, qrCodeUrl หรือ expiresAt ระดับบน อย่าสมมติว่าทุกเจ้าส่ง destination_bank หรือ QR base64 ในชื่อเดียวกัน
  • หากคำตอบหายหรือได้ 5xx อาจสร้างรายการแล้ว ต้องตรวจรายการเดิมก่อนสร้างใหม่ Endpoint นี้สร้างรายการจริง ไม่ใช่ sandbox

ตรวจสลิป

POST /v1/payin/:referenceId/verify-slip
JSON request body
FieldTypeจำเป็นคำอธิบาย
qrStringstringไม่ไม่บังคับ ส่งคู่กับ imageBase64 ได้: ข้อความ QR ที่อ่านจากสลิปโอนเงิน ไม่ใช่ QR สำหรับจ่ายเงิน บาง Provider ตรวจจากข้อความนี้อย่างเดียวไม่ได้
imageBase64stringไม่ส่งทุกครั้ง: รูปสลิปจริงแบบ base64 เป็น JPEG หรือ PNG (data:image/jpeg;base64,... หรือ base64 ล้วน) บาง Provider ตรวจได้จากรูปเท่านั้นและจะปฏิเสธถ้าส่งแค่ qrString HTTP body รวมไม่เกิน 8 MiB base64 ทำให้ขนาดโตขึ้นราว 1/3 รูปจึงควรไม่เกินราว 6 MB
Request · JSON
{
  "imageBase64": "data:image/jpeg;base64,REPLACE_WITH_SLIP_IMAGE_BASE64",
  "qrString": "REPLACE_WITH_ACTUAL_SLIP_QR"
}

Response example · HTTP 201 · JSON
{
  "success": true,
  "status": "paid",
  "applied": true,
  "rawResponse": {}
}

ฟิลด์ผลลัพธ์: success, status?, applied?, alreadyCompleted?, pending?, code?, message?, errorMessage?, rawResponse?

  • ส่งรูปสลิป (imageBase64) ทุกครั้ง จะส่ง qrString มาด้วยก็ได้ API รับค่าใดค่าหนึ่งก็ได้ แต่ Provider ที่ตรวจจากรูปเท่านั้นจะตอบ success=false ถ้าส่งแค่ qrString ต้องเป็นรายการของร้านและมีเลขต้นทาง Provider ต้องรองรับการตรวจสลิป รายการ Payin PROCESSING หรือ EXPIRED อาจกู้คืนได้
  • เติมเครดิตครั้งเดียวต่อ 1 ออเดอร์ เฉพาะเมื่อได้คำตอบ applied=true หรือสถานะธุรกรรม/callback เป็น COMPLETED ส่งสลิปเข้าออเดอร์ที่ COMPLETED แล้วจะได้ success=false, code=ALREADY_PAID, alreadyCompleted=true คือออเดอร์จ่ายแล้ว ห้ามเติมซ้ำ สลิปที่เคยใช้จ่ายออเดอร์อื่นแล้วจะได้ success=false, code=SLIP_ALREADY_USED ถ้า Provider ยังไม่ตอบผล จะได้ success=false, status=pending, pending=true ให้ลูกค้ารอ แล้วติดตามสถานะธุรกรรม
  • ต้นทางปฏิเสธอาจตอบ HTTP 201 พร้อม success=false และ errorMessage หลักฐานที่ต้องตรวจอาจได้ HTTP 409 ห้ามเครดิตจาก rawResponse หรือคำว่า paid ของต้นทาง ให้ยืนยันสถานะธุรกรรม ALL1PAY

สร้างรายการจ่ายเงิน

POST /v1/payout
JSON request body
FieldTypeจำเป็นคำอธิบาย
amountnumberใช่จำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม
currencystringไม่ค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน
bankCodestringใช่รหัสธนาคารผู้รับที่ Provider จ่ายเงินรองรับ การแปลง CIMB ของ Payin ไม่ได้ใช้กับ Payout ต้องยืนยัน mapping ของเส้นทางจ่ายเงิน
accountNumberstringใช่เลขบัญชีผู้รับ เก็บศูนย์นำหน้า
accountNamestringใช่ชื่อเจ้าของบัญชีผู้รับ
orderIdnon-empty stringใช่เลขรายการร้านที่ต้องไม่ซ้ำทั้ง Payin และ Payout เก็บเลขรายการเดิมไว้ขณะตรวจผลที่ยังไม่ชัดเจน
providerAccountIdstringไม่ละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้
callbackUrlstringไม่ปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน
metadataobjectไม่ข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ
Request · JSON
{
  "amount": 1000,
  "currency": "THB",
  "bankCode": "KBANK",
  "accountNumber": "0012345678",
  "accountName": "Example Recipient",
  "orderId": "PAYOUT-EXAMPLE-001"
}

Response example · HTTP 201 · JSON
{
  "referenceId": "TXN-EXAMPLE-PAYOUT",
  "status": "PROCESSING",
  "reviewRequired": false,
  "amount": 1000,
  "currency": "THB",
  "feeAmount": 2,
  "totalDebit": 1002,
  "providerRefId": "PAYOUT-EXAMPLE",
  "providerData": {}
}

ฟิลด์ผลลัพธ์: referenceId, status, reviewRequired, amount, currency, feeAmount, totalDebit, providerRefId?, providerData, errorMessage?

  • amount คือเงินต้นที่ขอจ่ายผู้รับ feeAmount คือค่าธรรมเนียมร้าน และ totalDebit=amount+feeAmount พักเงินรวมนี้ระหว่างดำเนินการ ตัวอย่าง 0.2% ไม่ใช่เรทของทุกร้าน
  • timeout, ไม่มีเลขต้นทาง หรือ reviewRequired=true ไม่ใช่หลักฐานว่าล้มเหลวหรือคืนเงินแล้ว ความผิดพลาดที่ยังสรุปไม่ได้อาจตอบ HTTP 409 พร้อม referenceId และ reviewRequired=true หยุดสร้างซ้ำด้วย orderId ใหม่แล้วติดตามรายการเดิม
  • HTTP 201 อาจเป็น FAILED หลังปฏิเสธชัดเจน หรือ PENDING/PROCESSING ที่รอตรวจ COMPLETED จึงเป็นสถานะสำเร็จที่ยืนยันแล้ว ไม่มีการส่ง Payout รายการนี้ไป Provider อื่นอัตโนมัติ

ตรวจสถานะรายการ

GET /v1/transaction/:referenceId
Response example · HTTP 200 · JSON
{
  "referenceId": "TXN-EXAMPLE-PAYIN",
  "orderId": "PAYIN-EXAMPLE-001",
  "type": "PAYIN",
  "status": "COMPLETED",
  "amount": "1000",
  "currency": "THB",
  "fee": "15",
  "createdAt": "2026-09-16T07:00:00.000Z",
  "completedAt": "2026-09-16T07:01:00.000Z"
}

ฟิลด์ผลลัพธ์: referenceId, orderId, type, status, amount, currency, fee, createdAt, completedAt

  • อ่านสถานะที่ ALL1PAY บันทึก ไม่ได้ยิงถาม Provider สด referenceId เป็นเลข ALL1PAY ไม่ใช่ orderId หรือ providerRefId เลขที่ไม่มีหรือของร้านอื่นได้ HTTP 400 Transaction not found
  • Endpoint นี้ใช้ orderId และ fee แต่รายการรวม/webhook ใช้ merchantOrderId ยอด amount และ fee ในคำตอบนี้เป็นข้อความทศนิยม อย่าสมมติว่าทุก endpoint ส่งยอดเป็น JSON number และ endpoint นี้ยังไม่ส่ง reviewRequired

รายการธุรกรรม

GET /v1/transactions
Query parameters
FieldTypeจำเป็นคำอธิบาย
pagequery integerไม่ค่าเริ่มต้น 1 ไม่รับ offset เกิน 10,000 แถว ใช้ nextCursor เมื่ออ่านประวัติลึก
limitquery integer 1–100ไม่ค่าเริ่มต้น 20
typequery PAYIN | PAYOUTไม่กรองประเภทรายการ
statusquery statusไม่กรองสถานะตามตารางสถานะ
cursorquery stringไม่คัดลอก meta.nextCursor ตามเดิม คงตัวกรอง type/status และละ page หากเป็น null หรือ data ว่างให้หยุด
Response example · HTTP 200 · JSON
{
  "data": [
    {
      "id": "EXAMPLE-ID",
      "referenceId": "TXN-EXAMPLE-PAYIN",
      "merchantOrderId": "PAYIN-EXAMPLE-001",
      "type": "PAYIN",
      "status": "PROCESSING",
      "amount": "1000",
      "currency": "THB",
      "merchantFeeAmount": "15",
      "customerName": null,
      "customerEmail": null,
      "bankCode": null,
      "accountNumber": null,
      "accountName": null,
      "paymentUrl": "https://payment.example.com/order/example",
      "providerRefId": "ORD-EXAMPLE",
      "expiredAt": null,
      "completedAt": null,
      "failedReason": null,
      "createdAt": "2026-09-16T07:00:00.000Z",
      "updatedAt": "2026-09-16T07:00:00.000Z",
      "reviewRequired": false,
      "metadata": {
        "bankName": "SCB",
        "bankNumber": "0012345678"
      }
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "limit": 20,
    "totalPages": 1,
    "nextCursor": null
  }
}

ฟิลด์ผลลัพธ์: data, meta.total, meta.page, meta.limit, meta.totalPages, meta.nextCursor

  • เรียงใหม่ก่อนตาม createdAt/id ตัวกรองและ cursor จำกัดเฉพาะร้าน Public v1 ไม่รองรับ dateFrom, dateTo, search หรือค้นด้วย orderId อย่าอ้างคำอธิบาย Postman เก่าที่ระบุว่าทำได้
  • ใช้ pagination แบบจำกัดเพื่อหารายการที่คำตอบหายด้วย merchantOrderId แล้วเก็บ referenceId หากยังไม่แน่ใจให้ติดต่อ support ที่นี่มี reviewRequired ส่วน metadata ส่งเฉพาะ bankName/bankNumber ไม่ใช่ข้อมูลเสริมทั้งหมด ยอดที่เป็น Decimal ส่งเป็นข้อความ

ยอดกระเป๋าร้าน

GET /v1/balance
Response example · HTTP 200 · JSON
{
  "merchantId": "EXAMPLE-MERCHANT",
  "currency": "THB",
  "payinBalance": 50000,
  "payoutBalance": 12000,
  "holdBalance": 3000,
  "totalBalance": 62000,
  "availablePayout": 11000,
  "maxSinglePayout": 11000,
  "updatedAt": "2026-09-16T07:00:00.000Z"
}

ฟิลด์ผลลัพธ์: merchantId, currency, payinBalance, payoutBalance, holdBalance, totalBalance, availablePayout, maxSinglePayout, updatedAt

  • payinBalance ได้เครดิตสุทธิหลัง Payin สำเร็จ payoutBalance คือกระเป๋าจ่ายเงิน holdBalance คือยอดพัก totalBalance=payinBalance+payoutBalance ไม่รวม holdBalance
  • availablePayout หักยอด freeze จ่ายเงินที่ป้องกันไว้และไม่ติดลบ จึงอาจต่ำกว่า payoutBalance ยอดที่อ่านไม่ได้รับประกันว่า Payout ถัดไปจะผ่าน เพราะยังมีการจัดสรรต่อ Provider และรายการพร้อมกัน
  • maxSinglePayout คือยอดสูงสุดที่ Payout หนึ่งรายการถอนได้ตอนนี้ เพราะ Payout แต่ละรายการจ่ายจากบัญชีผู้ให้บริการบัญชีเดียว เมื่อยอดแยกอยู่หลายบัญชี ค่านี้จึงอาจต่ำกว่า availablePayout ยอดที่มากกว่านี้ให้แบ่งเป็นหลายรายการ

โยกเงินรับไปกระเป๋าจ่าย

POST /v1/transfer
JSON request body
FieldTypeจำเป็นคำอธิบาย
amountnumberใช่จำนวนเงินย้ายจากกระเป๋ารับเงินไปกระเป๋าจ่ายเงิน อย่างน้อย 1 บาท ต้องมียอดรับเงินที่ใช้ได้เพียงพอ
Request · JSON
{
  "amount": 1000
}

Response example · HTTP 201 · JSON
{
  "payinBefore": 50000,
  "payinAfter": 49000,
  "payoutBefore": 12000,
  "payoutAfter": 13000,
  "transferAmount": 1000
}

ฟิลด์ผลลัพธ์: payinBefore, payinAfter, payoutBefore, payoutAfter, transferAmount

  • โยกเงินในกระเป๋าร้านทันที ไม่ได้โอนไปบัญชีธนาคารภายนอก ยอดรับไม่พอได้ HTTP 400 ขั้นต่ำ Provider ไม่ใช้กับการโยกภายในนี้
  • Endpoint นี้ไม่มี orderId หรือ idempotency key การส่งซ้ำอาจโยกซ้ำ หาก timeout ให้ตรวจ Wallet Activity และติดต่อ support ก่อน POST อีกครั้ง ห้าม retry อัตโนมัติ

Integration Resources

Use the signed REST API examples below. No SDK package download is published on this page.

View JavaScript, Python, PHP and cURL examples

Code Examples

Copy-paste examples to get started quickly

javascript
const crypto = require('node:crypto');

async function createPayin() {
const apiKey = process.env.ALL1PAY_API_KEY;
const secret = process.env.ALL1PAY_API_SECRET;
const url = new URL('https://service.all1pay.cloud/api/v1/payin');
const timestamp = Date.now().toString();
const body = JSON.stringify({
  "amount": 1000,
  "currency": "THB",
  "orderId": "ORDER-12345",
  "flowType": "qr",
  "customerName": "Example Customer"
});
const message = timestamp + 'POST' + url.pathname + url.search + body;
const signature = crypto.createHmac('sha256', secret).update(message).digest('hex');
const response = await fetch(url, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey,
    'x-secret-key': secret, 'x-timestamp': timestamp, 'x-signature': signature },
  body,
});
const result = await response.json();
// Persist referenceId + orderId even when HTTP/business processing fails.
console.log({ httpStatus: response.status, ...result });
if (!response.ok) throw new Error('ALL1PAY HTTP ' + response.status + ': ' + JSON.stringify(result));
if (result.status === 'FAILED' || result.reviewRequired) throw new Error('Payin not accepted: ' + JSON.stringify(result));
// PROCESSING / paymentUrl means an order exists, not that money was received.
// Credit only after verified COMPLETED evidence; reconcile timeouts before retrying.
return result;
}

createPayin().catch(error => { console.error(error); process.exitCode = 1; });

Request Preview

Preview a request body without sending a payment

Configure Request

Currency: THB · flowType: qr. The preview updates as you type. Enabled flows and amount limits depend on your account.

Request Body

json
{
  "amount": 1000,
  "currency": "THB",
  "orderId": "ORDER-12345",
  "flowType": "qr",
  "customerName": "Example Customer"
}

Use the signed example above to send this body from your server. A successful create response is not proof that payment has completed.

Ready to Get Started?

Apply for a merchant account, or review the integration examples before connecting your system.