REST API ของเรา
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 ทุกคำขอมี:
Authorization: Bearer bw_live_…หรือBearer bw_test_…: คำนำหน้ากำหนดโหมด คีย์ Test จึงเห็นเฉพาะใบแจ้งหนี้ Test และรันบนเทสต์เน็ตContent-Type: application/jsonในคำขอPOST- เก็บคีย์ไว้ที่เซิร์ฟเวอร์ของคุณเท่านั้น ห้ามใส่ในหน้าเว็บหรือแอป เราเก็บเฉพาะค่าแฮชของคีย์
ข้อผิดพลาดตอบกลับเป็นสถานะ 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 -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 เป็นจำนวนเหรียญแบบสตริงทศนิยมบนเครือข่ายที่เลือก
{
"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_TRC20 | USDT | TRON | $1 |
USDT_BEP20 | USDT | BNB Chain | $1 |
USDC_BEP20 | USDC | BNB Chain | $1 |
USDT_ERC20 | USDT | Ethereum | $5 |
USDC_ERC20 | USDC | Ethereum | $5 |
USDC_BASE | USDC | Base | $1 |
USDT_POLYGON | USDT | Polygon | $1 |
USDC_POLYGON | USDC | Polygon | $1 |
USDT_ARBITRUM | USDT | Arbitrum | $1 |
USDC_ARBITRUM | USDC | Arbitrum | $1 |
USDT_OPTIMISM | USDT | Optimism | $1 |
USDC_OPTIMISM | USDC | Optimism | $1 |
USDT_AVALANCHE | USDT | Avalanche | $1 |
USDC_AVALANCHE | USDC | Avalanche | $1 |
USDT_XLAYER | USDT | X Layer | $1 |
USDC_XLAYER | USDC | X Layer | $1 |
USD1_BEP20 | USD1 | BNB Chain | $1 |
FDUSD_BEP20 | FDUSD | BNB Chain | $1 |
DAI_ERC20 | DAI | Ethereum | $5 |
DAI_ARBITRUM | DAI | Arbitrum | $1 |
DAI_BASE | DAI | Base | $1 |
BTC | BTC | Bitcoin | $5 |
LTC | LTC | Litecoin | $1 |
DOGE | DOGE | Dogecoin | $1 |
BCH | BCH | Bitcoin Cash | $1 |
TRX | TRX | TRON | $1 |
BNB | BNB | BNB Chain | $1 |
ETH | ETH | Ethereum | $5 |
ETH_BASE | ETH | Base | $1 |
ETH_ARBITRUM | ETH | Arbitrum | $1 |
ETH_OPTIMISM | ETH | Optimism | $1 |
POL | POL | Polygon | $1 |
AVAX | AVAX | Avalanche | $1 |
OKB | OKB | X Layer | $1 |
USDT_SOL | USDT | Solana | $1 |
USDC_SOL | USDC | Solana | $1 |
SOL | SOL | Solana | $1 |
USDT_TON | USDT | TON | $1 |
TON | TON | TON | $1 |
บัญชีฝากเงิน (ที่อยู่คงที่) POST /v1/deposit-accounts
POST /v1/deposit-accounts พร้อม {"customer_ref": "user_42"} ให้ลูกค้ารายนั้นมีที่อยู่ถาวรบนทุกเครือข่าย (เชน EVM ทั้งหมดใช้ที่อยู่เดียวกัน) สิ่งที่ลูกค้าส่งมาจะถูกบันทึกเป็นดอลลาร์สหรัฐ พร้อม webhook deposit.credited หนึ่งครั้งต่อการโอน
curl -X POST https://blockwallets.io/v1/deposit-accounts \
-H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
-d '{"customer_ref":"user_42"}'{
"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, … }
]
}customer_ref: 1–128 ตัวอักษร เป็นตัวอักษร ตัวเลข และ_ . : @ -ค่าเดิมได้บัญชีเดิมเสมอreturn_urlไม่บังคับ ต้องอยู่ในโดเมนของคุณ- การตอบกลับมี
deposit_url(หน้าที่เราโฮสต์ แสดงที่อยู่ คิวอาร์โค้ด และรายการฝากล่าสุด) และnetworks(แต่ละเครือข่ายมีid,address,min_amount,confirmations) - id รายการฝากขึ้นต้นด้วย
dep_amountเป็นเซนต์สหรัฐamount_tokenคือจำนวนเหรียญ และเหรียญที่มีราคาจะมีrateที่ใช้มาด้วย
การโอนที่ต่ำกว่าขั้นต่ำ (ปกติ $1, BTC $5) จะถูกบันทึกเป็น below_min และไม่ถูกบันทึกยอดให้อัตโนมัติ ติดต่อเราเพื่อให้บันทึกยอดให้
Webhook
เรา POST JSON ไปที่ URL webhook ในแดชบอร์ด (“นักพัฒนา › การเชื่อมต่อและคีย์” Live และ Test มี URL และ secret ของตัวเอง) เนื้อหาคืออีเวนต์:
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,…}}X-BW-Signature:t=<unix seconds>,v1=<hex>โดยv1= HMAC-SHA256(webhook secret ของโหมดนั้น,t+.+ เนื้อหาดิบ)X-BW-Event: id ของอีเวนต์ (ev_…) ใช้ตัดรายการซ้ำX-BW-Delivery: ครั้งที่ส่ง เริ่มที่ 1
| อีเวนต์ | เมื่อไร |
|---|---|
invoice.paid | ใบแจ้งหนี้เป็น paid หรือ paid_over (รวมถึงเงินที่เข้ามาหลังหมดอายุ) |
invoice.wrong_amount | ใบแจ้งหนี้จบเป็น wrong_amount |
invoice.closed | ใบแจ้งหนี้หมดอายุโดยไม่ได้รับเงินเลย หรือคุณปิดไปแล้ว |
deposit.credited | การโอนเข้าบัญชีฝากเงินถูกบันทึกยอดแล้ว |
ตรวจกับเนื้อหาดิบก่อนแยกวิเคราะห์ ปฏิเสธ t ที่ห่างจากนาฬิกาของคุณเกิน 300 วินาที และเปรียบเทียบด้วยเวลาคงที่ invoice / deposit ในเนื้อหาเป็นอ็อบเจกต์เดียวกับที่การค้นหาคืนมา
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 ได้โดยไม่ต้องมีเหรียญเทสต์เน็ต