Aller au contenu

Webhooks

hook = client.webhooks.create("https://example.com/hook",
events=["artifact.updated", "job.completed"])
secret = hook["secret"] # この応答でのみ取得可能
# 受信側
from d2b.client import _Webhooks
ok = _Webhooks.verify_delivery(secret, request.headers, raw_body) # signature + heure d'envoi (par défaut : dans les 5 min)
  • Signature : X-D2B-Signature-V2: sha256=<hex> = HMAC-SHA256(secret, "{X-D2B-Delivery}.{X-D2B-Timestamp}." + raw_body). X-D2B-Timestamp est l’heure d’envoi de cette tentative (secondes UNIX, renouvelée à chaque nouvelle tentative) : rejetez toute requête dont l’âge dépasse votre tolérance (par exemple 5 minutes) pour contrer les rejeux. X-D2B-Delivery est l’identifiant de la livraison (identique à chaque nouvelle tentative). Vérifiez sur le corps brut (sans le resérialiser)
  • L’ancienne signature X-D2B-Signature: sha256=<hex> = HMAC-SHA256(secret, raw_body) est toujours envoyée. Elle ne porte pas d’heure d’envoi et ne peut donc pas empêcher un rejeu
  • Événements : artifact.updated / artifact.deleted / artifact.stale / snapshot.committed / source.analyzed / source.materialized / conflict.created / version.branched / version.merged / job.completed
  • Historique des livraisons : GET /api/v1/me/webhooks/{id}/deliveries
  • Nouvelles tentatives : les réponses non 2xx et les échecs de connexion sont retentés jusqu’à 14 fois avec un délai exponentiel de 30 s à 1 h (environ 8 heures au total). Une livraison qui échoue encore reste visible sous deliveries mais n’est plus retentée. Chaque événement produit une livraison, mais une tentative dont la réponse n’est jamais arrivée est retentée : la même livraison (le même X-D2B-Delivery) peut donc vous parvenir plusieurs fois. Traitez les livraisons de façon idempotente, avec X-D2B-Delivery comme clé. Le timestamp du payload est l’heure de l’événement et ne change pas lors des nouvelles tentatives

Pour les traitements longs (ingestion d’un gros fichier, etc.), la recommandation est d’en faire un job avec async=true et d’attendre job.completed — moins cher qu’une boucle de polling, et plus robuste face aux timeouts des agents.