Webhooks
Webhookは、サポートされているイベントCHAMPREPをHTTPSエンドポイントに配信します。これにより、 ポーリングが削減され、統合システムが変更が発生したその場で対応できるようになります。
Webhookの管理には、 webhooks:manage 範囲。
管理エンドポイント
Section titled “管理エンドポイント”| 方法 | パス | 目的 |
|---|---|---|
GET |
/v1/webhooks/events |
現在サポートされているイベントタイプを列挙してください。 |
GET |
/v1/webhooks |
設定済みの Webhook エンドポイントを一覧表示します。 |
POST |
/v1/webhooks |
HTTPSエンドポイントとイベントリストを登録してください。 |
PATCH |
/v1/webhooks/{webhookId} |
URL、イベント、説明、またはアクティブ状態を更新してください。 |
DELETE |
/v1/webhooks/{webhookId} |
エンドポイントを削除します。 |
POST |
/v1/webhooks/{webhookId}/rotate-secret |
署名用シークレットをローテーションしてください。 |
クエリ /v1/webhooks/events イベントカタログをハードコーディングするのではなく、サービスがパブリックイベントを追加するにつれて、 サポートされるイベントタイプを拡張できるようにします。
エンドポイントの登録
Section titled “エンドポイントの登録”curl --fail-with-body \ --request POST \ --header "Authorization: Bearer $CHAMPREP_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "url": "https://example.com/webhooks/champrep", "events": ["contact.created"], "description": "Contact synchronization" }' \ https://api.champrep.com/v1/webhooks署名用シークレットは、エンドポイントの作成時、またはそのシークレットが ローテーションされた際に返されます。直ちにシークレットマネージャーに保存してください。これはベアラーキーAPIではなく、 Webhookエンドポイントごとに一意である必要があります。
各配信は HTTPS で行われます POST JSON ボディを含む場合:
{ "id": "delivery_identifier", "type": "contact.created", "timestamp": "2026-08-08T12:00:00Z", "data": {}}配信ヘッダーには以下が含まれます:
| ヘッダー | 目的 |
|---|---|
X-CHAMPREP-Signature |
HMAC SHA-256 署名 sha256=<hex> フォーム。 |
X-CHAMPREP-Timestamp |
署名付きコンテンツにはUnixタイムスタンプが使用されます。 |
X-CHAMPREP-Delivery-Id |
重複排除のための一意の識別子。 |
X-CHAMPREP-Event |
ルーティング用のイベントタイプ。 |
以下の正確な UTF-8 バイトに対して HMAC SHA-256 を計算します。
<timestamp>.<raw-request-body> エンドポイントの署名用シークレットを使用します。 期待される署名と受信した署名を、定数時間の比較で照合してください。
import crypto from 'node:crypto';
export function verifyChamprepWebhook(rawBody, headers, secret) { const timestamp = String(headers['x-champrep-timestamp'] || ''); const received = String(headers['x-champrep-signature'] || ''); const expected = `sha256=${crypto .createHmac('sha256', secret) .update(`${timestamp}.${rawBody}`) .digest('hex')}`;
const receivedBytes = Buffer.from(received); const expectedBytes = Buffer.from(expected); return receivedBytes.length === expectedBytes.length && crypto.timingSafeEqual(receivedBytes, expectedBytes);}フレームワークがボディを解析・再シリアル化する前に、生のボディを検証してください。 再シリアル化されたオブジェクトは異なるバイト列を生成し、検証に失敗する可能性があります。
リプレイ攻撃および重複処理の防止
Section titled “リプレイ攻撃および重複処理の防止”- 選択した短い許容範囲外のタイムスタンプは拒否してください。
- 処理済みの配信IDは、少なくとも再試行ウィンドウの期間中は保存してください。
- 重複する配信IDについては、すでに処理済みとして扱い、成功 レスポンスを返してください。
- 可能な限り、ビジネス処理を冪等性を持って実行してください。
成功した 2xx 速やかに成功レスポンスを返し、負荷の高い処理はキューに移してください。 タイムアウト、ネットワーク障害、 429、サーバーエラーは再試行可能です。継続的な 失敗はエンドポイントの無効化につながる可能性があるため、配信状態を監視し、 失敗しているURLを速やかに修正してください。
署名用シークレットや完全な機密ペイロードをログに記録しないでください。シークレットが 漏洩した可能性がある場合はシークレットをローテーションし、新しい 配信を受け入れる前に受信者を更新してください。