{
  "info": {
    "name": "ALL1PAY Merchant API v1",
    "description": "Revision 2026-10-01. This reference describes the matching application release. The CIMB payin alias, typed payin errors and Test Webhook require that release; older deployments may return older errors or lack the test page. Revision is a documentation date, not a new URL version.\n\nคู่มือนี้อ้างอิงแอปรุ่นที่เผยแพร่พร้อมกัน การแปลง CIMB, error Payin แบบแยก code และ Test Webhook ต้องใช้ API รุ่นที่รองรับ ระบบรุ่นเก่าอาจตอบ error แบบเดิมหรือยังไม่มีหน้าทดสอบ วันที่เอกสารไม่ใช่การเปลี่ยน URL จาก v1\n\nPOST requests are disabled until allow_live_requests=true. Set stable order IDs. Read the bundled English/Thai reference before using live credentials. There is no Idempotency-Key header or automatic replay of duplicate orderId.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://service.all1pay.cloud/api",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "",
      "type": "string"
    },
    {
      "key": "secret_key",
      "value": "",
      "type": "string"
    },
    {
      "key": "allow_live_requests",
      "value": "false",
      "type": "string"
    },
    {
      "key": "payin_order_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "payout_order_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "reference_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "image_base64",
      "value": "",
      "type": "string"
    },
    {
      "key": "qr_string",
      "value": "",
      "type": "string"
    }
  ],
  "auth": {
    "type": "noauth"
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Never store real credentials in a shared collection export.",
          "function stop(reason) {",
          "  // Also neutralize the destination for old runners without skipRequest.",
          "  pm.request.url.update('https://example.invalid/ALL1PAY-request-disabled');",
          "  if (pm.execution && pm.execution.skipRequest) pm.execution.skipRequest();",
          "  throw new Error(reason);",
          "}",
          "const method = pm.request.method.toUpperCase();",
          "if (method !== 'GET' && pm.variables.get('allow_live_requests') !== 'true') stop('Live POST disabled. Enable allow_live_requests only for an intentional operation.');",
          "const apiKey = pm.variables.get('api_key'), secret = pm.variables.get('secret_key');",
          "if (!apiKey || !secret) stop('Set api_key and secret_key locally.');",
          "const resolved = pm.variables.replaceIn(pm.request.url.toString());",
          "if (!/^https:\\/\\/[^/]+\\//.test(resolved) || resolved.includes('{{') || resolved.includes('#')) stop('Set an HTTPS base_url and all path variables; do not include fragments.');",
          "pm.request.url.update(resolved);",
          "const path = resolved.replace(/^https:\\/\\/[^/]+/, '');",
          "let body = '';",
          "if (method !== 'GET' && pm.request.body && pm.request.body.raw) {",
          "  const value = JSON.parse(pm.variables.replaceIn(pm.request.body.raw));",
          "  if ((path.endsWith('/v1/payin') || path.endsWith('/v1/payout')) && (!value.orderId || value.orderId.includes('{{'))) stop('Set a stable business orderId before creating an order.');",
          "  body = Object.keys(value).length ? JSON.stringify(value) : '';",
          "  pm.request.body.update(body || '{}');",
          "}",
          "const timestamp = Date.now().toString();",
          "const CryptoJS = require('crypto-js');",
          "const signature = CryptoJS.HmacSHA256(timestamp + method + path + body, secret).toString(CryptoJS.enc.Hex);",
          "for (const [key, value] of Object.entries({ 'Content-Type': 'application/json', 'x-api-key': apiKey, 'x-secret-key': secret, 'x-timestamp': timestamp, 'x-signature': signature })) pm.request.headers.upsert({ key, value });"
        ]
      }
    }
  ],
  "item": [
    {
      "name": "Create Payin",
      "request": {
        "method": "POST",
        "header": [],
        "url": "{{base_url}}/v1/payin",
        "description": "สร้างรายการรับเงิน\n\nHTTP 201 can contain status FAILED and errorMessage after an upstream rejection. PROCESSING plus a payment link means creation, not paid. Check the response body before showing a payment screen.\n\nHTTP 201 อาจมี status FAILED และ errorMessage เมื่อต้นทางปฏิเสธ PROCESSING พร้อมลิงก์หมายถึงสร้างรายการ ไม่ใช่ชำระแล้ว ตรวจ body ก่อนแสดงหน้าจ่ายเงิน\n\nQR request: set flowType=qr, if enabled. Optional bank fields can be omitted for routes that do not need them. Slip request: show the returned payment page/destination and submit the actual transfer slip. Do not fabricate destination details.\n\nQR: ส่ง flowType=qr เมื่อร้านเปิดใช้ ละข้อมูลธนาคารได้ในเส้นทางที่ไม่ต้องใช้ ส่วน slip ให้แสดงหน้าชำระ/บัญชีปลายทางที่ได้รับและส่งสลิปจริง ห้ามสร้างข้อมูลปลายทางเอง\n\npaymentUrl/providerRefId may be absent. providerData is provider-specific and can change shape. There is no guaranteed top-level qrCode, qrCodeUrl or expiresAt. Do not assume every provider returns destination_bank or a base64 QR in the same field.\n\npaymentUrl/providerRefId อาจไม่มี providerData มีรูปแบบตาม Provider ไม่รับประกัน qrCode, qrCodeUrl หรือ expiresAt ระดับบน อย่าสมมติว่าทุกเจ้าส่ง destination_bank หรือ QR base64 ในชื่อเดียวกัน\n\nIf the HTTP response is lost or returns 5xx, creation may already have happened. Reconcile the original order before another create request. This endpoint is a live operation, not a sandbox test.\n\nหากคำตอบหายหรือได้ 5xx อาจสร้างรายการแล้ว ต้องตรวจรายการเดิมก่อนสร้างใหม่ Endpoint นี้สร้างรายการจริง ไม่ใช่ sandbox\n\n**amount** (number, required): Positive amount, at least 1; the selected route may impose a higher minimum or a maximum. Send THB amounts with at most two decimal places.\nจำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม\n\n**currency** (string, optional): Defaults to THB. Use THB for the documented Thai payment routes; do not infer multi-currency support from this field.\nค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน\n\n**orderId** (string, optional): Strongly recommended. Unique for the merchant across payins AND payouts; omit only if you accept losing this duplicate-creation protection.\nแนะนำให้ระบุและไม่ซ้ำภายในร้านทั้ง Payin และ Payout หากละจะไม่มีการกันสร้างซ้ำด้วยเลขร้านนี้\n\n**providerAccountId** (string, optional): Omit for merchant-configured routing. If supplied, it must be an assigned, enabled account supporting the amount/flow. A direct provider test does not prove merchant eligibility.\nละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้\n\n**callbackUrl** (string, optional): Per-order callback destination, otherwise the merchant default is used. Use public HTTPS without embedded credentials or redirects; private/reserved addresses are blocked.\nปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน\n\n**customerName** (string, optional): Customer name; not evidence of verified bank ownership.\nชื่อลูกค้า ไม่ใช่หลักฐานยืนยันเจ้าของบัญชี\n\n**customerEmail** (string, optional): Customer email.\nอีเมลลูกค้า\n\n**bankName** (string, optional): Customer's source-bank short name. Supply with bankNumber for slip routes that require source-account binding. See the Payin bank table; CIMB becomes CIMBT. Not a destination bank or bank_name.\nรหัสธนาคารต้นทางของลูกค้า ส่งคู่ bankNumber สำหรับช่องทาง slip ที่ผูกบัญชีผู้โอน ดูตารางธนาคาร Payin; CIMB แปลงเป็น CIMBT ไม่ใช่ธนาคารปลายทางและไม่ใช่ฟิลด์ bank_name\n\n**bankNumber** (string, optional): Customer's source-account number. Preserve leading zeros; send digits as a string. Provider-specific length/ownership checks still apply.\nเลขบัญชีต้นทางลูกค้า ส่งตัวเลขเป็นข้อความและเก็บศูนย์นำหน้า การตรวจความยาว/เจ้าของบัญชียังขึ้นกับ Provider\n\n**customerPhone** (string, optional): Customer phone, if needed by the route.\nเบอร์ลูกค้าหากเส้นทางนั้นต้องใช้\n\n**flowType** (slip | qr, optional): Default slip. Explicitly send slip or qr; metadata.channel does not select the common flow. The merchant route must allow it.\nค่าเริ่มต้น slip ควรส่ง slip หรือ qr ชัดเจน metadata.channel ไม่ใช้เลือก flow กลาง และร้านต้องเปิดช่องทางนั้นไว้\n\n**metadata** (object, optional): Optional JSON object, at most 16 KiB, 8 levels and 512 values. Returned transaction lists do not echo arbitrary metadata. Unknown top-level request fields are rejected.\nข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"orderId\": \"{{payin_order_id}}\",\n  \"flowType\": \"slip\",\n  \"bankName\": \"SCB\",\n  \"bankNumber\": \"0012345678\"\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      },
      "response": [
        {
          "name": "Illustrative response",
          "originalRequest": {
            "method": "POST",
            "header": [],
            "url": "{{base_url}}/v1/payin",
            "description": "สร้างรายการรับเงิน\n\nHTTP 201 can contain status FAILED and errorMessage after an upstream rejection. PROCESSING plus a payment link means creation, not paid. Check the response body before showing a payment screen.\n\nHTTP 201 อาจมี status FAILED และ errorMessage เมื่อต้นทางปฏิเสธ PROCESSING พร้อมลิงก์หมายถึงสร้างรายการ ไม่ใช่ชำระแล้ว ตรวจ body ก่อนแสดงหน้าจ่ายเงิน\n\nQR request: set flowType=qr, if enabled. Optional bank fields can be omitted for routes that do not need them. Slip request: show the returned payment page/destination and submit the actual transfer slip. Do not fabricate destination details.\n\nQR: ส่ง flowType=qr เมื่อร้านเปิดใช้ ละข้อมูลธนาคารได้ในเส้นทางที่ไม่ต้องใช้ ส่วน slip ให้แสดงหน้าชำระ/บัญชีปลายทางที่ได้รับและส่งสลิปจริง ห้ามสร้างข้อมูลปลายทางเอง\n\npaymentUrl/providerRefId may be absent. providerData is provider-specific and can change shape. There is no guaranteed top-level qrCode, qrCodeUrl or expiresAt. Do not assume every provider returns destination_bank or a base64 QR in the same field.\n\npaymentUrl/providerRefId อาจไม่มี providerData มีรูปแบบตาม Provider ไม่รับประกัน qrCode, qrCodeUrl หรือ expiresAt ระดับบน อย่าสมมติว่าทุกเจ้าส่ง destination_bank หรือ QR base64 ในชื่อเดียวกัน\n\nIf the HTTP response is lost or returns 5xx, creation may already have happened. Reconcile the original order before another create request. This endpoint is a live operation, not a sandbox test.\n\nหากคำตอบหายหรือได้ 5xx อาจสร้างรายการแล้ว ต้องตรวจรายการเดิมก่อนสร้างใหม่ Endpoint นี้สร้างรายการจริง ไม่ใช่ sandbox\n\n**amount** (number, required): Positive amount, at least 1; the selected route may impose a higher minimum or a maximum. Send THB amounts with at most two decimal places.\nจำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม\n\n**currency** (string, optional): Defaults to THB. Use THB for the documented Thai payment routes; do not infer multi-currency support from this field.\nค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน\n\n**orderId** (string, optional): Strongly recommended. Unique for the merchant across payins AND payouts; omit only if you accept losing this duplicate-creation protection.\nแนะนำให้ระบุและไม่ซ้ำภายในร้านทั้ง Payin และ Payout หากละจะไม่มีการกันสร้างซ้ำด้วยเลขร้านนี้\n\n**providerAccountId** (string, optional): Omit for merchant-configured routing. If supplied, it must be an assigned, enabled account supporting the amount/flow. A direct provider test does not prove merchant eligibility.\nละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้\n\n**callbackUrl** (string, optional): Per-order callback destination, otherwise the merchant default is used. Use public HTTPS without embedded credentials or redirects; private/reserved addresses are blocked.\nปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน\n\n**customerName** (string, optional): Customer name; not evidence of verified bank ownership.\nชื่อลูกค้า ไม่ใช่หลักฐานยืนยันเจ้าของบัญชี\n\n**customerEmail** (string, optional): Customer email.\nอีเมลลูกค้า\n\n**bankName** (string, optional): Customer's source-bank short name. Supply with bankNumber for slip routes that require source-account binding. See the Payin bank table; CIMB becomes CIMBT. Not a destination bank or bank_name.\nรหัสธนาคารต้นทางของลูกค้า ส่งคู่ bankNumber สำหรับช่องทาง slip ที่ผูกบัญชีผู้โอน ดูตารางธนาคาร Payin; CIMB แปลงเป็น CIMBT ไม่ใช่ธนาคารปลายทางและไม่ใช่ฟิลด์ bank_name\n\n**bankNumber** (string, optional): Customer's source-account number. Preserve leading zeros; send digits as a string. Provider-specific length/ownership checks still apply.\nเลขบัญชีต้นทางลูกค้า ส่งตัวเลขเป็นข้อความและเก็บศูนย์นำหน้า การตรวจความยาว/เจ้าของบัญชียังขึ้นกับ Provider\n\n**customerPhone** (string, optional): Customer phone, if needed by the route.\nเบอร์ลูกค้าหากเส้นทางนั้นต้องใช้\n\n**flowType** (slip | qr, optional): Default slip. Explicitly send slip or qr; metadata.channel does not select the common flow. The merchant route must allow it.\nค่าเริ่มต้น slip ควรส่ง slip หรือ qr ชัดเจน metadata.channel ไม่ใช้เลือก flow กลาง และร้านต้องเปิดช่องทางนั้นไว้\n\n**metadata** (object, optional): Optional JSON object, at most 16 KiB, 8 levels and 512 values. Returned transaction lists do not echo arbitrary metadata. Unknown top-level request fields are rejected.\nข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"orderId\": \"{{payin_order_id}}\",\n  \"flowType\": \"slip\",\n  \"bankName\": \"SCB\",\n  \"bankNumber\": \"0012345678\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "status": "Created",
          "code": 201,
          "header": [
            {
              "key": "Content-Type",
              "value": "application/json"
            }
          ],
          "body": "{\n  \"referenceId\": \"TXN-EXAMPLE-PAYIN\",\n  \"status\": \"PROCESSING\",\n  \"paymentUrl\": \"https://payment.example.com/order/example\",\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"providerRefId\": \"ORD-EXAMPLE\",\n  \"providerData\": {}\n}"
        },
        {
          "name": "Below route minimum",
          "originalRequest": {
            "method": "POST",
            "header": [],
            "url": "{{base_url}}/v1/payin",
            "description": "สร้างรายการรับเงิน\n\nHTTP 201 can contain status FAILED and errorMessage after an upstream rejection. PROCESSING plus a payment link means creation, not paid. Check the response body before showing a payment screen.\n\nHTTP 201 อาจมี status FAILED และ errorMessage เมื่อต้นทางปฏิเสธ PROCESSING พร้อมลิงก์หมายถึงสร้างรายการ ไม่ใช่ชำระแล้ว ตรวจ body ก่อนแสดงหน้าจ่ายเงิน\n\nQR request: set flowType=qr, if enabled. Optional bank fields can be omitted for routes that do not need them. Slip request: show the returned payment page/destination and submit the actual transfer slip. Do not fabricate destination details.\n\nQR: ส่ง flowType=qr เมื่อร้านเปิดใช้ ละข้อมูลธนาคารได้ในเส้นทางที่ไม่ต้องใช้ ส่วน slip ให้แสดงหน้าชำระ/บัญชีปลายทางที่ได้รับและส่งสลิปจริง ห้ามสร้างข้อมูลปลายทางเอง\n\npaymentUrl/providerRefId may be absent. providerData is provider-specific and can change shape. There is no guaranteed top-level qrCode, qrCodeUrl or expiresAt. Do not assume every provider returns destination_bank or a base64 QR in the same field.\n\npaymentUrl/providerRefId อาจไม่มี providerData มีรูปแบบตาม Provider ไม่รับประกัน qrCode, qrCodeUrl หรือ expiresAt ระดับบน อย่าสมมติว่าทุกเจ้าส่ง destination_bank หรือ QR base64 ในชื่อเดียวกัน\n\nIf the HTTP response is lost or returns 5xx, creation may already have happened. Reconcile the original order before another create request. This endpoint is a live operation, not a sandbox test.\n\nหากคำตอบหายหรือได้ 5xx อาจสร้างรายการแล้ว ต้องตรวจรายการเดิมก่อนสร้างใหม่ Endpoint นี้สร้างรายการจริง ไม่ใช่ sandbox\n\n**amount** (number, required): Positive amount, at least 1; the selected route may impose a higher minimum or a maximum. Send THB amounts with at most two decimal places.\nจำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม\n\n**currency** (string, optional): Defaults to THB. Use THB for the documented Thai payment routes; do not infer multi-currency support from this field.\nค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน\n\n**orderId** (string, optional): Strongly recommended. Unique for the merchant across payins AND payouts; omit only if you accept losing this duplicate-creation protection.\nแนะนำให้ระบุและไม่ซ้ำภายในร้านทั้ง Payin และ Payout หากละจะไม่มีการกันสร้างซ้ำด้วยเลขร้านนี้\n\n**providerAccountId** (string, optional): Omit for merchant-configured routing. If supplied, it must be an assigned, enabled account supporting the amount/flow. A direct provider test does not prove merchant eligibility.\nละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้\n\n**callbackUrl** (string, optional): Per-order callback destination, otherwise the merchant default is used. Use public HTTPS without embedded credentials or redirects; private/reserved addresses are blocked.\nปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน\n\n**customerName** (string, optional): Customer name; not evidence of verified bank ownership.\nชื่อลูกค้า ไม่ใช่หลักฐานยืนยันเจ้าของบัญชี\n\n**customerEmail** (string, optional): Customer email.\nอีเมลลูกค้า\n\n**bankName** (string, optional): Customer's source-bank short name. Supply with bankNumber for slip routes that require source-account binding. See the Payin bank table; CIMB becomes CIMBT. Not a destination bank or bank_name.\nรหัสธนาคารต้นทางของลูกค้า ส่งคู่ bankNumber สำหรับช่องทาง slip ที่ผูกบัญชีผู้โอน ดูตารางธนาคาร Payin; CIMB แปลงเป็น CIMBT ไม่ใช่ธนาคารปลายทางและไม่ใช่ฟิลด์ bank_name\n\n**bankNumber** (string, optional): Customer's source-account number. Preserve leading zeros; send digits as a string. Provider-specific length/ownership checks still apply.\nเลขบัญชีต้นทางลูกค้า ส่งตัวเลขเป็นข้อความและเก็บศูนย์นำหน้า การตรวจความยาว/เจ้าของบัญชียังขึ้นกับ Provider\n\n**customerPhone** (string, optional): Customer phone, if needed by the route.\nเบอร์ลูกค้าหากเส้นทางนั้นต้องใช้\n\n**flowType** (slip | qr, optional): Default slip. Explicitly send slip or qr; metadata.channel does not select the common flow. The merchant route must allow it.\nค่าเริ่มต้น slip ควรส่ง slip หรือ qr ชัดเจน metadata.channel ไม่ใช้เลือก flow กลาง และร้านต้องเปิดช่องทางนั้นไว้\n\n**metadata** (object, optional): Optional JSON object, at most 16 KiB, 8 levels and 512 values. Returned transaction lists do not echo arbitrary metadata. Unknown top-level request fields are rejected.\nข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"orderId\": \"{{payin_order_id}}\",\n  \"flowType\": \"slip\",\n  \"bankName\": \"SCB\",\n  \"bankNumber\": \"0012345678\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "status": "Bad Request",
          "code": 400,
          "header": [],
          "body": "{\n  \"statusCode\": 400,\n  \"code\": \"PAYIN_AMOUNT_BELOW_MINIMUM\",\n  \"message\": \"ยอดเงินต่ำกว่าขั้นต่ำ: กรุณาสร้างรายการรับเงินตั้งแต่ 300 บาท\",\n  \"minimumAmount\": 300\n}"
        }
      ]
    },
    {
      "name": "Verify Slip",
      "request": {
        "method": "POST",
        "header": [],
        "url": "{{base_url}}/v1/payin/{{reference_id}}/verify-slip",
        "description": "ตรวจสลิป\n\nSend the slip image (imageBase64) every time; qrString may be added. The API accepts either value alone, but a provider that verifies only from images refuses a qrString-only request with success=false. The order must belong to you and have an upstream reference; the provider must support slip verification. PROCESSING or EXPIRED payins may be recovered.\n\nส่งรูปสลิป (imageBase64) ทุกครั้ง จะส่ง qrString มาด้วยก็ได้ API รับค่าใดค่าหนึ่งก็ได้ แต่ Provider ที่ตรวจจากรูปเท่านั้นจะตอบ success=false ถ้าส่งแค่ qrString ต้องเป็นรายการของร้านและมีเลขต้นทาง Provider ต้องรองรับการตรวจสลิป รายการ Payin PROCESSING หรือ EXPIRED อาจกู้คืนได้\n\nCredit the customer once per order: only from the answer with applied=true, or from the COMPLETED transaction status or callback. A slip sent to an order that is already COMPLETED returns success=false, code=ALREADY_PAID, alreadyCompleted=true: the order is paid, do not credit again. A slip that already paid another order returns success=false, code=SLIP_ALREADY_USED. When the provider has not answered yet, the answer is success=false, status=pending, pending=true: tell the customer to wait and follow the transaction status.\n\nเติมเครดิตครั้งเดียวต่อ 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 ให้ลูกค้ารอ แล้วติดตามสถานะธุรกรรม\n\nA provider refusal can return HTTP 201 with success=false and errorMessage. Evidence needing review can return HTTP 409. Do not credit from rawResponse or an upstream paid label; confirm the ALL1PAY transaction status.\n\nต้นทางปฏิเสธอาจตอบ HTTP 201 พร้อม success=false และ errorMessage หลักฐานที่ต้องตรวจอาจได้ HTTP 409 ห้ามเครดิตจาก rawResponse หรือคำว่า paid ของต้นทาง ให้ยืนยันสถานะธุรกรรม ALL1PAY\n\n**qrString** (string, optional): Optional, send it together with imageBase64: the QR string decoded from the bank transfer slip, not a payment QR. Some providers cannot verify from this text alone.\nไม่บังคับ ส่งคู่กับ imageBase64 ได้: ข้อความ QR ที่อ่านจากสลิปโอนเงิน ไม่ใช่ QR สำหรับจ่ายเงิน บาง Provider ตรวจจากข้อความนี้อย่างเดียวไม่ได้\n\n**imageBase64** (string, optional): Send this every time: the actual slip image as base64, JPEG or PNG (data:image/jpeg;base64,... or bare base64). Some providers verify only from the image and refuse a qrString-only request. Total HTTP body limit is 8 MiB; base64 adds about a third, so keep the image under about 6 MB.\nส่งทุกครั้ง: รูปสลิปจริงแบบ base64 เป็น JPEG หรือ PNG (data:image/jpeg;base64,... หรือ base64 ล้วน) บาง Provider ตรวจได้จากรูปเท่านั้นและจะปฏิเสธถ้าส่งแค่ qrString HTTP body รวมไม่เกิน 8 MiB base64 ทำให้ขนาดโตขึ้นราว 1/3 รูปจึงควรไม่เกินราว 6 MB",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"imageBase64\": \"{{image_base64}}\",\n  \"qrString\": \"{{qr_string}}\"\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      },
      "response": [
        {
          "name": "Illustrative response",
          "originalRequest": {
            "method": "POST",
            "header": [],
            "url": "{{base_url}}/v1/payin/{{reference_id}}/verify-slip",
            "description": "ตรวจสลิป\n\nSend the slip image (imageBase64) every time; qrString may be added. The API accepts either value alone, but a provider that verifies only from images refuses a qrString-only request with success=false. The order must belong to you and have an upstream reference; the provider must support slip verification. PROCESSING or EXPIRED payins may be recovered.\n\nส่งรูปสลิป (imageBase64) ทุกครั้ง จะส่ง qrString มาด้วยก็ได้ API รับค่าใดค่าหนึ่งก็ได้ แต่ Provider ที่ตรวจจากรูปเท่านั้นจะตอบ success=false ถ้าส่งแค่ qrString ต้องเป็นรายการของร้านและมีเลขต้นทาง Provider ต้องรองรับการตรวจสลิป รายการ Payin PROCESSING หรือ EXPIRED อาจกู้คืนได้\n\nCredit the customer once per order: only from the answer with applied=true, or from the COMPLETED transaction status or callback. A slip sent to an order that is already COMPLETED returns success=false, code=ALREADY_PAID, alreadyCompleted=true: the order is paid, do not credit again. A slip that already paid another order returns success=false, code=SLIP_ALREADY_USED. When the provider has not answered yet, the answer is success=false, status=pending, pending=true: tell the customer to wait and follow the transaction status.\n\nเติมเครดิตครั้งเดียวต่อ 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 ให้ลูกค้ารอ แล้วติดตามสถานะธุรกรรม\n\nA provider refusal can return HTTP 201 with success=false and errorMessage. Evidence needing review can return HTTP 409. Do not credit from rawResponse or an upstream paid label; confirm the ALL1PAY transaction status.\n\nต้นทางปฏิเสธอาจตอบ HTTP 201 พร้อม success=false และ errorMessage หลักฐานที่ต้องตรวจอาจได้ HTTP 409 ห้ามเครดิตจาก rawResponse หรือคำว่า paid ของต้นทาง ให้ยืนยันสถานะธุรกรรม ALL1PAY\n\n**qrString** (string, optional): Optional, send it together with imageBase64: the QR string decoded from the bank transfer slip, not a payment QR. Some providers cannot verify from this text alone.\nไม่บังคับ ส่งคู่กับ imageBase64 ได้: ข้อความ QR ที่อ่านจากสลิปโอนเงิน ไม่ใช่ QR สำหรับจ่ายเงิน บาง Provider ตรวจจากข้อความนี้อย่างเดียวไม่ได้\n\n**imageBase64** (string, optional): Send this every time: the actual slip image as base64, JPEG or PNG (data:image/jpeg;base64,... or bare base64). Some providers verify only from the image and refuse a qrString-only request. Total HTTP body limit is 8 MiB; base64 adds about a third, so keep the image under about 6 MB.\nส่งทุกครั้ง: รูปสลิปจริงแบบ base64 เป็น JPEG หรือ PNG (data:image/jpeg;base64,... หรือ base64 ล้วน) บาง Provider ตรวจได้จากรูปเท่านั้นและจะปฏิเสธถ้าส่งแค่ qrString HTTP body รวมไม่เกิน 8 MiB base64 ทำให้ขนาดโตขึ้นราว 1/3 รูปจึงควรไม่เกินราว 6 MB",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"imageBase64\": \"{{image_base64}}\",\n  \"qrString\": \"{{qr_string}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "status": "Created",
          "code": 201,
          "header": [
            {
              "key": "Content-Type",
              "value": "application/json"
            }
          ],
          "body": "{\n  \"success\": true,\n  \"status\": \"paid\",\n  \"applied\": true,\n  \"rawResponse\": {}\n}"
        }
      ]
    },
    {
      "name": "Create Payout",
      "request": {
        "method": "POST",
        "header": [],
        "url": "{{base_url}}/v1/payout",
        "description": "สร้างรายการจ่ายเงิน\n\namount is the principal requested for the recipient. feeAmount is the merchant fee and totalDebit=amount+feeAmount. The total is held during processing. The 0.2% fee in this example is illustrative, not a universal rate.\n\namount คือเงินต้นที่ขอจ่ายผู้รับ feeAmount คือค่าธรรมเนียมร้าน และ totalDebit=amount+feeAmount พักเงินรวมนี้ระหว่างดำเนินการ ตัวอย่าง 0.2% ไม่ใช่เรทของทุกร้าน\n\nA timeout, absent provider reference or reviewRequired=true is not proof of failure or refund. An ambiguous provider exception can return HTTP 409 with referenceId and reviewRequired=true. Stop automatic creation/retry with a new orderId and follow up the same operation.\n\ntimeout, ไม่มีเลขต้นทาง หรือ reviewRequired=true ไม่ใช่หลักฐานว่าล้มเหลวหรือคืนเงินแล้ว ความผิดพลาดที่ยังสรุปไม่ได้อาจตอบ HTTP 409 พร้อม referenceId และ reviewRequired=true หยุดสร้างซ้ำด้วย orderId ใหม่แล้วติดตามรายการเดิม\n\nHTTP 201 may report FAILED after a definitive refusal or PENDING/PROCESSING requiring review. COMPLETED is the confirmed success state. There is no automatic payout failover to another provider for this order.\n\nHTTP 201 อาจเป็น FAILED หลังปฏิเสธชัดเจน หรือ PENDING/PROCESSING ที่รอตรวจ COMPLETED จึงเป็นสถานะสำเร็จที่ยืนยันแล้ว ไม่มีการส่ง Payout รายการนี้ไป Provider อื่นอัตโนมัติ\n\n**amount** (number, required): Positive amount, at least 1; the selected route may impose a higher minimum or a maximum. Send THB amounts with at most two decimal places.\nจำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม\n\n**currency** (string, optional): Defaults to THB. Use THB for the documented Thai payment routes; do not infer multi-currency support from this field.\nค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน\n\n**bankCode** (string, required): Recipient bank code supported by the assigned payout provider. The new Payin CIMB alias does NOT normalize payout codes; confirm payout mapping for your route.\nรหัสธนาคารผู้รับที่ Provider จ่ายเงินรองรับ การแปลง CIMB ของ Payin ไม่ได้ใช้กับ Payout ต้องยืนยัน mapping ของเส้นทางจ่ายเงิน\n\n**accountNumber** (string, required): Recipient account number, with leading zeros preserved.\nเลขบัญชีผู้รับ เก็บศูนย์นำหน้า\n\n**accountName** (string, required): Recipient account holder name.\nชื่อเจ้าของบัญชีผู้รับ\n\n**orderId** (non-empty string, required): Required unique merchant order ID across BOTH payins and payouts. Keep the same business-operation ID while resolving an uncertain result.\nเลขรายการร้านที่ต้องไม่ซ้ำทั้ง Payin และ Payout เก็บเลขรายการเดิมไว้ขณะตรวจผลที่ยังไม่ชัดเจน\n\n**providerAccountId** (string, optional): Omit for merchant-configured routing. If supplied, it must be an assigned, enabled account supporting the amount/flow. A direct provider test does not prove merchant eligibility.\nละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้\n\n**callbackUrl** (string, optional): Per-order callback destination, otherwise the merchant default is used. Use public HTTPS without embedded credentials or redirects; private/reserved addresses are blocked.\nปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน\n\n**metadata** (object, optional): Optional JSON object, at most 16 KiB, 8 levels and 512 values. Returned transaction lists do not echo arbitrary metadata. Unknown top-level request fields are rejected.\nข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"bankCode\": \"KBANK\",\n  \"accountNumber\": \"0012345678\",\n  \"accountName\": \"Example Recipient\",\n  \"orderId\": \"{{payout_order_id}}\"\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      },
      "response": [
        {
          "name": "Illustrative response",
          "originalRequest": {
            "method": "POST",
            "header": [],
            "url": "{{base_url}}/v1/payout",
            "description": "สร้างรายการจ่ายเงิน\n\namount is the principal requested for the recipient. feeAmount is the merchant fee and totalDebit=amount+feeAmount. The total is held during processing. The 0.2% fee in this example is illustrative, not a universal rate.\n\namount คือเงินต้นที่ขอจ่ายผู้รับ feeAmount คือค่าธรรมเนียมร้าน และ totalDebit=amount+feeAmount พักเงินรวมนี้ระหว่างดำเนินการ ตัวอย่าง 0.2% ไม่ใช่เรทของทุกร้าน\n\nA timeout, absent provider reference or reviewRequired=true is not proof of failure or refund. An ambiguous provider exception can return HTTP 409 with referenceId and reviewRequired=true. Stop automatic creation/retry with a new orderId and follow up the same operation.\n\ntimeout, ไม่มีเลขต้นทาง หรือ reviewRequired=true ไม่ใช่หลักฐานว่าล้มเหลวหรือคืนเงินแล้ว ความผิดพลาดที่ยังสรุปไม่ได้อาจตอบ HTTP 409 พร้อม referenceId และ reviewRequired=true หยุดสร้างซ้ำด้วย orderId ใหม่แล้วติดตามรายการเดิม\n\nHTTP 201 may report FAILED after a definitive refusal or PENDING/PROCESSING requiring review. COMPLETED is the confirmed success state. There is no automatic payout failover to another provider for this order.\n\nHTTP 201 อาจเป็น FAILED หลังปฏิเสธชัดเจน หรือ PENDING/PROCESSING ที่รอตรวจ COMPLETED จึงเป็นสถานะสำเร็จที่ยืนยันแล้ว ไม่มีการส่ง Payout รายการนี้ไป Provider อื่นอัตโนมัติ\n\n**amount** (number, required): Positive amount, at least 1; the selected route may impose a higher minimum or a maximum. Send THB amounts with at most two decimal places.\nจำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม\n\n**currency** (string, optional): Defaults to THB. Use THB for the documented Thai payment routes; do not infer multi-currency support from this field.\nค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน\n\n**bankCode** (string, required): Recipient bank code supported by the assigned payout provider. The new Payin CIMB alias does NOT normalize payout codes; confirm payout mapping for your route.\nรหัสธนาคารผู้รับที่ Provider จ่ายเงินรองรับ การแปลง CIMB ของ Payin ไม่ได้ใช้กับ Payout ต้องยืนยัน mapping ของเส้นทางจ่ายเงิน\n\n**accountNumber** (string, required): Recipient account number, with leading zeros preserved.\nเลขบัญชีผู้รับ เก็บศูนย์นำหน้า\n\n**accountName** (string, required): Recipient account holder name.\nชื่อเจ้าของบัญชีผู้รับ\n\n**orderId** (non-empty string, required): Required unique merchant order ID across BOTH payins and payouts. Keep the same business-operation ID while resolving an uncertain result.\nเลขรายการร้านที่ต้องไม่ซ้ำทั้ง Payin และ Payout เก็บเลขรายการเดิมไว้ขณะตรวจผลที่ยังไม่ชัดเจน\n\n**providerAccountId** (string, optional): Omit for merchant-configured routing. If supplied, it must be an assigned, enabled account supporting the amount/flow. A direct provider test does not prove merchant eligibility.\nละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้\n\n**callbackUrl** (string, optional): Per-order callback destination, otherwise the merchant default is used. Use public HTTPS without embedded credentials or redirects; private/reserved addresses are blocked.\nปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน\n\n**metadata** (object, optional): Optional JSON object, at most 16 KiB, 8 levels and 512 values. Returned transaction lists do not echo arbitrary metadata. Unknown top-level request fields are rejected.\nข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"bankCode\": \"KBANK\",\n  \"accountNumber\": \"0012345678\",\n  \"accountName\": \"Example Recipient\",\n  \"orderId\": \"{{payout_order_id}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "status": "Created",
          "code": 201,
          "header": [
            {
              "key": "Content-Type",
              "value": "application/json"
            }
          ],
          "body": "{\n  \"referenceId\": \"TXN-EXAMPLE-PAYOUT\",\n  \"status\": \"PROCESSING\",\n  \"reviewRequired\": false,\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"feeAmount\": 2,\n  \"totalDebit\": 1002,\n  \"providerRefId\": \"PAYOUT-EXAMPLE\",\n  \"providerData\": {}\n}"
        },
        {
          "name": "Unknown outcome — review, do not resend",
          "originalRequest": {
            "method": "POST",
            "header": [],
            "url": "{{base_url}}/v1/payout",
            "description": "สร้างรายการจ่ายเงิน\n\namount is the principal requested for the recipient. feeAmount is the merchant fee and totalDebit=amount+feeAmount. The total is held during processing. The 0.2% fee in this example is illustrative, not a universal rate.\n\namount คือเงินต้นที่ขอจ่ายผู้รับ feeAmount คือค่าธรรมเนียมร้าน และ totalDebit=amount+feeAmount พักเงินรวมนี้ระหว่างดำเนินการ ตัวอย่าง 0.2% ไม่ใช่เรทของทุกร้าน\n\nA timeout, absent provider reference or reviewRequired=true is not proof of failure or refund. An ambiguous provider exception can return HTTP 409 with referenceId and reviewRequired=true. Stop automatic creation/retry with a new orderId and follow up the same operation.\n\ntimeout, ไม่มีเลขต้นทาง หรือ reviewRequired=true ไม่ใช่หลักฐานว่าล้มเหลวหรือคืนเงินแล้ว ความผิดพลาดที่ยังสรุปไม่ได้อาจตอบ HTTP 409 พร้อม referenceId และ reviewRequired=true หยุดสร้างซ้ำด้วย orderId ใหม่แล้วติดตามรายการเดิม\n\nHTTP 201 may report FAILED after a definitive refusal or PENDING/PROCESSING requiring review. COMPLETED is the confirmed success state. There is no automatic payout failover to another provider for this order.\n\nHTTP 201 อาจเป็น FAILED หลังปฏิเสธชัดเจน หรือ PENDING/PROCESSING ที่รอตรวจ COMPLETED จึงเป็นสถานะสำเร็จที่ยืนยันแล้ว ไม่มีการส่ง Payout รายการนี้ไป Provider อื่นอัตโนมัติ\n\n**amount** (number, required): Positive amount, at least 1; the selected route may impose a higher minimum or a maximum. Send THB amounts with at most two decimal places.\nจำนวนเงินอย่างน้อย 1 บาท เส้นทางที่ใช้มีขั้นต่ำหรือสูงสุดเพิ่มเติมได้ ส่งยอด THB ไม่เกินสองตำแหน่งทศนิยม\n\n**currency** (string, optional): Defaults to THB. Use THB for the documented Thai payment routes; do not infer multi-currency support from this field.\nค่าเริ่มต้น THB ใช้ THB กับเส้นทางรับ–จ่ายเงินไทยในคู่มือนี้ การมีฟิลด์นี้ไม่ได้ยืนยันว่ารองรับทุกสกุลเงิน\n\n**bankCode** (string, required): Recipient bank code supported by the assigned payout provider. The new Payin CIMB alias does NOT normalize payout codes; confirm payout mapping for your route.\nรหัสธนาคารผู้รับที่ Provider จ่ายเงินรองรับ การแปลง CIMB ของ Payin ไม่ได้ใช้กับ Payout ต้องยืนยัน mapping ของเส้นทางจ่ายเงิน\n\n**accountNumber** (string, required): Recipient account number, with leading zeros preserved.\nเลขบัญชีผู้รับ เก็บศูนย์นำหน้า\n\n**accountName** (string, required): Recipient account holder name.\nชื่อเจ้าของบัญชีผู้รับ\n\n**orderId** (non-empty string, required): Required unique merchant order ID across BOTH payins and payouts. Keep the same business-operation ID while resolving an uncertain result.\nเลขรายการร้านที่ต้องไม่ซ้ำทั้ง Payin และ Payout เก็บเลขรายการเดิมไว้ขณะตรวจผลที่ยังไม่ชัดเจน\n\n**providerAccountId** (string, optional): Omit for merchant-configured routing. If supplied, it must be an assigned, enabled account supporting the amount/flow. A direct provider test does not prove merchant eligibility.\nละเพื่อให้เลือกเส้นทางตามการตั้งค่าร้าน หากระบุต้องเป็นบัญชีที่ผูกและเปิดใช้กับร้าน รองรับยอด/ช่องทาง การทดสอบ Provider โดยตรงไม่ได้ยืนยันว่าร้านใช้เส้นทางนั้นได้\n\n**callbackUrl** (string, optional): Per-order callback destination, otherwise the merchant default is used. Use public HTTPS without embedded credentials or redirects; private/reserved addresses are blocked.\nปลายทาง callback เฉพาะรายการ หากไม่ได้ระบุใช้ค่าเริ่มต้นร้าน ต้องเป็น HTTPS สาธารณะ ไม่มีรหัสผ่านฝังใน URL หรือ redirect ไม่รับที่อยู่ภายใน/สงวน\n\n**metadata** (object, optional): Optional JSON object, at most 16 KiB, 8 levels and 512 values. Returned transaction lists do not echo arbitrary metadata. Unknown top-level request fields are rejected.\nข้อมูลเสริมแบบ object ไม่เกิน 16 KiB ลึก 8 ชั้นและ 512 ค่า รายการธุรกรรมไม่ส่ง metadata อิสระทั้งหมดกลับมา ฟิลด์ระดับบนที่ไม่รองรับถูกปฏิเสธ",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 1000,\n  \"currency\": \"THB\",\n  \"bankCode\": \"KBANK\",\n  \"accountNumber\": \"0012345678\",\n  \"accountName\": \"Example Recipient\",\n  \"orderId\": \"{{payout_order_id}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "status": "Conflict",
          "code": 409,
          "header": [],
          "body": "{\n  \"message\": \"พักรายการเพื่อตรวจสอบข้อมูล Provider ยังไม่ลงเงินหรือคืนเงิน กรุณาติดต่อทีมดูแล (SETTLEMENT_REVIEW_REQUIRED)\",\n  \"referenceId\": \"TXN-EXAMPLE-PAYOUT\",\n  \"reviewRequired\": true\n}"
        }
      ]
    },
    {
      "name": "Check Transaction",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{base_url}}/v1/transaction/{{reference_id}}",
        "description": "ตรวจสถานะรายการ\n\nReads ALL1PAY's recorded state, not a fresh provider inquiry. referenceId is the ALL1PAY reference, not orderId or providerRefId. Unknown/foreign references return HTTP 400 Transaction not found.\n\nอ่านสถานะที่ ALL1PAY บันทึก ไม่ได้ยิงถาม Provider สด referenceId เป็นเลข ALL1PAY ไม่ใช่ orderId หรือ providerRefId เลขที่ไม่มีหรือของร้านอื่นได้ HTTP 400 Transaction not found\n\nThis endpoint returns orderId and fee, whereas list/webhook records use merchantOrderId. amount and fee are decimal strings on this read response; do not assume all endpoints serialize money as JSON numbers. It does not currently include reviewRequired.\n\nEndpoint นี้ใช้ orderId และ fee แต่รายการรวม/webhook ใช้ merchantOrderId ยอด amount และ fee ในคำตอบนี้เป็นข้อความทศนิยม อย่าสมมติว่าทุก endpoint ส่งยอดเป็น JSON number และ endpoint นี้ยังไม่ส่ง reviewRequired"
      },
      "response": [
        {
          "name": "Illustrative response",
          "originalRequest": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/v1/transaction/{{reference_id}}",
            "description": "ตรวจสถานะรายการ\n\nReads ALL1PAY's recorded state, not a fresh provider inquiry. referenceId is the ALL1PAY reference, not orderId or providerRefId. Unknown/foreign references return HTTP 400 Transaction not found.\n\nอ่านสถานะที่ ALL1PAY บันทึก ไม่ได้ยิงถาม Provider สด referenceId เป็นเลข ALL1PAY ไม่ใช่ orderId หรือ providerRefId เลขที่ไม่มีหรือของร้านอื่นได้ HTTP 400 Transaction not found\n\nThis endpoint returns orderId and fee, whereas list/webhook records use merchantOrderId. amount and fee are decimal strings on this read response; do not assume all endpoints serialize money as JSON numbers. It does not currently include reviewRequired.\n\nEndpoint นี้ใช้ orderId และ fee แต่รายการรวม/webhook ใช้ merchantOrderId ยอด amount และ fee ในคำตอบนี้เป็นข้อความทศนิยม อย่าสมมติว่าทุก endpoint ส่งยอดเป็น JSON number และ endpoint นี้ยังไม่ส่ง reviewRequired"
          },
          "status": "OK",
          "code": 200,
          "header": [
            {
              "key": "Content-Type",
              "value": "application/json"
            }
          ],
          "body": "{\n  \"referenceId\": \"TXN-EXAMPLE-PAYIN\",\n  \"orderId\": \"PAYIN-EXAMPLE-001\",\n  \"type\": \"PAYIN\",\n  \"status\": \"COMPLETED\",\n  \"amount\": \"1000\",\n  \"currency\": \"THB\",\n  \"fee\": \"15\",\n  \"createdAt\": \"2026-09-16T07:00:00.000Z\",\n  \"completedAt\": \"2026-09-16T07:01:00.000Z\"\n}"
        }
      ]
    },
    {
      "name": "List Transactions",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{base_url}}/v1/transactions",
        "description": "รายการธุรกรรม\n\nNewest first by createdAt/id. Filter/cursor scope belongs to your merchant. The public v1 controller does NOT accept dateFrom, dateTo, search or an orderId lookup filter; do not rely on old Postman descriptions advertising them.\n\nเรียงใหม่ก่อนตาม createdAt/id ตัวกรองและ cursor จำกัดเฉพาะร้าน Public v1 ไม่รองรับ dateFrom, dateTo, search หรือค้นด้วย orderId อย่าอ้างคำอธิบาย Postman เก่าที่ระบุว่าทำได้\n\nUse bounded pagination to locate a lost order by merchantOrderId, then retain its referenceId; contact support when uncertain. reviewRequired is available here. metadata only includes bankName/bankNumber, not your arbitrary metadata object. Monetary Decimal fields serialize as strings.\n\nใช้ pagination แบบจำกัดเพื่อหารายการที่คำตอบหายด้วย merchantOrderId แล้วเก็บ referenceId หากยังไม่แน่ใจให้ติดต่อ support ที่นี่มี reviewRequired ส่วน metadata ส่งเฉพาะ bankName/bankNumber ไม่ใช่ข้อมูลเสริมทั้งหมด ยอดที่เป็น Decimal ส่งเป็นข้อความ\n\n**page** (query integer, optional): Default 1; offset beyond 10,000 rows is rejected. Prefer nextCursor for deep history.\nค่าเริ่มต้น 1 ไม่รับ offset เกิน 10,000 แถว ใช้ nextCursor เมื่ออ่านประวัติลึก\n\n**limit** (query integer 1–100, optional): Default 20.\nค่าเริ่มต้น 20\n\n**type** (query PAYIN | PAYOUT, optional): Filter by type.\nกรองประเภทรายการ\n\n**status** (query status, optional): Filter by a documented transaction status.\nกรองสถานะตามตารางสถานะ\n\n**cursor** (query string, optional): Copy meta.nextCursor unchanged, keep type/status filters, and omit page. null or an empty data page ends iteration.\nคัดลอก meta.nextCursor ตามเดิม คงตัวกรอง type/status และละ page หากเป็น null หรือ data ว่างให้หยุด"
      },
      "response": [
        {
          "name": "Illustrative response",
          "originalRequest": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/v1/transactions",
            "description": "รายการธุรกรรม\n\nNewest first by createdAt/id. Filter/cursor scope belongs to your merchant. The public v1 controller does NOT accept dateFrom, dateTo, search or an orderId lookup filter; do not rely on old Postman descriptions advertising them.\n\nเรียงใหม่ก่อนตาม createdAt/id ตัวกรองและ cursor จำกัดเฉพาะร้าน Public v1 ไม่รองรับ dateFrom, dateTo, search หรือค้นด้วย orderId อย่าอ้างคำอธิบาย Postman เก่าที่ระบุว่าทำได้\n\nUse bounded pagination to locate a lost order by merchantOrderId, then retain its referenceId; contact support when uncertain. reviewRequired is available here. metadata only includes bankName/bankNumber, not your arbitrary metadata object. Monetary Decimal fields serialize as strings.\n\nใช้ pagination แบบจำกัดเพื่อหารายการที่คำตอบหายด้วย merchantOrderId แล้วเก็บ referenceId หากยังไม่แน่ใจให้ติดต่อ support ที่นี่มี reviewRequired ส่วน metadata ส่งเฉพาะ bankName/bankNumber ไม่ใช่ข้อมูลเสริมทั้งหมด ยอดที่เป็น Decimal ส่งเป็นข้อความ\n\n**page** (query integer, optional): Default 1; offset beyond 10,000 rows is rejected. Prefer nextCursor for deep history.\nค่าเริ่มต้น 1 ไม่รับ offset เกิน 10,000 แถว ใช้ nextCursor เมื่ออ่านประวัติลึก\n\n**limit** (query integer 1–100, optional): Default 20.\nค่าเริ่มต้น 20\n\n**type** (query PAYIN | PAYOUT, optional): Filter by type.\nกรองประเภทรายการ\n\n**status** (query status, optional): Filter by a documented transaction status.\nกรองสถานะตามตารางสถานะ\n\n**cursor** (query string, optional): Copy meta.nextCursor unchanged, keep type/status filters, and omit page. null or an empty data page ends iteration.\nคัดลอก meta.nextCursor ตามเดิม คงตัวกรอง type/status และละ page หากเป็น null หรือ data ว่างให้หยุด"
          },
          "status": "OK",
          "code": 200,
          "header": [
            {
              "key": "Content-Type",
              "value": "application/json"
            }
          ],
          "body": "{\n  \"data\": [\n    {\n      \"id\": \"EXAMPLE-ID\",\n      \"referenceId\": \"TXN-EXAMPLE-PAYIN\",\n      \"merchantOrderId\": \"PAYIN-EXAMPLE-001\",\n      \"type\": \"PAYIN\",\n      \"status\": \"PROCESSING\",\n      \"amount\": \"1000\",\n      \"currency\": \"THB\",\n      \"merchantFeeAmount\": \"15\",\n      \"customerName\": null,\n      \"customerEmail\": null,\n      \"bankCode\": null,\n      \"accountNumber\": null,\n      \"accountName\": null,\n      \"paymentUrl\": \"https://payment.example.com/order/example\",\n      \"providerRefId\": \"ORD-EXAMPLE\",\n      \"expiredAt\": null,\n      \"completedAt\": null,\n      \"failedReason\": null,\n      \"createdAt\": \"2026-09-16T07:00:00.000Z\",\n      \"updatedAt\": \"2026-09-16T07:00:00.000Z\",\n      \"reviewRequired\": false,\n      \"metadata\": {\n        \"bankName\": \"SCB\",\n        \"bankNumber\": \"0012345678\"\n      }\n    }\n  ],\n  \"meta\": {\n    \"total\": 1,\n    \"page\": 1,\n    \"limit\": 20,\n    \"totalPages\": 1,\n    \"nextCursor\": null\n  }\n}"
        }
      ]
    },
    {
      "name": "Wallet Balance",
      "request": {
        "method": "GET",
        "header": [],
        "url": "{{base_url}}/v1/balance",
        "description": "ยอดกระเป๋าร้าน\n\npayinBalance is credited net of merchant fees after successful payin settlement. payoutBalance is the payout wallet; holdBalance covers pending held money. totalBalance=payinBalance+payoutBalance excludes holdBalance.\n\npayinBalance ได้เครดิตสุทธิหลัง Payin สำเร็จ payoutBalance คือกระเป๋าจ่ายเงิน holdBalance คือยอดพัก totalBalance=payinBalance+payoutBalance ไม่รวม holdBalance\n\navailablePayout subtracts protected payout freezes and cannot be negative; it may be lower than payoutBalance. A snapshot does not guarantee admission of a later payout. Per-provider allocation and concurrent activity may also restrict payout.\n\navailablePayout หักยอด freeze จ่ายเงินที่ป้องกันไว้และไม่ติดลบ จึงอาจต่ำกว่า payoutBalance ยอดที่อ่านไม่ได้รับประกันว่า Payout ถัดไปจะผ่าน เพราะยังมีการจัดสรรต่อ Provider และรายการพร้อมกัน\n\nmaxSinglePayout is the largest amount one payout can take right now: a payout is paid from a single provider account, so when your money is split across accounts it can be lower than availablePayout. Split a larger payout into several.\n\nmaxSinglePayout คือยอดสูงสุดที่ Payout หนึ่งรายการถอนได้ตอนนี้ เพราะ Payout แต่ละรายการจ่ายจากบัญชีผู้ให้บริการบัญชีเดียว เมื่อยอดแยกอยู่หลายบัญชี ค่านี้จึงอาจต่ำกว่า availablePayout ยอดที่มากกว่านี้ให้แบ่งเป็นหลายรายการ"
      },
      "response": [
        {
          "name": "Illustrative response",
          "originalRequest": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/v1/balance",
            "description": "ยอดกระเป๋าร้าน\n\npayinBalance is credited net of merchant fees after successful payin settlement. payoutBalance is the payout wallet; holdBalance covers pending held money. totalBalance=payinBalance+payoutBalance excludes holdBalance.\n\npayinBalance ได้เครดิตสุทธิหลัง Payin สำเร็จ payoutBalance คือกระเป๋าจ่ายเงิน holdBalance คือยอดพัก totalBalance=payinBalance+payoutBalance ไม่รวม holdBalance\n\navailablePayout subtracts protected payout freezes and cannot be negative; it may be lower than payoutBalance. A snapshot does not guarantee admission of a later payout. Per-provider allocation and concurrent activity may also restrict payout.\n\navailablePayout หักยอด freeze จ่ายเงินที่ป้องกันไว้และไม่ติดลบ จึงอาจต่ำกว่า payoutBalance ยอดที่อ่านไม่ได้รับประกันว่า Payout ถัดไปจะผ่าน เพราะยังมีการจัดสรรต่อ Provider และรายการพร้อมกัน\n\nmaxSinglePayout is the largest amount one payout can take right now: a payout is paid from a single provider account, so when your money is split across accounts it can be lower than availablePayout. Split a larger payout into several.\n\nmaxSinglePayout คือยอดสูงสุดที่ Payout หนึ่งรายการถอนได้ตอนนี้ เพราะ Payout แต่ละรายการจ่ายจากบัญชีผู้ให้บริการบัญชีเดียว เมื่อยอดแยกอยู่หลายบัญชี ค่านี้จึงอาจต่ำกว่า availablePayout ยอดที่มากกว่านี้ให้แบ่งเป็นหลายรายการ"
          },
          "status": "OK",
          "code": 200,
          "header": [
            {
              "key": "Content-Type",
              "value": "application/json"
            }
          ],
          "body": "{\n  \"merchantId\": \"EXAMPLE-MERCHANT\",\n  \"currency\": \"THB\",\n  \"payinBalance\": 50000,\n  \"payoutBalance\": 12000,\n  \"holdBalance\": 3000,\n  \"totalBalance\": 62000,\n  \"availablePayout\": 11000,\n  \"maxSinglePayout\": 11000,\n  \"updatedAt\": \"2026-09-16T07:00:00.000Z\"\n}"
        }
      ]
    },
    {
      "name": "Transfer Payin to Payout",
      "request": {
        "method": "POST",
        "header": [],
        "url": "{{base_url}}/v1/transfer",
        "description": "โยกเงินรับไปกระเป๋าจ่าย\n\nTransfers merchant wallet balances immediately; it does not pay an external bank account. Insufficient payin funds return HTTP 400. Route minimums do not apply to this internal transfer.\n\nโยกเงินในกระเป๋าร้านทันที ไม่ได้โอนไปบัญชีธนาคารภายนอก ยอดรับไม่พอได้ HTTP 400 ขั้นต่ำ Provider ไม่ใช้กับการโยกภายในนี้\n\nThis endpoint has no orderId or idempotency key. Repeating it can transfer again. After a timeout, inspect wallet activity and contact support before another POST; do not automatically retry.\n\nEndpoint นี้ไม่มี orderId หรือ idempotency key การส่งซ้ำอาจโยกซ้ำ หาก timeout ให้ตรวจ Wallet Activity และติดต่อ support ก่อน POST อีกครั้ง ห้าม retry อัตโนมัติ\n\n**amount** (number, required): Amount to move from your payin wallet to your payout wallet, at least 1. Sufficient available payin funds are required.\nจำนวนเงินย้ายจากกระเป๋ารับเงินไปกระเป๋าจ่ายเงิน อย่างน้อย 1 บาท ต้องมียอดรับเงินที่ใช้ได้เพียงพอ",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"amount\": 1000\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      },
      "response": [
        {
          "name": "Illustrative response",
          "originalRequest": {
            "method": "POST",
            "header": [],
            "url": "{{base_url}}/v1/transfer",
            "description": "โยกเงินรับไปกระเป๋าจ่าย\n\nTransfers merchant wallet balances immediately; it does not pay an external bank account. Insufficient payin funds return HTTP 400. Route minimums do not apply to this internal transfer.\n\nโยกเงินในกระเป๋าร้านทันที ไม่ได้โอนไปบัญชีธนาคารภายนอก ยอดรับไม่พอได้ HTTP 400 ขั้นต่ำ Provider ไม่ใช้กับการโยกภายในนี้\n\nThis endpoint has no orderId or idempotency key. Repeating it can transfer again. After a timeout, inspect wallet activity and contact support before another POST; do not automatically retry.\n\nEndpoint นี้ไม่มี orderId หรือ idempotency key การส่งซ้ำอาจโยกซ้ำ หาก timeout ให้ตรวจ Wallet Activity และติดต่อ support ก่อน POST อีกครั้ง ห้าม retry อัตโนมัติ\n\n**amount** (number, required): Amount to move from your payin wallet to your payout wallet, at least 1. Sufficient available payin funds are required.\nจำนวนเงินย้ายจากกระเป๋ารับเงินไปกระเป๋าจ่ายเงิน อย่างน้อย 1 บาท ต้องมียอดรับเงินที่ใช้ได้เพียงพอ",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 1000\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "status": "Created",
          "code": 201,
          "header": [
            {
              "key": "Content-Type",
              "value": "application/json"
            }
          ],
          "body": "{\n  \"payinBefore\": 50000,\n  \"payinAfter\": 49000,\n  \"payoutBefore\": 12000,\n  \"payoutAfter\": 13000,\n  \"transferAmount\": 1000\n}"
        }
      ]
    }
  ]
}
