REST API ของเรา

เปิดใน ChatGPTเปิดใน Claude

API ของเราคืออินเทอร์เฟซ REST ของ blockwallets เอง: ใบแจ้งหนี้กำหนดราคาเป็นเซนต์สหรัฐ ref แบบ idempotent ต่อหนึ่งคำสั่งซื้อ บัญชีฝากเงินคงที่ครอบคลุมทุกเครือข่าย และ Webhook ที่เซ็นด้วย HMAC-SHA256 สร้างใบแจ้งหนี้แบบเดียวกันบนหน้าชำระเงินเดียวกันกับAPI ที่เข้ากันได้กับ Cryptomus ด้วยค่าธรรมเนียมและยอดคงเหลือเหมือนกัน

สร้างคีย์เองได้ในแดชบอร์ดที่ “นักพัฒนา › การเชื่อมต่อและคีย์”: คีย์ Live และ Test อย่างละหนึ่งชุดพร้อม webhook signing secret ของคีย์เหล่านั้น แต่ละรายการแสดงเพียงครั้งเดียว ในรายการจะเห็นเฉพาะคำนำหน้า หากบัญชีเปิดการยืนยันสองขั้นตอน การสร้างหรือเปลี่ยนคีย์ Live จะต้องกรอกรหัส ยังไม่มีบัญชีร้านค้า? ขอใช้งาน ใช้ Cryptomus อยู่แล้ว? ดู API ที่เข้ากันได้กับ Cryptomus (วิธีเลือก)

คีย์และคำขอ

Base URL https://blockwallets.io คำขอและการตอบกลับเป็น JSON ทุกคำขอมี:

ข้อผิดพลาดตอบกลับเป็นสถานะ HTTP และ {"error": {"code": "…", "message": "…"}}: 400 invalid_request (ฟิลด์หายไปหรือรูปแบบผิด), 401 unauthorized (ไม่มีคีย์ ไม่รู้จักคีย์ หรือคีย์ถูกปิด), 404 not_found, 409 conflict (คำขอขัดกับสถานะปัจจุบันของใบแจ้งหนี้), 422 currency_unsupported

Endpoint

Endpointทำอะไร
GET /v1/networksเครือข่ายที่รับได้ในขณะนี้ตามโหมดของคีย์นี้: ขั้นต่ำ การยืนยัน เวลาที่มักใช้ และค่าธรรมเนียมโดยประมาณ เหรียญที่มีราคาจะมีอัตราปัจจุบันมาด้วย
POST /v1/invoicesสร้างใบแจ้งหนี้ (201) หรือคืนใบเดิมของ ref เดียวกัน (200)
GET /v1/invoices?ref=…ค้นหาใบแจ้งหนี้ด้วย ref ของคุณ
GET /v1/invoices/:idค้นหาใบแจ้งหนี้ด้วย id
POST /v1/invoices/:id/networkเลือกเครือข่ายของใบแจ้งหนี้เอง (หน้าชำระเงินแบบ white-label): คืน address และ pay_amount ไปแสดง
POST /v1/invoices/:id/closeปิดใบแจ้งหนี้ที่รอชำระและยังไม่พบการโอนใด ๆ
POST /v1/deposit-accountsเปิด (201) หรือดึง (200) บัญชีฝากเงินของลูกค้าหนึ่งราย: ที่อยู่ถาวรบนทุกเครือข่าย
GET /v1/deposit-accounts?customer_ref=…ค้นหาบัญชีฝากเงินด้วย customer_ref
GET /v1/deposit-accounts/:idค้นหาบัญชีฝากเงินด้วย id
GET /v1/depositsแสดงรายการฝากของบัญชีหนึ่ง (account_id หรือ customer_ref, limit 1–200, ค่าเริ่มต้น 50)
GET /v1/deposits/:idค้นหารายการฝากหนึ่งรายการ
GET /v1/eventsการส่ง webhook ของใบแจ้งหนี้หรือรายการฝากหนึ่งรายการ (invoice_id หรือ deposit_id)
POST /v1/events/:id/redeliverส่ง webhook อีกครั้ง (202)

เพิ่ม ?probe=1 ที่การค้นหาใบแจ้งหนี้หรือบัญชีฝากเงินเพื่อตรวจเชนระหว่างทาง (อย่างมากทุก 10 วินาที) มิฉะนั้นคุณจะได้สถานะล่าสุดจากตัวสแกนของเรา ซึ่งตรวจทุกนาที

สร้างใบแจ้งหนี้ POST /v1/invoices

เรียก POST /v1/invoices เมื่อลูกค้าชำระเงิน แล้วส่งลูกค้าไปที่ pay_url ในการตอบกลับ

curl
curl -X POST https://blockwallets.io/v1/invoices \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"ref":"order_1042","amount":4200,"title":"Order #1042",
       "return_url":"https://shop.example/cart","success_url":"https://shop.example/thanks?order=1042",
       "meta":{"user_id":42}}'
ฟิลด์จำเป็นคำอธิบาย
refใช่เลขคำสั่งซื้อของคุณ: 1–64 ตัวอักษร เป็นตัวอักษร ตัวเลข และ _ . : - ไม่ซ้ำกันในแต่ละโหมด ส่ง ref เดิมพร้อมฟิลด์เดิมอีกครั้งได้ใบแจ้งหนี้เดิม ถ้าฟิลด์ต่างกันได้ 409
amountใช่จำนวนเงินเป็นเซนต์สหรัฐ เป็นจำนวนเต็ม: 4200 = $42.00 ต้องไม่ต่ำกว่าขั้นต่ำของเครือข่ายเมื่อเลือกเครือข่ายแล้ว
titleใช่สิ่งที่ลูกค้าเห็นบนหน้าชำระเงิน ไม่เกิน 64 ตัวอักษร
return_urlใช่ปลายทางของปุ่ม “ย้อนกลับ” บนหน้าชำระเงิน ต้องอยู่ในโดเมนเว็บไซต์ของคุณโดเมนใดโดเมนหนึ่ง
success_urlไม่ปลายทางที่ลูกค้าไปหลังชำระเงิน ค่าเริ่มต้นคือ return_url
networkไม่เลือกเครือข่ายล่วงหน้าด้วย id จากตารางเครือข่าย เว้นว่างเพื่อให้ลูกค้าเลือกบนหน้าชำระเงิน
customer_refไม่id ลูกค้าของคุณ ไม่เกิน 64 ตัวอักษร คืนกลับตามที่ส่งมา
lifetimeไม่อายุเป็นวินาที 600 – 43200 ค่าเริ่มต้น 3600
amount_ruleไม่"any" = บันทึกยอดเท่าที่เข้ามา (เติมเงิน): เป็น paid ทันทีที่ยืนยัน เว้นว่างเพื่อใช้ “กฎยอดรับเงิน” ใน “ตั้งค่า › กฎการรับเงินและอัตราค่าธรรมเนียม” ของแดชบอร์ด
accuracy_percentไม่จ่ายขาดได้เท่าไรที่ยังนับว่าชำระแล้ว 0 – 5 (เปอร์เซ็นต์) ค่าเริ่มต้น 0
subtract_percentไม่สัดส่วนค่าธรรมเนียมแพลตฟอร์มที่ลูกค้าจ่าย 0 – 100 (เปอร์เซ็นต์) บวกเพิ่มใน pay_amount เว้นว่างเพื่อใช้ค่าเริ่มต้นของแดชบอร์ด
payment_multipleไม่ยอดที่จ่ายไม่ครบเติมเพิ่มที่ที่อยู่เดิมได้หรือไม่ ค่าเริ่มต้นตามแดชบอร์ด (เปิดอยู่ เว้นแต่คุณเปลี่ยน) false: การโอนที่ไม่ครบครั้งแรกจบเป็น wrong_amount
metaไม่อ็อบเจกต์ JSON ใดก็ได้ไม่เกิน 2 KB คืนกลับตามที่ส่งมาในการค้นหาและ webhook
currencyไม่เฉพาะ USD (ค่าเริ่มต้น) อย่างอื่นได้ 422

ทุก URL ต้องอยู่ในโดเมนเว็บไซต์ของคุณโดเมนใดโดเมนหนึ่ง (แดชบอร์ด → “นักพัฒนา › การเชื่อมต่อและคีย์”) การตอบกลับคืออ็อบเจกต์ใบแจ้งหนี้ด้านล่าง network, address และ pay_amount จะถูกเติมเมื่อเลือกเครือข่ายแล้ว

อ็อบเจกต์ใบแจ้งหนี้

id ขึ้นต้นด้วย inv_ amount เป็นเซนต์สหรัฐ ส่วน pay_amount และ paid_amount เป็นจำนวนเหรียญแบบสตริงทศนิยมบนเครือข่ายที่เลือก

json
{
  "id": "inv_01J8…",
  "ref": "order_1042",
  "mode": "live",
  "status": "pending",
  "amount": 4200,
  "currency": "USD",
  "title": "Order #1042",
  "meta": { "user_id": 42 },
  "network": null,
  "address": null,
  "pay_amount": null,
  "paid_amount": null,
  "payments": [],
  "pay_url": "https://blockwallets.io/pay/inv_01J8…",
  "return_url": "https://shop.example/cart",
  "success_url": "https://shop.example/thanks?order=1042",
  "created_at": "2026-11-03T08:00:00.000Z",
  "expires_at": "2026-11-03T09:00:00.000Z",
  "paid_at": null,
  "closed_at": null
}
statusความหมายสิ่งที่คุณทำ
pendingรอการชำระ—
confirmingพบการโอนและกำลังยืนยัน หรือโอนมาไม่ครบและยังเติมเพิ่มได้—
paidชำระแล้วจัดส่ง / บันทึกยอดคำสั่งซื้อ
paid_overชำระแล้ว และจ่ายเกินเหมือนกัน ส่วนที่เกินอยู่ในยอดคงเหลือของคุณ
wrong_amountจบโดยได้รับไม่ครบ (เมื่อหมดอายุ หรือที่การโอนไม่ครบครั้งแรกเมื่อ payment_multiple เป็น false)ธุรกิจเติมเงินบันทึกยอดที่เข้ามาได้ (paid_amount ส่วนเหรียญที่คิดตามอัตรามี paid_cents ด้วย) ร้านค้าขอให้ลูกค้าจ่ายส่วนที่เหลือ
closedหมดอายุโดยไม่ได้รับเงินเลย หรือคุณปิดไปแล้ว— (เงินที่เข้ามาทีหลังยังถูกบันทึกและแจ้งให้ทราบ)

ฟิลด์อื่น ๆ: pay_url (หน้าชำระเงิน), payments (ทุกการโอนพร้อม txid, amount, confirmations และ confirmed), expires_at, paid_at, closed_at ส่วน BTC, LTC, DOGE, BCH และเหรียญประจำเครือข่ายมี rate (ดอลลาร์สหรัฐต่อเหรียญ ล็อก 30 นาที), rate_locked_until และ paid_cents (ยอดที่เข้ามาแล้วเป็นเซนต์สหรัฐ) ด้วย

เครือข่าย

ส่ง id เป็น network GET /v1/networks คืนเครือข่ายที่เปิดอยู่ในขณะนี้ตามโหมดของคุณ เครือข่ายอาจถูกพัก จึงควรอ่านจากที่นี่แทนการฝังค่าไว้ในโค้ด

networkเหรียญเชนขั้นต่ำ
USDT_TRC20USDTTRON$1
USDT_BEP20USDTBNB Chain$1
USDC_BEP20USDCBNB Chain$1
USDT_ERC20USDTEthereum$5
USDC_ERC20USDCEthereum$5
USDC_BASEUSDCBase$1
USDT_POLYGONUSDTPolygon$1
USDC_POLYGONUSDCPolygon$1
USDT_ARBITRUMUSDTArbitrum$1
USDC_ARBITRUMUSDCArbitrum$1
USDT_OPTIMISMUSDTOptimism$1
USDC_OPTIMISMUSDCOptimism$1
USDT_AVALANCHEUSDTAvalanche$1
USDC_AVALANCHEUSDCAvalanche$1
USDT_XLAYERUSDTX Layer$1
USDC_XLAYERUSDCX Layer$1
USD1_BEP20USD1BNB Chain$1
FDUSD_BEP20FDUSDBNB Chain$1
DAI_ERC20DAIEthereum$5
DAI_ARBITRUMDAIArbitrum$1
DAI_BASEDAIBase$1
BTCBTCBitcoin$5
LTCLTCLitecoin$1
DOGEDOGEDogecoin$1
BCHBCHBitcoin Cash$1
TRXTRXTRON$1
BNBBNBBNB Chain$1
ETHETHEthereum$5
ETH_BASEETHBase$1
ETH_ARBITRUMETHArbitrum$1
ETH_OPTIMISMETHOptimism$1
POLPOLPolygon$1
AVAXAVAXAvalanche$1
OKBOKBX Layer$1
USDT_SOLUSDTSolana$1
USDC_SOLUSDCSolana$1
SOLSOLSolana$1
USDT_TONUSDTTON$1
TONTONTON$1

บัญชีฝากเงิน (ที่อยู่คงที่) POST /v1/deposit-accounts

POST /v1/deposit-accounts พร้อม {"customer_ref": "user_42"} ให้ลูกค้ารายนั้นมีที่อยู่ถาวรบนทุกเครือข่าย (เชน EVM ทั้งหมดใช้ที่อยู่เดียวกัน) สิ่งที่ลูกค้าส่งมาจะถูกบันทึกเป็นดอลลาร์สหรัฐ พร้อม webhook deposit.credited หนึ่งครั้งต่อการโอน

curl
curl -X POST https://blockwallets.io/v1/deposit-accounts \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"customer_ref":"user_42"}'
json
{
  "id": "dac_01J8…",
  "mode": "live",
  "customer_ref": "user_42",
  "deposit_url": "https://blockwallets.io/deposit/dac_01J8…",
  "min_amount": 100,
  "currency": "USD",
  "networks": [
    { "id": "USDT_TRC20", "chain": "tron", "token": "USDT", "address": "TXy4…8kQ2", "min_amount": 100, "confirmations": 1, … },
    { "id": "USDC_BASE", "chain": "base", "token": "USDC", "address": "0x5aE1…", "min_amount": 100, "confirmations": 20, … }
  ]
}

การโอนที่ต่ำกว่าขั้นต่ำ (ปกติ $1, BTC $5) จะถูกบันทึกเป็น below_min และไม่ถูกบันทึกยอดให้อัตโนมัติ ติดต่อเราเพื่อให้บันทึกยอดให้

Webhook

เรา POST JSON ไปที่ URL webhook ในแดชบอร์ด (“นักพัฒนา › การเชื่อมต่อและคีย์” Live และ Test มี URL และ secret ของตัวเอง) เนื้อหาคืออีเวนต์:

http
POST /your/webhook
X-BW-Event: ev_01J8…
X-BW-Delivery: 1
X-BW-Signature: t=1793693052,v1=5f0c9b…

{"id":"ev_01J8…","type":"invoice.paid","created_at":"2026-11-03T08:04:12.000Z","invoice":{"id":"inv_01J8…","ref":"order_1042","status":"paid","amount":4200,…}}
อีเวนต์เมื่อไร
invoice.paidใบแจ้งหนี้เป็น paid หรือ paid_over (รวมถึงเงินที่เข้ามาหลังหมดอายุ)
invoice.wrong_amountใบแจ้งหนี้จบเป็น wrong_amount
invoice.closedใบแจ้งหนี้หมดอายุโดยไม่ได้รับเงินเลย หรือคุณปิดไปแล้ว
deposit.creditedการโอนเข้าบัญชีฝากเงินถูกบันทึกยอดแล้ว

ตรวจกับเนื้อหาดิบก่อนแยกวิเคราะห์ ปฏิเสธ t ที่ห่างจากนาฬิกาของคุณเกิน 300 วินาที และเปรียบเทียบด้วยเวลาคงที่ invoice / deposit ในเนื้อหาเป็นอ็อบเจกต์เดียวกับที่การค้นหาคืนมา

Node.js
import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), header: X-BW-Signature
function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.trim().split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return typeof parts.v1 === "string" && parts.v1.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}

การตอบ 2xx นับว่าส่งถึงแล้ว มิฉะนั้นเราลองใหม่หลัง 1 นาที, 5 นาที, 30 นาที, 2 ชั่วโมง, 12 ชั่วโมง, 24 ชั่วโมง และ 24 ชั่วโมง (รวม 8 ครั้ง)

Events และการส่งซ้ำ

GET /v1/events?invoice_id=inv_… (หรือ deposit_id=dep_…) แสดงรายการ webhook ของใบแจ้งหนี้หรือรายการฝากหนึ่งรายการ พร้อม state, attempts, last_status และ last_error POST /v1/events/ev_…/redeliver จัดคิวส่งอีกครั้งทันที เช่นหลังจากคุณแก้ endpoint แล้ว “นักพัฒนา › บันทึก Webhook” ในแดชบอร์ดแสดงทุกครั้งที่ลองส่ง พร้อมคำขอและการตอบกลับ

โหมดทดสอบ

ใบแจ้งหนี้ที่สร้างด้วยคีย์ bw_test_ รันบนเทสต์เน็ตและไม่แตะเงินจริง หน้าชำระเงินแสดงปุ่ม “จำลองการชำระเงิน” (เต็มจำนวน / ครึ่งหนึ่ง / จ่ายเกิน) คุณจึงดูสถานะและ webhook ได้โดยไม่ต้องมีเหรียญเทสต์เน็ต