Webhooks : s'abonner aux événements de liens et d'espace de travail

Envoyez des requêtes HTTP POST signées depuis Elido vers votre serveur lorsque les liens, domaines, membres et votre espace de travail changent. En-têtes, charges utiles, nouvelles tentatives, journal de livraison et rotation du secret.

10 min de lectureMis à jour 2026-09-22

Ce que vous allez configurer

  • Un endpoint qui reçoit des événements Elido tels que link.created, link.updated, link.deleted, member.invited et domain.verified.
  • La vérification HMAC-SHA256 de l'en-tête X-Elido-Signature, afin que votre serveur puisse confirmer que chaque livraison provient bien d'Elido.
  • Trois tentatives de livraison par événement, un journal de livraison avec un bouton Retry manuel et la rotation du secret avec un chevauchement de 7 jours.

Les webhooks transmettent les événements d'Elido à votre serveur au moment où ils se produisent, pour vous éviter d'interroger l'API périodiquement. Utilisations courantes : synchroniser les métadonnées des liens avec un CRM, tenir à jour un index interne des liens ou lancer une tâche lorsqu'un lien est publié.

Les webhooks couvrent les changements concernant les liens, les domaines, les membres et l'espace de travail. Ils ne transportent pas les clics individuels. Pour les données de clics, utilisez l'export des clics ou une intégration d'événements comme Mixpanel. Les événements webhook par clic sont prévus.

Ajouter un endpoint webhook

  1. Accédez à Dashboard → Webhooks.
  2. Saisissez l'URL à laquelle nous devons envoyer la requête POST et une description facultative.
  3. Choisissez le type d'endpoint : Events (vous sélectionnez les types d'événements) ou SIEM (firehose) (tous les événements de l'espace de travail).
  4. Pour un endpoint Events, cochez les types d'événements souhaités. Les événements link.* sont cochés par défaut.
  5. Cliquez sur Add endpoint. Le secret de signature apparaît une seule fois, juste sous le formulaire. Copiez-le maintenant : Elido ne l'affichera plus.

L'URL doit être en HTTPS. Le protocole http:// simple est rejeté lors de l'enregistrement de l'endpoint, sauf pour localhost et 127.0.0.1, qui restent autorisés pour le développement local.

Vous pouvez mettre un endpoint en pause et le réactiver depuis la liste. Un endpoint en pause ne reçoit aucune nouvelle livraison, et tout ce qui est encore en file d'attente pour cet endpoint attend sa réactivation.

Qui peut gérer les webhooks

Toute personne dans l'espace de travail peut consulter les endpoints et le journal de livraison. La création, la modification, la mise en pause, la suppression, la rotation du secret et la nouvelle tentative d'une livraison nécessitent la permission workspace.edit, détenue par les rôles intégrés Admin et Owner. Une clé API peut appeler les mêmes endpoints webhook de l'API si son rôle dispose de cette permission.

Types d'endpoint

  • Events (event) : reçoit uniquement les types d'événements auxquels vous vous êtes abonné. Signé.
  • SIEM (siem) : reçoit chaque événement publié pour l'espace de travail, y compris audit.event pour chaque entrée du journal d'audit. Signé. Conçu pour les pipelines de journaux et les outils de sécurité.
  • Discord, Telegram et Sentry : canaux de discussion et d'alerte qui réutilisent le même système de livraison, mais envoient le propre format du fournisseur. Ils s'authentifient via l'URL ou le jeton du fournisseur et ne transportent donc aucun en-tête de signature. Voir Discord, Telegram et Sentry.

Tout ce qui suit concernant les signatures et les secrets s'applique uniquement aux endpoints Events et SIEM.

Catalogue des événements

Les noms suivent le format <resource>.<action>. Le formulaire du tableau de bord propose les plus courants ; via l'API, vous pouvez abonner un endpoint Events à n'importe quel type de cette liste, et un endpoint SIEM les reçoit tous.

Dans le sélecteur du tableau de bord :

  • link.created : un lien court a été créé, y compris les liens créés en masse.
  • link.updated : un lien a changé (destination, titre, tags, expiration, etc.), a été restauré, son statut a changé ou son statut de sécurité a été modifié par la modération.
  • link.deleted : un lien a été supprimé de manière réversible.
  • workspace.updated : les paramètres de l'espace de travail ont changé.
  • workspace.created : publié lors de la création d'un espace de travail. Comme aucun endpoint ne peut exister dans un espace de travail avant sa création, vous ne recevrez normalement pas celui-ci.
  • member.invited : une personne a rejoint l'espace de travail, par ajout direct, acceptation d'une invitation ou approvisionnement SCIM.
  • member.removed : un membre a été supprimé, manuellement ou via SCIM.
  • audit.event : un événement par entrée du journal d'audit.

Disponibles via l'API ou un endpoint SIEM :

  • link.expired : un lien a dépassé sa date d'expiration.
  • link.cap_reached : un lien a atteint sa limite de clics. data contient cap et clicks.
  • link.broken : le contrôle de santé des liens d'Elido a constaté que la destination échouait. data contient status_code, error_message et first_seen_at.
  • link.encrypted_created et link.encryption_rotated : pour les liens chiffrés.
  • domain.verified : un domaine personnalisé a réussi son contrôle DNS.
  • domain.ssl_failed : les enregistrements DNS d'un domaine personnalisé étaient toujours introuvables 24 heures après son ajout. Malgré son nom, cet événement concerne la vérification DNS, et non le renouvellement du certificat.
  • member.role_changed : le rôle d'un membre a changé. data contient old_role, new_role et changed_by_user_id.
  • invitation.created et invitation.accepted.
  • Événements de facturation : subscription.* (par exemple subscription.activated, subscription.renewed, subscription.canceled) et usage.threshold_80, usage.threshold_100.

Prévus et non envoyés aujourd'hui : link.clicked.aggregated (comptes de clics par lien et par fenêtre), les événements par clic, conversion.recorded, domain.tls_renewed, qr.generated et un événement abuse.flagged distinct. Une décision de modération concernant un lien arrive actuellement sous la forme de link.updated avec le nouvel abuse_status.

Structure de la charge utile

Chaque livraison signée est une requête POST avec Content-Type: application/json, User-Agent: Elido-Webhooks/1.0 et cette enveloppe :

{
  "type": "link.created",
  "workspace_id": 4123,
  "timestamp": "2026-09-22T09:42:11Z",
  "data": {
    "id": 891234,
    "workspace_id": 4123,
    "domain_id": 12,
    "slug": "spring-2026",
    "destination_url": "https://acme.com/spring-sale",
    "title": "Spring sale",
    "tags": ["email"],
    "status": "active",
    "expires_at": null,
    "created_by_user_id": 5821,
    "created_at": "2026-09-22T09:42:11Z"
  }
}
  • type est le type d'événement. Il figure également dans l'en-tête X-Webhook-Event.
  • timestamp indique le moment où l'événement s'est produit, en UTC.
  • data dépend de l'événement. Pour les événements link.*, il s'agit de l'objet lien complet (l'exemple ci-dessus est abrégé). Pour les autres événements, il s'agit d'un petit objet contenant les ID et les champs répertoriés dans le catalogue.
  • Les secrets ne quittent jamais Elido : les champs tels que le hash du mot de passe d'un lien ou un jeton d'invitation sont retirés de data avant la livraison.

Le corps ne contient pas encore de champ id pour l'événement ; un ID par événement est prévu. Pour assurer l'idempotence, utilisez l'en-tête X-Webhook-Delivery, décrit ci-dessous.

En-têtes et signatures

Chaque livraison vers un endpoint Events ou SIEM contient les éléments suivants :

En-têteValeur
X-Elido-Signaturev1= suivi de la signature HMAC-SHA256 hexadécimale
X-Webhook-SignatureMême valeur que X-Elido-Signature, conservée pour les intégrations plus anciennes
X-Webhook-TimestampHeure Unix en secondes à laquelle cette requête a été signée
X-Webhook-EventLe type d'événement, par exemple link.created
X-Webhook-DeliveryL'ID de livraison. Il reste identique lors des nouvelles tentatives de la même livraison
X-Elido-Signature-PreviousUniquement pendant une rotation du secret : même signature produite avec l'ancienne clé

La signature est calculée ainsi :

v1=hex( HMAC-SHA256( secret, "{X-Webhook-Timestamp}.{raw request body}" ) )

La clé est l'intégralité de votre chaîne secrète, préfixe whsec_ inclus, utilisée telle quelle. Signez les octets bruts reçus, et non un objet JSON sérialisé à nouveau, puis comparez-les en temps constant. Voici un court exemple Node (Express) :

import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";

const SECRET = process.env.ELIDO_WEBHOOK_SECRET; // full whsec_... value

function same(a, b = "") {
  const x = Buffer.from(a);
  const y = Buffer.from(b);
  return x.length === y.length && timingSafeEqual(x, y);
}

const app = express();
app.post(
  "/webhooks/elido",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const ts = req.get("X-Webhook-Timestamp") ?? "";
    if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
      return res.status(400).send("stale timestamp");
    }
    const expected =
      "v1=" +
      createHmac("sha256", SECRET)
        .update(`${ts}.`)
        .update(req.body)
        .digest("hex");
    const ok = [
      req.get("X-Elido-Signature"),
      req.get("X-Elido-Signature-Previous"),
    ].some((sig) => same(expected, sig));
    if (!ok) return res.status(401).send("bad signature");

    const event = JSON.parse(req.body.toString("utf8"));
    // queue event for processing, then answer quickly
    res.sendStatus(200);
  },
);

Pour les versions Python et Go, un vecteur de test et les erreurs courantes, consultez comment vérifier les signatures webhook.

Faire tourner le secret de signature

Ouvrez l'endpoint dans Dashboard → Webhooks et cliquez sur Rotate secret. Le nouveau secret whsec_ est affiché une seule fois, puis Elido l'utilise pour les signatures.

L'ancienne clé reste valide pendant une période de grâce de 7 jours. Pendant cette période, chaque livraison contient deux signatures : X-Elido-Signature avec la nouvelle clé et X-Elido-Signature-Previous avec l'ancienne, afin qu'un récepteur qui n'a pas encore basculé puisse continuer à vérifier les signatures. Acceptez l'un ou l'autre en-tête pendant le déploiement du nouveau secret.

Les endpoints créés avant le 22 septembre 2026 constituent une exception : leur première rotation ne produit pas de X-Elido-Signature-Previous, et le secret d'origine cesse donc de fonctionner immédiatement. Déployez le nouveau secret juste après cette première rotation. Les endpoints créés depuis cette date produisent deux signatures dès la première rotation. À partir de la deuxième rotation, le chevauchement de 7 jours s'applique.

Nouvelles tentatives

Une livraison échoue en cas de réponse autre que 2xx, d'erreur réseau ou d'absence de réponse dans les 10 secondes. Chaque livraison bénéficie de 3 tentatives au total :

  1. La première tentative, quelques secondes après l'événement.
  2. Une nouvelle tentative environ 5 minutes après le premier échec.
  3. Une dernière tentative environ 15 minutes après le deuxième échec.

Si la troisième tentative échoue, la livraison est marquée failed et ne fait plus l'objet de nouvelles tentatives automatiques. L'endpoint reste actif et les nouveaux événements continuent d'être livrés. Votre endpoint peut voir la même livraison plusieurs fois (par exemple, s'il a traité une requête mais répondu après le délai de 10 secondes) : dédupliquez donc avec X-Webhook-Delivery.

Journal de livraison

Ouvrez un endpoint dans Dashboard → Webhooks pour voir ses 100 livraisons les plus récentes. Pour chacune, vous obtenez le type d'événement, le statut (pending, delivered ou failed), le statut HTTP renvoyé par votre serveur, le temps de réponse, le nombre de tentatives utilisées sur 3, les dates de création et de fin, l'heure de la prochaine tentative pour les livraisons en attente, la dernière erreur et la charge utile complète envoyée.

Toute livraison réussie ou échouée possède un bouton Retry. Il remet la même livraison en file d'attente (avec le même ID X-Webhook-Delivery, mais une nouvelle signature) et lui attribue un nouveau budget de 3 tentatives. Via l'API, GET /v1/workspaces/{workspace_id}/webhooks/{id}/deliveries parcourt les livraisons plus anciennes avec limit (jusqu'à 100) et offset, et POST .../deliveries/{delivery_id}/retry fait la même chose que le bouton. Si vous ne pouvez pas rejouer une livraison vous-même, le support Elido peut le faire pour vous.

L'enregistrement du corps de réponse de votre serveur dans le journal est prévu.

Tests locaux

Une commande CLI qui transfère les webhooks vers localhost (npx @elido/cli webhooks forward) est prévue. En attendant, exposez votre serveur local via un tunnel tel que ngrok ou Cloudflare Tunnel, ajoutez l'URL HTTPS du tunnel comme endpoint, puis supprimez-le lorsque vous avez terminé.

Limites

  • 10 secondes pour répondre depuis votre endpoint.
  • 3 tentatives de livraison par événement, plus les nouvelles tentatives manuelles.
  • L'API du journal de livraison renvoie au maximum 100 livraisons par page.

Résolution des problèmes

La signature ne correspond jamais. Les causes habituelles sont les suivantes : votre framework a analysé puis sérialisé à nouveau le JSON avant que vous le hachiez (hachez le corps brut), vous avez supprimé le préfixe whsec_ de la clé ou vous signez avec le timestamp du corps au lieu de l'en-tête X-Webhook-Timestamp. L'article sur la vérification des signatures contient un vecteur de test pour vérifier votre code.

La signature ne correspond plus après une rotation. Votre serveur utilise toujours l'ancien secret. Déployez le nouveau. Pour un endpoint créé avant le 22 septembre 2026, la première rotation ne fournit pas de X-Elido-Signature-Previous sur lequel s'appuyer.

Certains événements arrivent deux fois. Elido a effectué une nouvelle tentative parce que votre endpoint a répondu avec une erreur ou a mis plus de 10 secondes à répondre. Dédupliquez avec X-Webhook-Delivery et répondez avec un statut 2xx avant d'effectuer les opérations lentes.

Un type d'événement n'arrive jamais. Vérifiez que l'endpoint y est abonné, qu'il n'est pas en pause et que le type figure dans le catalogue ci-dessus. Les types marqués comme prévus ne sont pas encore envoyés.

Cela vous a-t-il été utile ?
Besoin de plus ? Écrivez à l'équipe - réponse sous un jour ouvré.Contacter le support