Skip to main content

Webhooks

TapToChat peut envoyer une requête HTTPS à votre serveur à chaque événement : une nouvelle conversation, un message, une attribution. Chaque requête est signée, pour que vous sachiez qu’elle vient de nous.

Configurer un webhook

Les webhooks font partie de l’offre Pro. Les propriétaires et administrateurs les gèrent dans Paramètres.

  1. Ouvrez Paramètres → Webhooks et choisissez Ajouter un webhook.
  2. Donnez-lui un nom et l’URL https qui recevra les événements.
  3. Choisissez les événements à envoyer.
  4. Copiez le secret de signature. Il n’est affiché qu’une fois ; vous pourrez le renouveler plus tard.
Ouvrir Paramètres → Webhooks

Événements

Chaque webhook ne reçoit que les événements auxquels il est abonné.

ÉvénementEnvoyé quand
conversation.createdUn visiteur commence une conversation, sur n’importe quel canal.
conversation.assignedUne conversation est attribuée à un agent.
conversation.closedUne conversation est fermée.
message.createdUn message est enregistré : d’un visiteur, d’un agent ou une réponse automatique.
tag.addedUne étiquette est ajoutée à une conversation.
note.createdUn agent ajoute une note interne ou lance une commande comme /summary, dont le résultat est enregistré comme note (kind command_result).
integration.connectedUne intégration est connectée.
integration.disconnectedUne intégration est déconnectée.
integration.errorLa synchronisation d’une intégration échoue.
webhook.testVous choisissez Envoyer un événement de test dans Paramètres. Jamais envoyé autrement.

Contenu

Chaque requête est un POST avec un corps JSON, toujours dans la même enveloppe :

{
  "id": "6f1c2b0e-8a7d-4c1e-9b3a-2d5e7f9a1c4b",
  "event": "message.created",
  "created_at": "2026-10-01T09:30:00.000Z",
  "organization_id": "0c9a1f4e-3b2d-4e5f-8a6b-7c8d9e0f1a2b",
  "data": {
    "message": {
      "id": "a1b2c3d4-…",
      "conversation_id": "e5f6a7b8-…",
      "sender_type": "visitor",
      "sender_id": null,
      "content": "Hello, is anyone there?",
      "channel": "web",
      "created_at": "2026-10-01T09:30:00.000Z"
    },
    "conversation": { "id": "e5f6a7b8-…", "status": "open", "visitor_name": "Ada", "…": "…" }
  }
}
  • id: l’identifiant de l’événement. Un renvoi porte le même id : utilisez-le pour ignorer les doublons.
  • event: le nom de l’événement, comme dans le tableau ci-dessus.
  • data: ce qui s’est passé. Ses champs dépendent de l’événement ; un événement de message contient le message et sa conversation.

En-têtes

  • X-TapToChat-Signature: la signature : v1= suivi d’un HMAC-SHA256 en hexadécimal.
  • X-TapToChat-Timestamp: le moment de la signature, en secondes Unix.
  • X-TapToChat-Event: le nom de l’événement.
  • X-TapToChat-Delivery-Id: cette livraison. Chaque renvoi porte le même id.

Vérifier la signature

Calculez un HMAC-SHA256 du timestamp, d’un point et du corps brut de la requête, avec votre secret de signature comme clé, et comparez-le à l’en-tête de signature en temps constant. Refusez les requêtes dont le timestamp s’écarte de plus de 5 minutes de votre horloge, pour qu’une requête interceptée ne puisse pas être rejouée.

Utilisez le secret entier comme clé, préfixe whsec_ compris. Vérifiez le corps brut avant de l’analyser : un JSON resérialisé ne correspondra pas.

import crypto from 'node:crypto'

// The raw request body, exactly as received: verify before parsing JSON.
export function verifyTapToChat(rawBody, headers, secret) {
  const timestamp = headers['x-taptochat-timestamp']
  const signature = headers['x-taptochat-signature']
  if (!timestamp || !signature) return false

  // Refuse old requests, so a captured one cannot be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false

  const expected =
    'v1=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
  const a = Buffer.from(signature)
  const b = Buffer.from(expected)
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

Renvois

Répondez par un statut 2xx en moins de 10 secondes pour accuser réception. Sinon, la livraison est renvoyée, jusqu’à 6 tentatives au total.

Les délais entre les tentatives sont de 30s, 60s, 120s, 240s, 480s.

Une réponse 4xx autre que 408 ou 429 arrête aussitôt les renvois, tout comme une redirection : les redirections ne sont pas suivies, indiquez donc l’URL finale.

Une livraison peut parfois arriver plus d’une fois. Utilisez l’id du corps pour traiter chaque événement une seule fois.

Désactivation automatique

Après 20 livraisons échouées d’affilée, le webhook est désactivé et Paramètres en indique la raison. Corrigez le récepteur, puis réactivez-le ; le compteur repart de zéro.

Bon à savoir

  • L’URL doit utiliser https et pointer vers une adresse publique.
  • Les messages envoyés par les agents depuis l’application mobile TapToChat ne déclenchent pas encore message.created. Ceux envoyés depuis le tableau de bord web et depuis chaque canal, si.

Quelque chose ne fonctionne pas comme décrit ? Contactez-nous.