ガイドと洞察

冪等パートナー API の自動化: 重複した副作用を発生させずに AI 顧客、キー、クレジットをプロビジョニング

パートナー API の自動化は、タイムアウト、Webhook イベントの重複、同時ワーカー、金額解析ミスなどにより、最初のリクエスト後に最も頻繁に失敗します。永続的な操作、安定した冪等性キー、正確な 10 進数の処理、および調整を中心としたプロビジョニングとクレジットのワークフローを構築します。

サインアップ ワーカーが顧客グループを作成すると、HTTP リクエストがタイムアウトになり、ジョブ ランナーが新しいリクエストで再試行します。同じ顧客が 2 つのグループ、2 つの API キー、または間違った上流オブジェクトを指すローカル データベース レコードを持っている可能性があります。 Webhook ハンドラーは各配信を新しいビジネス イベントとして扱うため、支払い Webhook は 1 分後に到着し、2 回配信され、顧客に 2 回クレジットされます。

これがパートナー API 自動化における本当の失敗モードです。最初の呼び出しが成功することが難しい部分であることはほとんどありません。難しいのは、ネットワークに障害が発生し、ワーカーがクラッシュし、ユーザーがダブルクリックし、決済プロバイダーが Webhook を再試行し、後で財務データを調整する必要がある場合でも、ビジネスの意図を維持することです。

実際のパターンは単純です。変化するすべてのパートナー API アクションを、ファイアアンドフォーゲット HTTP リクエストとしてではなく、永続的なビジネス操作として扱います。つまり、ローカル操作記録を保存し、冪等キーを意図的に使用し、資金を正確に解析し、Webhook を非同期で処理し、補償変更を発行する前に未知の結果を調整することを意味します。

個別の事実、推奨事項、予測

事実

Model Gate のパートナー API ドキュメントには、POSTPATCH、および DELETE リクエストには Idempotency-Key が必要であること、タイムアウト後の再試行では同じキーを再利用する必要があること、冪等レコードは 7 日間保持されることが記載されています。

同じドキュメントには、金額と制限は JSON 10 進数文字列であると記載されています。これらは、バイナリ浮動小数点型を通じて変換されるのではなく、正確な 10 進数値または文字列として処理される必要があります。

パートナー API は、残高、監査イベント、グループ、キー、リクエスト、トランザクションの管理およびレポート機能を公開します。監査イベントは、リクエスト ID、アクション、ターゲット、ソース IP、ステータス、安全なメタデータ、UTC タイムスタンプなどのフィールドを使用して、成功した管理変更を記録します。

Stripe では、作成操作と更新操作を安全に再試行する方法として冪等キーを文書化しています。 Webhook ガイダンスでは、エンドポイントが同じイベントを複数回受信する可能性があることも警告し、処理されたイベント ID をログに記録し、非同期で処理することを推奨しています。

AWS と Azure のガイダンスは、同じ分散システム ルールを強化しています。つまり、再試行は便利ですが、サーバーが呼び出し元の意図を保持できるように、変更操作には呼び出し元が提供するリクエスト ID または同等の反復性コントラクトが必要です。

推奨事項

プロビジョニング、キーの作成、支出制限の変更、クレジットの補充、ウォレットのチェック、Webhook 主導のフルフィルメントに 1 つのローカル操作台帳を使用します。台帳を、インテント、試行、アップストリーム リクエスト ID、結果のターゲット ID、および調整状態に関する統合の永続的な信頼できる情報源にします。

インテントが安定している安定したビジネス インテントから冪等キーを生成します。タイムアウトまたはサーバー結果が不明な場合は、同じキーを再利用します。ビジネス運営が意図的に新しい場合にのみ、新しいキーを生成します。

Webhook は 2 つのフェーズで処理されます。イベント ID を迅速に検証して保持し、冪等ワーカーを通じてビジネス アクションを非同期的に実行します。

予測

AI アクセスを再販する代理店や SaaS プラットフォームが増えるにつれ、サポートの問題は基本的な API 接続から調整へと移行していきます。つまり、顧客プロビジョニングの重複、クレジットの紛争、ウォレット残高の不一致、不明確な監査証跡などです。永続的なローカル操作記録を保持する統合は、HTTP 応答とログのみに依存する統合よりもサポートが容易になります。

ローカル パートナーの業務台帳を作成する

オペレーション台帳には、最初のパートナー API リクエストが送信される前のビジネス オペレーションが記録されます。追加しやすく、顧客によるクエリが可能であり、2 人のワーカーが同じ操作を同時に実行できないように厳密である必要があります。

便利なスキーマは次のようになります:

partner_operations
- Operation_id // 内部 UUID
- external_customer_id // 顧客、テナント、またはアカウント ID
- アクション // create_group、create_key、set_limit、top_up_credit
- idempotency_key // リクエストを変更するためにパートナー API に送信されます
- request_fingerprint // メソッド、パス、および意味のある本体の正規ハッシュ
- model_gate_request_id // X-Request-ID、または利用可能な場合は同等の応答識別子
- target_public_id // グループ ID、キー ID、トランザクション ID、またはその他の結果のオブジェクト
- ステータス // 保留中、成功、failed_retryable、failed_final、調整中
- 試行回数
- last_error_code
- last_error_message
- 作成された場所
- 更新日
- locked_until

重要な制約は、ビジネス目的による一意性です。たとえば、external_customer_id + action +signup_version は、初期プロビジョニングでは一意にすることができます。 2 回目の意図的な補充は、最初の補充と衝突してはなりません。異なるオペレーション ID とべき等性キーを持つ必要があります。

サインアップ フローの場合、provision_customer などの単一の親オペレーションを作成し、create_groupcreate_key、および set_initial_limit の子オペレーションを追跡します。これにより、バックエンドがどの外部ミューテーションがスタックしているかを正確に把握しながら、UI には顧客向けの 1 つのステータスが表示されます。

ビジネス目的から冪等キーを構築する

冪等キーは、再試行に耐えられるほど安定しており、2 つの異なる操作が 1 つに集約されるのを避けるのに十分な具体性を持っている必要があります。決定論的な形式は、サポート チームと調整チームがシステムについて推論するのに役立ちます。

create-group-for-custom:{customer_id}:{signup_version}
顧客のキーの作成:{顧客ID}:{グループID}:{キーの目的}:{バージョン}
set-spend-limit:{customer_id}:{group_id}:{limit_policy_version}
トップアップ:{customer_id}:{payment_event_id}:{ledger_entry_id}

操作が同じで前の結果が不明な場合は、同じ冪等キーを使用します。例には、クライアントのタイムアウト、リクエスト本文の送信後の接続のリセット、レスポンスを保存する前のワーカーのクラッシュ、サーバーがすでに変更を完了している可能性がある 5xx などがあります。

ビジネスの意図が変更された場合は、新しい冪等キーを使用します。顧客が 2 つ目のクレジット パッケージを購入する場合は、新たなチャージとなります。管理者が個別の承認後に支出制限を 100.00 から 250.00 に引き上げるのは、新しい操作です。リクエスト本文が大幅に変更された場合、修正されたサインアップ テンプレートのキーに新しいバージョンが必要になる場合もあります。

リクエストのフィンガープリントをキーの横に保存します。コードが別のペイロードで同じ冪等キーを再利用しようとすると、Partner API を呼び出す前にローカルで失敗します。このチェックにより、テンプレートの移行や部分的な再試行中に微妙なバグが検出されます。

顧客をステート マシンとしてプロビジョニングする

プロビジョニング ワーカーは、1 つのトランザクションでデータベース、パートナー API、および下流の請求システムをカバーできると想定するのではなく、明示的な状態を通過する必要があります。

pending_create_group
  - ローカル操作記録の作成
  - 冪等性キーを使用してグループ作成リクエストを送信します
  - ストアリクエストIDとグループパブリックID

group_created_key_pending
  - キー操作記録の作成
  - Idempotency-Key を使用してキー作成リクエストを送信します
  - セキュリティ ポリシーに従ってキーのメタデータとシークレットを保存します

key_created_limit_pending
  - 支出制限操作記録を作成する
  - 冪等性キーを使用した制限更新の送信
  - 結果のポリシー バージョンまたはターゲット ID を保存します

プロビジョニング済み
  - 顧客に準備完了のマークを付ける
  - 内部監査イベントを発行する
  - 製品システムに通知します

このステート マシンにより、クラッシュが発生しても存続可能になります。グループの作成後、キーを保存する前に作業者が死亡した場合、代わりの作業者が操作台帳を検査し、同じ冪等キーを再利用して作業を続行できます。グループが上流に存在するがローカル保存に失敗した場合、リコンシリエーションでは、別のオブジェクトをやみくもに作成するのではなく、グループ、キー、トランザクション、および監査サーフェスを通じてターゲットを見つけることができます。

お金を10進数データとして扱う

クレジット、ウォレット残高、使用制限、使用量合計、および取引金額は、バイナリ浮動小数点型を通過しないでください。 0.10 などの値は、測定値ではなく財務値です。元の JSON 10 進数文字列を取り込み境界に保存し、算術演算用に正確な 10 進数型にのみ変換します。

JavaScript では、Number の周りに請求ロジックを記述しないでください。 10 進数ライブラリを使用するか、専用の通貨モジュールに到達するまで値を文字列として保持します。 Python では、浮動小数点ではなく文字列の Decimal を使用します。データベースでは、算術演算が必要な場合は固定スケールの数値列を使用し、正確な上流表現を保持することが監査に役立つ場合はテキスト列を使用します。

// 悪い: バイナリ浮動小数点変換
const limit = Number(apiResponse.spend_limit);

// より良い: 正確な小数点境界
const limit = new Decimal(apiResponse.spend_limit);

同じルールを比較に適用します。一方をセントに丸め、もう一方をプロバイダーの精度に丸める支出制限チェックでは、リクエストが誤ってブロックまたは許可される可能性があります。 1 つの内部精度ポリシーを定義して文書化し、ゼロ付近の境界値、最小補充額、および移行の制限をテストします。

Webhook 取り込みを退屈にする

Webhook ハンドラーは、複雑なプロビジョニングをインラインで実行しないでください。ハンドラーの仕事は、イベントを認証し、その ID を保持し、すぐに返すことです。フルフィルメントは、安全に再試行できるワーカーに属します。

payment_webhook_events
- プロバイダー
- イベントID
- イベントの種類
- 受信した時刻
- ペイロードハッシュ
- 処理状況
- 関連顧客ID
- 関連操作 ID
- last_error

provider +event_id に一意の制約を設定します。同じイベントが 2 回到着した場合は、すでに保存または処理されていることを確認した後、成功を返します。配達が 2 回発生したため、ウォレットに 2 回入金しないでください。

フルフィルメント担当者は、一致する top_up_credit オペレーションを作成または検索する必要があります。その冪等キーには、支払いイベント ID と内部台帳エントリ ID を含めることができます。 Partner API のトップアップが成功した後、ローカル状態が更新される前にワーカーがクラッシュした場合、次の試行では同じキーが再利用され、結果のトランザクションがリコンサイルされます。

パートナー API 呼び出しを変更するための再試行ルール

再試行にはルールが必要です。これらがないと、再試行コードは重複した副作用を生成するものになります。

ネットワーク タイムアウト、接続のリセット、および不明な 5xx 結果の場合は、文書化された保持期間内に同じ Idempotency-Key を使用して同じリクエストを再試行してください。すべての試行を操作台帳に記録します。

429 応答の場合、指定された場合は Retry-After を尊重し、同じ操作に対して同じ冪等キーを維持します。レート制限によってビジネスの意図が変わることはありません。

検証エラーの場合は、自動的に再試行しないでください。オペレーションに失敗のマークを付け、特定のエラーを明らかにし、意図したペイロードが変更された場合は新しいリクエスト フィンガープリントを使用して修正されたオペレーションを要求します。

ペイロードの変更によって冪等性キーの競合が発生した場合は、停止します。それはローカルのバグまたは安全でない再試行です。ビジネス オペレーションが明示的に新規であり、ワークフローによって承認されない限り、新しいキーを自動的に生成しないでください。

補償する前に未知の結果を調整する

未知の結果が得られた場合、最も安全な次のステップは通常、代償変異ではありません。まず、何が起こったのか聞いてください。

操作台帳を使用して、冪等キー、リクエストのフィンガープリント、および最後に確認されたリクエスト ID を見つけます。次に、関連するパートナー API サーフェス、つまりプロビジョニングのグループとキーのリスト、クレジット チャージのトランザクション、ウォレットの状態の残高、使用状況のリクエスト レコード、管理の変更の監査イベントを確認します。

実際の調整シーケンスは次のとおりです:

<オル>
  • ロックを使用してローカル操作レコードをリロードします。
  • 保持期間内にあり、リクエストのフィンガープリントが一致する場合は、同じ冪等キーを使用して元のミューテーションを再試行します。
  • 再試行しても状態が解決しない場合は、関連するリストをクエリするか、顧客のメタデータ、グループ ID、キー ID、トランザクション ID、またはタイムスタンプを使用してエンドポイントを取得します。
  • リクエスト ID、アクション、ターゲット、UTC タイムスタンプに関連付けられた成功した管理変更の監査イベントを確認する
  • 証拠を伴って、ローカル操作を succeededfailed_final、または reconciliation_needed に更新します。
  • 上流の状態を確認し、補償のための新しい操作を記録した後でのみ、補償ミューテーションを発行します。
  • 7 日間の冪等性保持期間は、通常の再試行期間には便利ですが、アカウンティング アーカイブではありません。サポート、資金調達、紛争の遅延について、永続的なローカル記録を保管します。

    行き詰まった状態のためのランブック

    保留中_作成_グループ

    操作記録が存在するかどうか、および冪等性キーが送信されたかどうかを確認します。リクエストがパートナー API に到達した可能性がある場合は、同じキーを使用して再試行します。リクエストが送信された証拠がない場合は、元のリクエストを送信し、結果のリクエスト ID を保存します。

    group_created_key_pending

    グループ ターゲット ID をローカルおよびアップストリームで確認します。 2 番目のグループを作成しないでください。独自の冪等キーを使用してキー操作を作成するか、再試行してください。

    key_created_local_save_failed

    API キーのシークレットは 1 回しか表示されないことが多いため、これはセキュリティ上重要です。シークレットがポリシーに従って保存されていない場合は、ローカルでキーを使用不可としてマークし、明示的な操作によってキーを取り消すかローテーションし、新しいビジネス目的で代替キーを作成します。

    topup_requested_unknown

    可能であれば、同じ冪等キーを使用してトップアップを再試行します。次に、取引とウォレットの残高を調整します。最初の応答が失われたからといって、2 回目の補充を発行しないでください。

    webhook_received_processing_failed

    Webhook イベントを受信済みかつ未履行としてマークしたままにします。原因を解決した後、ワーカー経由で再実行します。固有のイベント レコードにより、重複したフルフィルメントが防止されます。

    調整_必要

    リクエスト ID、べき等キー、顧客 ID、ターゲット ID、タイムスタンプ、最後のエラーを使用して、オペレーションを内部サポート キューに割り当てます。手動レビューでは、別のプライベート証跡を作成するのではなく、同じ操作記録を更新する必要があります。

    テストのチェックリスト

    • 同じ顧客に対して登録ボタンが重複してクリックされると、1 つのグループと 1 つの目的のキーが作成されます。
    • アップストリームの成功後、ローカル保存が再開される前にワーカーがクラッシュするが、重複した副作用は発生しません。
    • レスポンス本文が処理される前の HTTP タイムアウトは、同じ冪等キーを再試行することで処理されます。
    • 支払い Webhook が重複しても、クレジット チャージは重複して作成されません。
    • 順序どおりでない支払い Webhook とプロビジョニング ジョブが正しい顧客状態に収束する
    • Retry-After を含む 429 レスポンスは、オペレーション ID を変更せずに再試行を遅らせます。
    • ペイロードを変更した冪等キーを再利用すると、ローカルで失敗します。
    • 0.010.10100.00 付近の 10 進数値、および支出制限の境界は予期せず丸められません。
    • 監査イベントの調整により、グループ、キー、または制限を誰がいつ変更したかを説明できます。
    • 冪等性保持期間よりも古いオペレーションは、ブラインド リプレイではなく、ローカル レコードとパートナー API レポート サーフェスを通じて調整されます。

    トレードオフ

    決定論的冪等性キーにより再試行と調査が容易になりますが、真に新しいインテントにキーを再利用することを避けるために十分なビジネス コンテキストを含める必要があります。

    ローカル操作台帳により、スキーマとワークフローが複雑になりますが、ネットワーク呼び出し、Webhook、データベース書き込みがさまざまなタイミングで失敗した場合に、統合に永続的な信頼できる情報源が提供されます。

    Webhook 取り込みからすぐに戻るとプロバイダーの再試行が減りますが、信頼性の高いキュー、リプレイ ツール、および処理エラーを可視化するための監視が必要です。

    厳密なリクエスト フィンガープリント チェックにより、異なるペイロードでのキーの誤った再利用が防止されますが、サインアップのデフォルトや制限テンプレートが変更されると、明示的なバージョン管理が強制されます。

    残高、トランザクション、グループ、キー、監査エンドポイントを介した調整は、元の応答を信頼するよりも時間がかかります。また、結果が不明な場合でも、これがより安全な方法です。

    実用的な結論

    Reliable Partner API の自動化は、HTTP 統合の問題であると同時に、会計および運用の問題でもあります。まず、永続的なビジネス オペレーションを定義します。顧客グループの作成、キーの作成、制限の変更、クレジットの補充、ウォレットの調整、Webhook の処理などです。各オペレーションに安定した冪等性キー、リクエストのフィンガープリント、ステータス マシン、永続的なローカル レコードを与えます。

    次に、すべてのワーカーを退屈にします。操作を取得し、意図したリクエストを正確に送信し、未知の結果の後に同じ冪等キーを再利用し、10 進文字列を正確に解析し、補正する前に調整します。この設計によってすべての障害が除去されるわけではありませんが、顧客に副作用が重複することなく、障害が説明可能、再試行可能、監査可能になります。

    関連資料

    FAQ

    よくある質問

    すべてのパートナー API リクエストでべき等キーを使用する必要がありますか?
    POST、PATCH、DELETE などの変更パートナー API リクエストでは、文書化された契約に従って冪等キーを使用する必要があります。読み取り専用リクエストは通常​​、同じ処理を必要としませんが、その結果は調整中に使用できます。
    1 つの冪等キーを複数の顧客のチャージに再利用できますか?
    いいえ。同じキーを再利用するのは、同じビジネス操作を再試行する場合のみです。 2 番目の意図的なトップアップは新しいビジネス操作であり、新しい操作レコードと冪等性キーを受け取る必要があります。
    グループ作成中にタイムアウトが発生した後はどうすればよいですか?
    タイムアウトを記録し、元の操作を保留中または再試行可能な状態に保ち、保持期間内に同じ冪等キーを使用して同じグループ作成リクエストを再試行します。結果が不明瞭な場合は、何かを作成する前に、グループの記録と監査イベントを通じて調整してください。
    なぜお金を 10 進数の文字列または正確な 10 進数として保存するのでしょうか?
    ウォレットの残高、クレジット金額、合計使用量、および使用限度額は財務データです。バイナリ浮動小数点変換では丸め誤差が生じる可能性があるため、取り込みでは 10 進数文字列を保持するか、正確な 10 進数型に変換する必要があります。