CirculeID

Webhooks

興味深いのは配信が失敗したときに何が起きるか

署名、再試行、順序、冪等性がこの契約のすべてです。正常系だけを扱う連携は未完成であり、まだ始まってもいません。

配信
最低1回
署名済み
生のボディに対して
再試行
指数バックオフ

Definition

パスポートのWebhookはどう動作しますか。

パスポート、イベント、クレデンシャルに変更があると、CirculeIDは署名付きコールバックを貴社のエンドポイントへ送信します。配信は指数バックオフ付きの最低1回保証であるため、ハンドラは署名を検証し、重複した配信識別子を無処理として扱い、処理前にAPIで現在の状態を読み直す必要があります。

Treat a payload as a notification, not as the record. That single habit removes the entire class of bug where a delayed retry overwrites newer data with older data.

イベント

購読できるもの

リソースごとにまとめています。購読は絞ってください。処理しないイベントを受け取るエンドポイントは、障害を誰も調べないエンドポイントになります。
Webhook のイベント種別と、それぞれが何を知らせるか
EventFires whenTypical handler
passport.createdA passport is issued against an identifierPrint or encode the data carrier
passport.updatedThe record changes materiallyRe-read state; refresh a cached storefront view
event.recordedAn EPCIS event is appended to an objectAdvance an internal workflow
credential.issuedA supplier signs a claim against your productClear the compliance gap for that field
credential.revokedAn issuer withdraws a claimRe-open the gap; review anything that relied on it
passport.gap_detectedA delegated act change leaves a field unmetRaise it to the compliance owner

検証

パースする前に検証する

署名は生のボディに対して計算してください。再シリアライズしたオブジェクトでは一致しません。タイムスタンプの許容範囲外のものは拒否してください。
Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody, header, secret) {
  const [ts, signature] = parseHeader(header);

  // Reject replays before doing any work.
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

  const expected = createHmac('sha256', secret)
    .update(`${ts}.${rawBody}`)   // raw body, exactly as received
    .digest();

  // Constant-time: a fast reject leaks the signature one byte at a time.
  return timingSafeEqual(Buffer.from(signature, 'hex'), expected);
}

契約

プラットフォームが保証すること

  • 署名済みのペイロード

    エンドポイントごとのシークレットを用いた生ボディに対するHMACと、タイムスタンプ。

  • 最低1回の配信

    再試行するシステムに対する誠実な保証です。ハンドラーは冪等でなければなりません。

  • 指数バックオフ

    長めのウィンドウにわたり再試行するため、短時間の障害では何も失われません。

  • すべてのペイロードにバージョンを付与

    すでに通過したバージョンを示す配信は無視してください。

  • 可視化された失敗ログ

    失敗した配信は一覧に表示され、再送できます。黙って破棄されることはありません。

  • 範囲を絞った購読

    イベント種別ごとに購読すれば、エンドポイントは自らが処理するものだけを受け取ります。

回答

よくある質問

そのWebhookが本当にCirculeIDから来たとどう確認しますか。

各配信には、生のリクエストボディに対する署名とタイムスタンプが付きます。パースの前にエンドポイントのシークレットで署名を検証し、タイムスタンプが許容範囲外の配信は拒否してください。未検証のペイロードを信頼するエンドポイントは、誰でも送信できるエンドポイントです。

配信順序は保証されますか。

オブジェクト単位でベストエフォートですが、それに依存しないでください。再試行やネットワークの状況により、古いイベントが新しいイベントより後に届くことがあります。各ペイロードは自らが反映するオブジェクトのバージョンを保持しているため、ハンドラは到着順を前提とせず、すでに通過したバージョンを示す配信を無視すべきです。

自社のエンドポイントが停止していた場合はどうなりますか。

配信は長めのウィンドウにわたり指数バックオフで再試行され、失敗ログはアカウント内で確認できます。無言で終わることはありません。ウィンドウが切れると配信は失敗として記録されますが、元の変更はAPIから照会できるため、Webhookの障害はデータ損失ではなく遅延にとどまります。

同じイベントが二重に配信されることはありますか。

はい。そうなる前提でご実装ください。少なくとも1回の配信は、再試行を行うあらゆるシステムにとっての誠実な保証です。各配信には安定した識別子が付くため、正しいハンドラーはその識別子を記録し、重複を何もしない操作として扱います。これにより、失敗した時間帯の再送も安全になります。

Webhookのペイロードを完全なレコードとして信頼してよいですか。

ペイロードは信頼できる唯一の情報源ではなく、通知として扱ってください。何かが変わったことを伝え、それが自社に関係するかを判断できるだけの情報を与えます。対応する場合は、API を通じて現在の状態を読み直してください。そうすれば、古い配信や順序の入れ替わった配信が、古いデータを自社システムに書き込むことはありません。

Next step

最初の一つはテスト用エンドポイントに向けてください

サンドボックスで購読し、意図的にエンドポイントを壊して、再試行と再送の挙動を確認してから本番で依存してください。

Index