Aller à la documentation
Base de connaissances

Webhooks

Prévenez votre point de terminaison quand du courrier arrive, au lieu de vous obliger à interroger.

Détails

  • Utilisables dès aujourd'hui depuis Paramètres → Webhooks et via l'API : enregistrez un point de terminaison https, choisissez lesquels des vingt événements il veut, et copiez le secret de signature whsec_, montré à la création et à la rotation et jamais ensuite. Les livraisons sont de vrais POST signés émis par la boîte mail elle-même plutôt que par un appel d'API : ils se déclenchent donc sur le courrier entrant et sur les ouvertures et les clics, quelle qu'en soit l'origine d'envoi. L'envoi se déclenche depuis toutes les surfaces, et auparavant il ne se déclenchait que depuis certaines : un envoi via l'API, MCP, un modèle ou une règle levait email.sent alors qu'un message envoyé depuis la fenêtre de rédaction de l'application ne le faisait pas, parce que celle-ci écrit directement dans la boîte mail plutôt que de passer par le service d'envoi qui émettait l'événement. L'événement est désormais levé au niveau de la boîte mail, là où tous se rejoignent : rédiger dans l'application, programmer pour mardi et poster sur l'API sont trois façons de provoquer le même webhook. Un envoi différé le dit deux fois : email.scheduled ou email.queued à son acceptation, email.sent quand il part réellement, et email.cancelled si vous le reprenez entre-temps. Dix points de terminaison par boîte mail, appliqué partout où l'on en enregistre un plutôt que sur ce seul écran.
  • Les événements se répartissent en trois familles. Quinze portent sur un message : email.received, email.replied, email.sent, email.delivered, email.failed, email.cancelled, email.scheduled, email.queued (le pendant de scheduled pour l'annulation d'envoi), email.delivery_delayed, email.bounced, email.complained, email.suppressed, email.opened, email.clicked et email.downloaded. email.sent signifie que le service d'envoi a accepté le message, email.delivered que le serveur destinataire l'a accepté, et email.delivery_delayed qu'il n'est pas encore arrivé et que les tentatives se poursuivent. email.replied se déclenche à côté de email.received quand le message qui arrive répond à un message déjà présent dans la boîte mail, si bien qu'un consommateur qui veut les deux les obtient tous les deux. email.downloaded se déclenche quand une personne récupère un fichier parti sous forme de lien de téléchargement, avec le même classificateur qui tient les scanners et les aperçus de liens hors du compte, et il ne nomme aucun destinataire, car le lien est le même pour tous ceux à qui le message est parti. Trois portent sur un domaine : domain.verified quand il commence à recevoir, domain.sending_changed quand son verdict d'envoi bouge, et domain.deleted quand il est supprimé, que vous l'ayez demandé ou que le nettoyage à sept jours l'ait retiré faute de vérification. Deux portent sur la liste de suppression elle-même, qui est autre chose que email.suppressed : suppression.added quand une adresse y entre, suppression.removed quand une adresse est de nouveau autorisée. N'en souscrire aucun signifie tous les événements de message sauf email.replied, soit quatorze aujourd'hui, jamais une famille ajoutée plus tard, et l'API relit cela comme ["*"]. Nommez les événements voulus si vous préférez être explicite. Chaque livraison porte X-OpenEmail-Signature sous la forme t=<unix>,v1=<hex>, un HMAC-SHA-256 sur l'horodatage, un point, et le corps brut, ainsi que X-OpenEmail-Event et X-OpenEmail-Delivery. Vérifiez sur les octets tels qu'ils sont arrivés : analyser puis resérialiser réordonne les clés et casse la signature. La fenêtre de rejeu de 300 secondes est au destinataire de l'appliquer, et le vérificateur du SDK la prend par défaut.
  • L'enregistrement est refusé pour tout ce qui n'est pas https ou n'est pas routable publiquement (loopback, RFC1918, link-local, CGNAT et les équivalents IPv6), et les redirections ne sont pas suivies : un 3xx est donc enregistré comme une livraison échouée plutôt que poursuivi ailleurs. Le destinataire dispose de 5 secondes, les points de terminaison sont livrés en parallèle, si bien que dix d'entre eux coûtent toujours 5 secondes plutôt que 50, et les tentatives récentes sont listées sur la page du point de terminaison avec le code de réponse et la durée.
  • Une livraison est tentée jusqu'à cinq fois. La première part au moment de l'événement ; un échec susceptible de se résoudre de lui-même est retenté après 1 minute, puis 5, puis 25, puis 2 heures, ce qui étale un événement sur environ deux heures et demie. Les nouvelles tentatives sont conservées comme travail durable plutôt qu'en mémoire : un déploiement au milieu de cette fenêtre ne les perd donc pas. Seuls les échecs qui valent la peine d'être répétés le sont : un dépassement de délai, une connexion refusée, 408, 425, 429 ou n'importe quel 5xx. Tout autre 4xx est le point de terminaison qui rejette délibérément la charge utile, et demander quatre fois de plus ferait quatre fois la charge pour la même réponse. L'identifiant de l'événement est créé une seule fois et chaque tentative le porte dans X-OpenEmail-Delivery : un destinataire qui voit deux fois le même identifiant peut donc ignorer le second plutôt qu'agir deux fois. Après 100 événements d'affilée dont toutes les tentatives échouent, le point de terminaison est désactivé, l'espace de travail reçoit un e-mail, et la raison est lisible sur le point de terminaison lui-même. Un point de terminaison qui répond 410 Gone est désactivé sur-le-champ.
  • Un point de terminaison qui échoue 100 fois d'affilée est désactivé plutôt que rappelé indéfiniment, et toutes les personnes ayant accès aux webhooks reçoivent un e-mail pour le dire : lequel, ce qu'a rapporté la dernière tentative, et que rien n'a été mis en file pendant qu'il échouait. Le compteur est CONSÉCUTIF et toute tentative livrée le remet à zéro : un mauvais après-midi en mars dernier ne peut donc pas s'additionner en une désactivation aujourd'hui. Le réactiver remet aussi le compteur à zéro. La console distingue les deux états plutôt que d'afficher un seul interrupteur : un point de terminaison que vous avez désactivé n'a pas la même allure qu'un point de terminaison que nous avons désactivé.
  • Gérer les points de terminaison est une seule tâche avec deux portes d'entrée. Via l'API, c'est POST /webhooks, le patch, le delete, la rotation du secret, le test et le journal de livraison, avec une méthode pour chacun dans le SDK ; dans l'application, c'est Paramètres → Webhooks, sur le même registre plutôt qu'un second. La lecture est conditionnée à webhooks:read, si bien que quiconque construit une intégration peut voir les points de terminaison et leur historique de livraison (lequel s'est déclenché, ce qu'a répondu le destinataire, combien de temps cela a pris) sans être le propriétaire. Enregistrer, modifier, tester, faire tourner et supprimer exigent webhooks:write ET la propriété de la boîte mail, sur les deux surfaces, et cette seconde moitié est délibérée : un point de terminaison n'a pas d'axe d'adresse, il reçoit donc chaque adresse que détient l'espace de travail, avec les sujets et les destinataires, et aucune permission ne veut dire « peut recevoir tout cela ». Un rôle qui construit des intégrations et ne lit pas le courrier pilote cela avec une clé d'espace de travail à la place.