エラー
すべての 4xx/5xx レスポンスは同じ JSON エンベロープを持ちます:
{
"code": 400,
"message": "invalid_input",
"details": [
{ "field": "items[0].unit_price", "message": "must be a positive decimal string" }
]
}code— 数値の HTTP ステータス (400、401、404、…)。汎用的な HTTP レイヤの処理には有用ですが、分岐ロジックにはmessageのほうを switch してください —codeだけでは、例えばinvalid_inputとpayment_method_not_supported(どちらも 400) を区別できません。message— lower-snake-case のセンチネル名 (センチネル名を小文字のスネークケースにしたもの。例:INVALID_INPUTは"invalid_input"になります)。リリース間で安定しています — こちらで switch してください。details— バリデーションエラー時に設定されます。{ field, message }の配列で、クライアントが入力にエラーをひも付けられるようになっています。それ以外では省略されます。
エラーボディにはトレース ID もタイムスタンプも含まれません。問題を報告する際は、レスポンスの Date ヘッダー、X-RateLimit-* ヘッダー、マーチャント ID、エンドポイント、おおよそのリクエスト時刻をサポートにお送りください。
認証失敗は別の形をしています。 上記のエンベロープは、ほとんどのエラーで API が返すものです。処理される前に拒否されたリクエスト (/b2b/v1/* 呼び出しでの欠落 / 不正な X-Signature、未知の X-Client-ID、期限切れの X-Timestamp) は { "error": "...", "message": "..." } の形で返ります。ここで error は粗いスラグ (unauthorized / bad_request / service_unavailable)、message が詳細を運びます。数値の code も details もありません。まず HTTP ステータスで分岐し、次に message を読んでください。例 (401):
{ "error": "unauthorized", "message": "invalid signature" }HTTP ステータス → 典型的なコード
| HTTP | 典型的な code 値 | 意味 |
|---|---|---|
| 400 | INVALID_INPUT、MISSING_REQUIRED、INVALID_FORMAT、INVALID_LENGTH、INVALID_VALUE、PAYMENT_METHOD_NOT_SUPPORTED、AMOUNT_BELOW_MINIMUM | 不正なリクエスト — details を確認 |
| 401 | INVALID_CREDENTIALS、INVALID_TOKEN、TOKEN_EXPIRED、INVALID_SIGNATURE (B2B); SESSION_EXPIRED (ダッシュボードのみ) | 認証失敗 — 不正なキー、期限切れタイムスタンプ、署名誤り。ダッシュボードのサインイン関連コードは B2B 統合には関係ありません。 |
| 402 | INSUFFICIENT_CREDIT | マーチャントのプリペイド残高が尽きました — リトライ前にチャージしてください |
| 403 | FORBIDDEN、IP_BLOCKED | キーは有効ですが、この呼び出しに必要なスコープ / IP 許可がありません |
| 404 | NOT_FOUND、RECORD_NOT_FOUND | リソースが存在しない (またはこのマーチャントには存在しない) |
| 409 | ALREADY_EXISTS | 異なるボディでの冪等性リプレイ、またはステートマシンが遷移を拒否 |
| 429 | TOO_MANY_REQUESTS、TOO_MANY_ATTEMPTS | レート制限到達; バックオフしてリトライ |
| 500 | INTERNAL_SERVER_ERROR、EXTERNAL_SERVICE_ERROR | 当方の問題; バックオフ付きでリトライ可能。 |
| 503 | SERVICE_UNAVAILABLE | 下流の依存が停止中。バックオフ付きでリトライ |
全コードリファレンス
目にする可能性のある code 値:
認証 (401)
INVALID_CREDENTIALS— API キーの組み合わせが拒否されたINVALID_TOKEN— トークンがパース不能または改ざんされているTOKEN_EXPIRED— トークンが期限切れSESSION_EXPIRED— ダッシュボードセッションが期限切れINVALID_SIGNATURE— B2B / Webhook 呼び出しの HMAC 署名不一致
認可 (403)
FORBIDDEN— 認証は通ったが、このアクションを実行する権限がないIP_BLOCKED— この IP アドレスからのリクエストはブロックされている
未検出 (404)
NOT_FOUND— 汎用RECORD_NOT_FOUND— 指定された ID の行が存在しない
競合 (409)
ALREADY_EXISTS— 汎用
バリデーション (400)
INVALID_INPUT— 汎用;detailsを確認MISSING_REQUIRED— 必須フィールドが欠落INVALID_FORMAT— 値が期待形式と一致しない (例: UUID、URL、メール)INVALID_LENGTH— 値が短すぎる、または長すぎるINVALID_VALUE— 値が許容される enum / 範囲外PAYMENT_METHOD_NOT_SUPPORTED— プロバイダ / アセットの組み合わせがマーチャントに対して有効化されていないAMOUNT_BELOW_MINIMUM— 注文額がネットワーク別または環境レベルの下限を下回っている。レスポンスのdetails.floor_usdに設定された下限 (USD) が入っているので、そのまま表示できます;messageテキストにも同じ内容が記載されています。INSUFFICIENT_BALANCE— バイヤーのウォレットが送金分の支払いアセットを十分に保有していない。INSUFFICIENT_GAS— バイヤーのウォレットが送金をブロードキャストするためのネイティブトークン(ネットワーク手数料用)を保有していない。
決済 / 課金 (402)
INSUFFICIENT_CREDIT— マーチャントのプリペイド残高がネットワーク手数料(ガス)とプラットフォーム手数料を賄えない。ダッシュボードからチャージしてリトライしてください
レート制限 (429)
TOO_MANY_REQUESTS— IP のレート制限を超過TOO_MANY_ATTEMPTS— 同じリソースに対する繰り返し失敗 (例: OTP) がスロットルを発動
サーバーエラー (500)
EXTERNAL_SERVICE_ERROR— サードパーティプロバイダが失敗したINTERNAL_SERVER_ERROR— 予期しないエラー; レスポンスのDateヘッダーとX-RateLimit-*ヘッダーを添えてサポートにご連絡ください
可用性 (503)
SERVICE_UNAVAILABLE— サービスが一時的に利用できません; バックオフ付きでリトライ
バリデーションエラー (400)
リクエストボディの形式不正が原因の場合、details は配列なので、
エラーをフィールドに紐付けてマッピングできます:
{
"code": 400,
"message": "invalid_input",
"details": [
{ "field": "items[0].unit_price", "message": "must be a positive decimal string" },
{ "field": "success_url", "message": "must be a valid https URL" }
]
}認証エラー (401)
INVALID_SIGNATURE の一般的な原因は 3 つあります:
- 不正なシークレットキー (環境変数を再確認)
- タイムスタンプのずれが 5 分超 (NTP で同期)
- 不正な canonical 文字列 (最も多いのは:
\nセパレータ漏れ、または、送信したものと異なるパース後に再シリアライズしたボディに署名している)
正確な署名アルゴリズムは 認証 を参照してください。
レート制限 (429)
| サーフェス | 制限 |
|---|---|
全 API ルート (/b2b/v1/* 含む) | IP アドレス単位 — 500 req/min、共通バケット。マーチャント単位ではありません。 |
公開チェックアウト (/checkout/*) | より厳しいサブバケット — IP あたり 20 req/min |
X-RateLimit-Limit と X-RateLimit-Remaining は、レート制限がかかった
すべてのレスポンスに含まれます (成功時のみではありません)。
あなたの IP に対する現在のバジェットとして扱ってください。
レート制限のレスポンスには Retry-After ヘッダー (ウィンドウがリセットされる
までの秒数) が含まれます — これに従ってください。フォールバックとして、
ジッタ付きでバックオフ — ベース 1s から指数的に 30s まで。
レート制限は変更される可能性があります。正当なトラフィックで制限に 達する場合 (例: 大規模な過去範囲の整合性チェック) は、サポートにご連絡ください。
残高不足 (402)
INSUFFICIENT_CREDIT (HTTP 402 Payment Required) は、プリペイド残高が、
実行しようとしていた操作 (典型的には暗号資産決済の精算、またはネットワーク
手数料がスポンサーされるオンチェーン処理) のネットワーク手数料(ガス)と
プラットフォーム手数料をカバーできないことを意味します。
マーチャントダッシュボードからチャージし (Billing → Add credit)、
操作をリトライしてください。すでに進行中の操作は、チャージ後に自動的に継続されます。
サーバーエラー (5xx)
500 はリクエストを処理できなかったことを意味します。バックオフ付きで
リトライ — idempotency_key があれば、元のリクエストが部分的に成功
していても二重課金になりません。
リトライが 1 分以内に回復しない場合、バイヤーには「一時的に決済が
利用できません」と一般的なメッセージを表示し、失敗したエンドポイント、
マーチャント ID、レスポンスの Date ヘッダーと X-RateLimit-* の値、
おおよそのリクエスト時刻を添えてサポートにご連絡ください — それで
該当リクエストを特定できます。
Webhook 配信エラー
Webhook 配信は別の失敗チャネルです — あなたのサーバーが呼び出し側 ではないため、API エラーとしては表面化しません。配信が non-2xx を 返す (またはタイムアウトする) と、0s、1min、5min、15min、1h、6h の 指数バックオフでリトライされます (合計 6 回 — Webhook → 概要 と同じスケジュール)。配信単位の完全な 履歴は、ダッシュボードの Developers → Webhooks → [endpoint] → Delivery log に表示されます。6 回目の試行後、配信はダッシュボードで 「Failed」と表示され、サーバーが正常化した後に手動で再生できます。