Webhook
hook = client.webhooks.create("https://example.com/hook", events=["artifact.updated", "job.completed"])secret = hook["secret"] # この応答でのみ取得可能
# 受信側from d2b.client import _Webhooksok = _Webhooks.verify_delivery(secret, request.headers, raw_body) # 署名 + 送信時刻(既定 5 分以内)- 署名:
X-D2B-Signature-V2: sha256=<hex>= HMAC-SHA256(secret,"{X-D2B-Delivery}.{X-D2B-Timestamp}." + raw_body)。X-D2B-Timestampはその試行の送信時刻(UNIX 秒、再送のたびに更新)なので、現在時刻との差が許容範囲(例: 5 分)を超える要求は拒否してください(リプレイ対策)。X-D2B-Deliveryは配信 ID(再送でも同じ値)。生のボディで検証してください(再シリアライズしない) - 従来の署名
X-D2B-Signature: sha256=<hex>= HMAC-SHA256(secret, raw_body) も引き続き送ります。送信時刻を含まないため、リプレイは防げません - イベント:
artifact.updated/artifact.deleted/artifact.stale/snapshot.committed/source.analyzed/source.materialized/conflict.created/version.branched/version.merged/job.completed - 配信履歴:
GET /api/v1/me/webhooks/{id}/deliveries - 再送: 2xx 以外・接続失敗は最大 14 回、30 秒から 1 時間まで指数的に間隔を広げて(合計およそ 8 時間)再送します。それでも届かない配信は
deliveriesに残りますが再送されません。1 イベントにつき配信は 1 つですが、応答が届かなかった試行は再送されるため、同じ配信(同じX-D2B-Delivery)が複数回届くことはあり得ます。受信側はX-D2B-Deliveryで冪等に処理してください。ペイロードのtimestampはイベントの発生時刻で、再送でも変わりません
長い処理(大きいファイルの取り込みなど)は async=true で job にし、job.completed を待つのが推奨です — poll ループより安く、エージェントのタイムアウトにも強くなります。