請求書を作成する
POSTが1回です。金額は人が書くとおりに指定でき、サーバー側で資産固有の小数桁数に合わせて変換されるため、基本単位へ手作業で換算する必要はありません。
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" }
}'レスポンス
{
"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はあなたのウォレットから導出され、この請求書に固定されます。expectedAmountは基本単位です。minConfirmationsはチェーン自身のしきい値であり、当社が考案した設定値ではありません。
認証とスコープ
キーはベアラートークンで、ダッシュボードで作成され、一度だけ表示されます。すべてのキーは明示的なスコープの一覧を持ち、そのルートに必要なスコープがなければリクエストは拒否されます。
利用できるスコープ
- invoices:write
- invoices:read
- webhooks:write
- webhooks:read
- balances:read
- customers:write
- customers:read
- subscriptions:write
- subscriptions:read
動作する範囲で最も狭い組み合わせを付与してください。請求書の作成だけができるキーは顧客情報を読めませんし、漏れた読み取り専用のキーでは何も動かせません。このAPIには、そもそも何かを動かす手段がないからです。
検証できるウェブフック
すべての配信に署名が付きます。署名は、タイムスタンプと生のボディをドットで連結したものに対するHMAC-SHA256で、ウェブフックのシークレットを鍵として16進数のダイジェストで送信されます。
配信を検証する
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"])
);ダイジェストの比較は一定時間で行い、許容範囲外のタイムスタンプは拒否し、X-Request-Idを冪等キーとして扱ってください。再送は同じ値を再利用するため、同一のイベントが2回届くのは正常であり、2回処理してはいけません。
請求書のイベント
支払いは未払いから支払済みへ切り替わるのではなく、状態を移っていきます。そのすべての遷移がウェブフックになります。不足と超過はエラーではなく、それぞれ独立したイベントです。
| イベント | 何が起きたか |
|---|---|
| invoice.created | 請求書が存在し、受取アドレスの監視が始まっています。 |
| invoice.receiving | 支払いの取引がオンチェーンで確認されましたが、まだ確定していません。 |
| invoice.confirming | 支払いは承認を集めている途中で、チェーンのしきい値には達していません。 |
| invoice.paid | チェーンが要求する深さで完全に確定しました。商品を引き渡して問題ありません。 |
| invoice.underpaid | 想定より少ない額が届きました。一部の支払いは加算されるため、2回目の送金で完了できます。 |
| invoice.overpaid | 想定より多い額が届きました。丸めずに正確に記録されます。 |
| invoice.expired | 全額の支払いがないまま、受付期間が終了しました。 |
全体の流れを無料で試す
本番の資金を使わずに、請求書の作成、検出、承認、ウェブフックをテストできます。 テストネットのトークンに金銭的価値はありません。テストネット上の取引は実際の支払いではありません。
対象範囲
- 資金を保有しません。支払いはあなたのアドレスに届いてそのまま留まるため、引き出すための残高エンドポイントは存在しません。
- 法定通貨への変換も決済も行いません。支払いは送られた資産のまま、送られたチェーン上に届きます。
- 公式SDKはまだありません。ここにあるのはすべて素のHTTPで、十分に保守しきれないパッケージを配るのではなく、実例を公開しています。
開発者からの質問
サンドボックスはありますか。
本番の資金を使わずに、請求書の作成、検出、承認、ウェブフックをテストできます。 テストネットのトークンに金銭的価値はありません。テストネット上の取引は実際の支払いではありません。
同じウェブフックを二重に処理しないようにするには。
X-Request-Idを冪等キーとして使ってください。再送は同じ値を再利用するので、それを記録して重複を無視します。再送は想定された動作です。配信に失敗したものは破棄されるのではなく、決められた間隔で再送されます。
金額を自分で基本単位に変換する必要がありますか。
いいえ。amountDecimalに人が書くとおりの値を送れば、APIが資産固有の小数桁数に合わせて変換します。レスポンスは基本単位のexpectedAmountを返すので、2つの表現が両方とも明示され、ずれることがありません。
稼働中のAPIと照合した実例の確認日: .