Skip to Content

エラー

すべての 4xx/5xx レスポンスは同じ JSON エンベロープを持ちます:

{ "code": 400, "message": "invalid_input", "details": [ { "field": "items[0].unit_price", "message": "must be a positive decimal string" } ] }
  • code数値の HTTP ステータス (400401404、…)。汎用的な HTTP レイヤの処理には有用ですが、分岐ロジックには message のほうを switch してください — code だけでは、例えば invalid_inputpayment_method_not_supported (どちらも 400) を区別できません。
  • messagelower-snake-case のセンチネル名で、内部の errors.go 定数から派生しています (例: INVALID_INPUT → "invalid_input")。リリース間で安定しています — こちらで switch してください。
  • details — バリデーションエラー時に設定されます。{ field, message } の配列で、クライアントが入力にエラーをひも付けられるようになっています。それ以外では省略されます。

現在、ボディには trace_idtimestamp を返していません。本ページの以前のドラフトでは両方を約束していましたが、それは計画上のものでした。サーバーログとリクエストを突き合わせる必要がある場合は、レスポンスの Date ヘッダーとゲートウェイ側のレート制限ヘッダー (X-RateLimit-*) を控え、サポートチケットでそれらを引用してください。

ゲートウェイエッジでの拒否は別の形をしています。 上記のエンベロープはバックエンドサービスが返すものです。サービスに到達する にゲートウェイで拒否されたリクエスト — /b2b/v1/* 呼び出しでの欠落 / 不正な X-Signature、未知の X-Client-ID、期限切れの X-Timestamp — は { "error": "...", "message": "..." } の形で返ります。ここで error は粗いスラグ (unauthorized / bad_request / service_unavailable)、message が詳細を運びます。数値の codedetails もありません。したがって検証側はまず HTTP ステータスで分岐し、次に message を読み、code / details はリクエストがゲートウェイを通過した場合にのみ存在するものとして扱ってください。ゲートウェイのボディ例 (401):

{ "error": "unauthorized", "message": "invalid signature" }

HTTP ステータス → 典型的なコード

HTTP典型的な code意味
400INVALID_INPUTMISSING_REQUIREDINVALID_FORMATINVALID_LENGTHINVALID_VALUEINVALID_USER_STATUSINVALID_USER_ROLEPAYMENT_METHOD_NOT_SUPPORTEDAMOUNT_BELOW_MINIMUM不正なリクエスト — details を確認
401INVALID_CREDENTIALSINVALID_TOKENTOKEN_EXPIREDINVALID_SIGNATURE (B2B); INVALID_OTPOTP_EXPIREDSESSION_EXPIRED (ダッシュボード / JWT のみ)認証失敗 — 不正なキー、期限切れタイムスタンプ、署名誤り。OTP/SESSION_EXPIRED コードはダッシュボード JWT ルート (/payment/v1/*) でのみ表面化し、純粋な B2B 統合では発生しません。
402INSUFFICIENT_CREDITマーチャントのプリペイド残高が尽きました — リトライ前にチャージしてください
403FORBIDDENIP_BLOCKEDキーは有効ですが、この呼び出しに必要なスコープ / IP 許可がありません
404NOT_FOUNDRECORD_NOT_FOUNDUSER_NOT_FOUNDSESSION_NOT_FOUNDリソースが存在しない (またはこのマーチャントには存在しない)
409ALREADY_EXISTSUSER_ALREADY_EXISTSSESSION_ALREADY_EXISTS異なるボディでの冪等性リプレイ、またはステートマシンが遷移を拒否
429TOO_MANY_REQUESTSTOO_MANY_ATTEMPTSレート制限到達; バックオフしてリトライ
500INTERNAL_SERVER_ERRORDATABASE_CONNECTION_ERRORDATABASE_QUERY_ERRORDATABASE_TRANSACTION_ERRORREDIS_CONNECTION_ERRORREDIS_OPERATION_ERROREXTERNAL_SERVICE_ERROR当方の問題; バックオフ付きでリトライ可能。(TWILIO_SERVICE_ERROR / SENDGRID_SERVICE_ERROR のようなプロバイダ固有コードは内部に存在しますが、ダッシュボード側の通知フローのみで表面化し、B2B エンドポイントには現れません。)
503SERVICE_UNAVAILABLE下流の依存が停止中。バックオフ付きでリトライ

全コードリファレンス

目にする可能性のある code 値の全集合 (payment-service/pkg/errors/errors.go と一致):

認証 & セッション (401)

  • INVALID_CREDENTIALS — ユーザー名 / パスワードまたは API キーの組み合わせが拒否された
  • INVALID_TOKEN — JWT / セッショントークンがパース不能または改ざんされている
  • TOKEN_EXPIRED — JWT の exp を過ぎた
  • INVALID_OTP — OTP が一致しない
  • OTP_EXPIRED — 発行から許容ウィンドウを超える時間が経過した OTP
  • SESSION_EXPIRED — ダッシュボードセッションが期限切れ
  • INVALID_SIGNATURE — B2B / Webhook 呼び出しの HMAC 署名不一致

認可 (403)

  • FORBIDDEN — 認証は通ったがロール / スコープ / マーチャント境界がアクションを阻止
  • IP_BLOCKED — IP が乱用リストに登録されている

未検出 (404)

  • NOT_FOUND — 汎用
  • RECORD_NOT_FOUND — 指定された ID の行が存在しない
  • USER_NOT_FOUND — ユーザー検索失敗
  • SESSION_NOT_FOUND — ダッシュボードセッション ID 未認識

競合 (409)

  • ALREADY_EXISTS — 汎用
  • USER_ALREADY_EXISTS — サインアップが一意制約に当たった
  • SESSION_ALREADY_EXISTS — セッションの重複挿入

バリデーション (400)

  • INVALID_INPUT — 汎用; details を確認
  • MISSING_REQUIRED — 必須フィールドが欠落
  • INVALID_FORMAT — 値が期待形式と一致しない (例: UUID、URL、メール)
  • INVALID_LENGTH — 値が短すぎる、または長すぎる
  • INVALID_VALUE — 値が許容される enum / 範囲外
  • INVALID_USER_STATUS — ユーザーが当該アクションを許可しない状態にある
  • INVALID_USER_ROLE — ロールに当該アクションの権限がない
  • 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)

  • DATABASE_CONNECTION_ERROR — DB に到達できなかった
  • DATABASE_QUERY_ERROR — クエリプランがランタイムで失敗
  • DATABASE_TRANSACTION_ERROR — commit/rollback 失敗
  • REDIS_CONNECTION_ERROR — Redis に到達できなかった
  • REDIS_OPERATION_ERROR — Redis コマンド失敗
  • EXTERNAL_SERVICE_ERROR — 汎用のサードパーティ障害 (以下のプロバイダ別に分類されていないもの)
  • TWILIO_SERVICE_ERROR — Twilio SMS / Verify 呼び出し失敗
  • SENDGRID_SERVICE_ERROR — SendGrid メール送信失敗
  • INTERNAL_SERVER_ERROR — 予期しない通り抜け; レスポンスの Date ヘッダー + X-RateLimit-* を控えてご連絡ください

可用性 (503)

  • SERVICE_UNAVAILABLE — クリティカルな下流が unhealthy を報告; バックオフ + リトライ

バリデーションエラー (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)

サーフェス制限
ゲートウェイ全ルート (/b2b/v1/* 含む)ゲートウェイの IP 単位 — 500 req/min、共通バケット。マーチャント単位ではありません。
公開チェックアウト (/checkout/*)より厳しいサブバケット — IP あたり 20 req/min

X-RateLimit-LimitX-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」バッジが表示され、サーバーが正常化 した後に手動で再生できます。