Nhà phát triển
API thanh toán crypto xây cho tất toán trực tiếp
Tạo hóa đơn bằng một request đã xác thực và Unheld trả về địa chỉ để trả, số tiền chính xác, và độ sâu xác nhận mà nó sẽ chờ. Tiền vào thẳng chiếc ví bạn kiểm soát — API không bao giờ nắm giữ thứ mà nó báo cáo.
Tạo hóa đơn
Một POST. Số tiền viết theo cách con người viết và được nhân theo số thập phân của chính tài sản ở phía máy chủ, nên bạn không bao giờ phải tự quy đổi sang đơn vị cơ sở.
curl -X POST https://api.unheld.io/api/v1/invoices \
-H "Authorization: Bearer $UNHELD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chainId": "11155111",
"assetType": "native",
"amountDecimal": "0.05",
"expiresInSeconds": 900,
"metadata": { "orderId": "A-1043" }
}'Phản hồi
{
"id": "e2b0…",
"status": "CREATED",
"receiveAddress": "0x…",
"expectedAmount": "50000000000000000",
"minConfirmations": 3,
"expiresAt": "2026-08-10T14:15:00.000Z",
"instructions": {
"chainId": "11155111",
"to": "0x…",
"amount": "50000000000000000",
"assetType": "native"
}
}receiveAddress được dẫn xuất từ ví của bạn và khóa vào hóa đơn này. expectedAmount tính bằng đơn vị cơ sở. minConfirmations là ngưỡng của chính chuỗi, không phải thiết lập chúng tôi tự nghĩ ra.
Xác thực và phạm vi
Khóa là bearer token, tạo trong bảng điều khiển và chỉ hiển thị một lần. Mỗi khóa mang một danh sách phạm vi rõ ràng và request bị từ chối nếu khóa thiếu phạm vi cho tuyến đó.
Các phạm vi hiện có
- invoices:write
- invoices:read
- webhooks:write
- webhooks:read
- balances:read
- customers:write
- customers:read
- subscriptions:write
- subscriptions:read
Hãy cấp tập hẹp nhất mà vẫn chạy được. Khóa chỉ tạo hóa đơn không đọc được khách hàng của bạn, và một khóa đọc bị lộ cũng không di chuyển được gì — vì không gì trong API này làm được điều đó.
Webhook bạn có thể xác minh
Mọi lần gửi đều được ký. Chữ ký là HMAC-SHA256 của dấu thời gian và phần thân thô nối bằng một dấu chấm, dùng secret webhook của bạn, gửi dưới dạng chuỗi hex.
Xác minh một lần gửi
const signature = crypto
.createHmac("sha256", webhookSecret)
.update(`${req.headers["x-timestamp"]}.${rawBody}`)
.digest("hex");
crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(req.headers["x-signature"])
);So sánh digest trong thời gian hằng số, từ chối dấu thời gian nằm ngoài cửa sổ dung sai, và coi X-Request-Id là khóa idempotency: các lần thử lại dùng lại đúng giá trị đó, nên cùng một sự kiện đến hai lần là bình thường và không được xử lý hai lần.
Sự kiện hóa đơn
Một khoản thanh toán đi qua các trạng thái chứ không nhảy thẳng từ chưa trả sang đã trả, và mỗi lần chuyển là một webhook. Trả thiếu và trả dư là sự kiện riêng, không phải lỗi.
| Sự kiện | Điều gì đã xảy ra |
|---|---|
| invoice.created | Hóa đơn đã tồn tại và địa chỉ nhận đang được theo dõi. |
| invoice.receiving | Đã thấy một giao dịch trả tiền trên chuỗi nhưng chưa được xác nhận. |
| invoice.confirming | Khoản thanh toán đang xác nhận và chưa đạt ngưỡng của chuỗi. |
| invoice.paid | Đã xác nhận đầy đủ ở độ sâu chuỗi yêu cầu. An toàn để giao hàng. |
| invoice.underpaid | Đến ít hơn dự kiến. Các khoản trả từng phần được cộng dồn, nên lần chuyển thứ hai có thể hoàn tất. |
| invoice.overpaid | Đến nhiều hơn dự kiến, được ghi nhận chính xác thay vì làm tròn bỏ đi. |
| invoice.expired | Cửa sổ đã đóng mà chưa thanh toán đủ. |
Thử toàn bộ luồng miễn phí
Thử hóa đơn, phát hiện, xác nhận và webhook mà không dùng tiền thật. Token testnet không có giá trị tiền tệ. Hoạt động testnet không phải thanh toán thật.
Phạm vi
- Nó không bao giờ giữ tiền. Không có endpoint số dư nào để rút, vì tiền vào địa chỉ của bạn và ở lại đó.
- Nó không quy đổi hay tất toán bằng tiền pháp định. Tiền đến bằng đúng tài sản và trên đúng chuỗi đã gửi.
- Chưa có SDK chính thức. Ở đây mọi thứ đều là HTTP thuần, và chúng tôi công bố ví dụ thay vì những gói mà chúng tôi sẽ bảo trì kém.
Câu hỏi của nhà phát triển
Có sandbox không?
Thử hóa đơn, phát hiện, xác nhận và webhook mà không dùng tiền thật. Token testnet không có giá trị tiền tệ. Hoạt động testnet không phải thanh toán thật.
Làm sao để không xử lý cùng một webhook hai lần?
Dùng X-Request-Id làm khóa idempotency. Các lần thử lại dùng lại đúng giá trị đó, nên hãy ghi lại và bỏ qua bản lặp. Thử lại là chuyện bình thường: một lần gửi thất bại sẽ được thử lại theo lịch chứ không bị bỏ.
Tôi có phải tự quy đổi số tiền sang đơn vị cơ sở không?
Không. Hãy gửi amountDecimal như một người viết ra và API sẽ nhân theo số thập phân của tài sản. Phản hồi trả về expectedAmount theo đơn vị cơ sở, nên cả hai cách biểu diễn đều tường minh và không thể lệch nhau.
Ví dụ đã được đối chiếu với API đang chạy vào .
Xây trên testnet trước
Tạo một khóa, trỏ nó tới một chuỗi testnet, và chạy trọn luồng trước khi bất cứ thứ gì thật sự dịch chuyển.
Bắt đầu miễn phíBảng giá · Những gì bạn có thể nhận hôm nay. · Tiền của bạn không đi qua chúng tôi.