Comment fonctionnent les webhooks

Il s'agit plutôt d'un article technique, mais en bref, les webhooks Commslayer délivrent des notifications d'événements en temps réel à votre serveur via HTTPS.

Exemples de cas d'utilisation

  • Synchroniser les tickets avec votre CRM : Écoutez les événements conversation_created et conversation_updated pour créer et mettre à jour automatiquement des enregistrements dans Salesforce, HubSpot ou tout autre CRM, en gardant votre équipe de vente informée sans saisie manuelle de données.
  • Déclencher des actions de commande à partir des réponses des clients : Utilisez les événements message_created pour détecter quand un client confirme une annulation ou un changement d'adresse, puis appelez votre API d'exécution pour le traiter instantanément.
  • Alimenter votre pipeline d'analyse avec des données de support : Diffusez chaque événement vers un entrepôt de données comme BigQuery ou Snowflake pour créer des tableaux de bord personnalisés, suivre les temps de résolution ou effectuer une analyse des sentiments sur toutes les interactions client.

Chaque livraison est signée avec HMAC-SHA256 à l'aide d'un secret partagé, inclut un horodatage pour la protection contre la relecture, et porte un delivery_id stable pour la déduplication. Les livraisons échouées sont réessayées jusqu'à 20 fois avec un délai d'attente exponentiel, et un disjoncteur protège les deux parties pendant les pannes prolongées. Vous pouvez tester n'importe quel type d'événement à la demande, inspecter les journaux de livraison et redélivrer les événements manqués via l'API.

1. Nom de l'en-tête de signature

X-Commslayer-Signature, format de valeur sha256=<signature>. Chaque livraison contient également X-Commslayer-Timestamp, X-Commslayer-Delivery-ID et X-Commslayer-Event. Lisez les noms d'en-tête sans tenir compte de la casse.

2. Algorithme HMAC/hachage

HMAC-SHA256. La clé est le secret de votre webhook - une chaîne hexadécimale de 64 caractères renvoyée une fois dans la réponse de création POST /api/integration/v1/webhooks, et à nouveau uniquement à partir de POST .../webhooks/:id/rotate_secret.

3. Octets exacts qui sont signés

"{timestamp}.{raw_request_body}" - la chaîne d'horodatage Unix-secondes, un point littéral, puis le corps de la requête exactement tel que reçu. Vérifiez toujours par rapport aux octets bruts ; ne re-sérialisez jamais le JSON analysé.

4. Encodage de la signature

Hexadécimal en minuscules, préfixé par sha256=.

5. En-tête d'horodatage et fenêtre de relecture

X-Commslayer-Timestamp, secondes de l'époque Unix. Nous n'appliquons pas de fenêtre côté serveur - rejetez tout ce qui dépasse 5 minutes de votre horloge. Chaque nouvelle tentative et redélivraison est re-signée avec un nouvel horodatage, de sorte que la fenêtre étroite n'entre jamais en conflit avec notre calendrier de nouvelles tentatives. Protection contre la relecture = signature valide + horodatage frais + déduplication sur delivery_id de la charge utile (voir 7) ; la copie de la charge utile est couverte par la signature, elle ne peut donc pas être falsifiée ou échangée.

6. Calendrier de nouvelles tentatives et délai d'attente

Délai d'attente de 10 secondes par tentative ; le succès est tout 2xx - renvoyez-le avant d'effectuer un traitement lourd. En cas d'échec : jusqu'à 20 tentatives avec un délai d'attente exponentiel (5s, 10s, 20s, doublant, plafonné à 1 heure), s'étendant sur environ 10,5 heures. Les échecs soutenus déclenchent un disjoncteur qui interrompt les livraisons pendant un maximum d'une heure ; tout ce qui est abandonné pendant une pause apparaît dans GET .../webhooks/:id/delivery_logs avec le statut skipped et peut être renvoyé via POST .../webhooks/:id/delivery_logs/:log_id/redeliver. Environ une journée d'échec continu désactive le webhook et envoie un e-mail à vos administrateurs de compte ; récupérez avec POST .../reset_circuit_breaker ou en réactivant le webhook, puis redélivrez ce que vous avez manqué.

7. ID de livraison unique

À deux endroits avec la même valeur : un champ delivery_id de niveau supérieur à l'intérieur de la charge utile (couvert par la signature - utilisez-le comme clé de déduplication) et l'en-tête X-Commslayer-Delivery-ID (copie de commodité). Il est stable sur toutes les nouvelles tentatives et les redélivraisons manuelles de la même livraison. Le type d'événement se trouve dans le champ event de la charge utile et l'en-tête X-Commslayer-Event. Les doublons et les arrivées désordonnées sont tous deux possibles - dédupliquez sur delivery_id et ne supposez pas l'ordre.

8. Exemple de charge utile et de code de vérification

POST /api/integration/v1/webhooks/:id/test envoie un échantillon réaliste de tout type d'événement via le chemin de livraison de production - en-têtes, signature et structure de charge utile identiques aux événements réels, livrés une fois sans nouvelles tentatives. Une charge utile message_created ressemble à :

{
  "event": "message_created",
  "id": 999001,
  "content": "Hello, I need help with my recent order #12345...",
  "content_type": "text",
  "message_type": "incoming",
  "private": false,
  "created_at": "2026-08-10T13:47:57Z",
  "source_id": null,
  "conversation": { "id": 1001, "status": "open", "...": "..." },
  "inbox": { "id": 1, "name": "Support Inbox" },
  "sender": { "...": "..." },
  "account": { "id": 1, "name": "..." },
  "attachments": [],
  "delivery_id": "7424357d-9166-4f47-98c7-9b39af82f0a1"
}

Vérification (Node) :

const crypto = require('crypto');

function verifyWebhook(rawBody, headers, secret) {
  const ts = headers['x-commslayer-timestamp'];
  const sig = headers['x-commslayer-signature']; // "sha256=<hex>"
  const expected = 'sha256=' +
    crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
  if (expected.length !== sig.length) return false;
  const authentic = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
  return authentic && fresh;
}

// After verification, dedupe on JSON.parse(rawBody).delivery_id

Deux notes d'intégration : analysez les charges utiles de manière permissive (nous pourrions ajouter des champs au fil du temps - ne rejetez pas les propriétés inconnues), et surveillez la santé de votre webhook via GET /api/integration/v1/webhooks/:id, qui expose l'état healthy, active et du disjoncteur.