Envoyer leads et transferts vers vos outils par webhook
Envoyez les nouveaux leads, transferts, demandes de chat en direct, formulaires reçus, rendez-vous réservés et demandes de retour d'intoCHAT vers votre serveur, Zapier, Make ou n8n en JSON signé : événements, contenu, signature, tentatives.
Un webhook envoie un événement de votre agent vers l'adresse de votre choix, sous forme de requête JSON signée en POST, en quelques secondes. Utilisez-le pour faire entrer les nouveaux leads dans votre CRM ou pour lancer une automatisation. Il fonctionne avec votre propre serveur et avec les outils d'automatisation qui acceptent les webhooks entrants, comme Zapier, Make ou n8n : vous utilisez le déclencheur de l'outil pour les webhooks entrants. Les applications d'intoCHAT pour Zapier et Make sont prêtes et deviennent disponibles une fois publiées dans les annuaires de ces outils ; consultez Zapier et Make. Pour recevoir ces événements sous forme de messages dans un canal Slack, aucun webhook n'est nécessaire : utilisez les alertes Slack.
Événements
| Événement | Nom dans le tableau de bord | Envoyé quand |
|---|---|---|
lead.created | New lead | un nouveau contact est enregistré, depuis le formulaire de leads ou à partir de coordonnées saisies par le visiteur dans le chat. |
handoff.requested | Hand-off requested | l'agent a envoyé une conversation à votre équipe par e-mail. Consultez Transfert par e-mail. |
form.submitted | Form submitted | un visiteur a envoyé l'un de vos formulaires de chat. |
booking.created | Meeting booked | un visiteur a réservé un rendez-vous depuis le chat. Consultez Réservation avec Cal.com ou Calendly. |
live_chat.requested | Live chat requested | l'agent a demandé à votre équipe de rejoindre le chat, parce qu'un visiteur a demandé à parler à quelqu'un pendant qu'une personne de votre équipe était en ligne. Consultez Chat en direct. |
return.requested | Return requested | un visiteur a demandé à retourner ou à échanger des articles d'une commande vérifiée par l'agent. Consultez Statut des commandes et retours. |
lead.created est envoyé une fois par contact. Un visiteur qui revient et renvoie les mêmes coordonnées ne déclenche pas de nouvel événement, pas plus qu'un chat qui ajoute un numéro de téléphone à un contact déjà enregistré dans ce chat.
handoff.requested n'est envoyé que si l'e-mail à votre équipe est bien parti. Les transferts depuis le Playground l'envoient aussi, avec "test": true. Si vous avez connecté les tickets helpdesk, il est envoyé une fois le ticket créé ou en échec, généralement quelques secondes plus tard, et contient le ticket quand il y en a un.
form.submitted est envoyé une fois par envoi. Un formulaire ne peut être envoyé qu'une fois par conversation, et un envoi ne déclenche jamais lead.created, même si le formulaire demande une adresse e-mail.
booking.created est envoyé une fois par réservation, après que Cal.com ou Calendly l'a acceptée et qu'intoCHAT l'a enregistrée. Une réservation ne déclenche jamais lead.created. Les réservations depuis le Playground sont de vraies réservations et l'envoient aussi, sans marqueur de test. Les modifications faites ensuite dans Cal.com ou Calendly, comme une annulation, ne déclenchent aucun événement.
live_chat.requested est envoyé une fois par demande, quand l'agent demande à votre équipe de rejoindre le chat, que quelqu'un le rejoigne ou non. Un visiteur qui redemande une personne après l'expiration de la demande ou la fin du chat en direct en déclenche un nouveau. Le Playground ne demande jamais de chat en direct : il n'envoie donc jamais cet événement.
return.requested est envoyé une fois par demande de retour, quand intoCHAT l'a enregistrée. Chaque conversation peut envoyer une demande par commande : redemander pour la même commande n'envoie donc rien. Les demandes depuis le Playground l'envoient aussi, sans marqueur de test.
Ajouter un webhook
- Ouvrez votre agent et allez dans l'onglet Leads. Webhooks se trouve vers le bas de l'onglet, au-dessus de Slack alerts.
- Cliquez sur Add webhook.
- Dans Endpoint URL, collez l'adresse que votre serveur ou votre outil indique pour les webhooks entrants.
- Sous Events to send, laissez cochés les événements souhaités : New lead, Hand-off requested, Form submitted, Meeting booked, Live chat requested et Return requested. Les six sont cochés pour un nouveau webhook. Un webhook ajouté auparavant garde ses événements : cliquez sur Edit et cochez Form submitted, Meeting booked, Live chat requested ou Return requested s'il doit recevoir ces événements.
- Laissez Active activé et cliquez sur Add webhook.
- Copiez le secret de signature qui s'affiche, conservez-le là où votre récepteur peut le lire, puis cliquez sur I've saved it.
- Cliquez sur Send test event pour vérifier la connexion. Le résultat s'affiche sous les boutons.
L'adresse doit commencer par https:// et pointer vers un serveur public. Les adresses de réseaux privés ou internes, comme localhost ou 192.168.1.10, sont refusées à l'enregistrement et vérifiées à nouveau avant chaque envoi. Chaque agent peut avoir jusqu'à 5 webhooks.
Les webhooks que Zapier, Make ou votre propre code ont abonnés via l'API REST ne comptent pas dans ces 5 ; consultez Webhooks créés par des intégrations. Les webhooks propres à un formulaire non plus ; consultez Un webhook pour un formulaire.
Pour mettre un webhook en pause sans perdre ses réglages, désactivez-le : il affiche alors Paused. Les événements survenus pendant la pause ne sont pas envoyés, même plus tard. Un envoi qui attend une nouvelle tentative échoue à sa prochaine tentative ; une fois le webhook réactivé, vous pouvez le renvoyer. Edit modifie l'adresse et les événements. Remove supprime le webhook et son historique d'envois.
Webhooks créés par des intégrations
Une intégration peut abonner un webhook à votre agent via l'API REST, avec l'une de vos clés API. Les applications Zapier et Make le font quand vous activez un Zap ou ajoutez un déclencheur instantané à un scénario.
Ces webhooks figurent dans la carte Webhooks avec les autres, avec un badge qui indique leur provenance : via Zapier, via Make ou via API. Ils sont envoyés, signés, retentés et journalisés comme les webhooks que vous ajoutez vous-même, et vous pouvez y utiliser Send test event, Recent deliveries, l'interrupteur Active et New secret.
- Ils n'ont pas de bouton Edit : le Zap, le scénario ou le code qui les a créés détient l'adresse et les événements, et les modifier ici le casserait.
- Remove en supprime un. Le Zap ou le scénario reste activé mais ne reçoit plus d'événements ; désactivez-le aussi de son côté, ou désactivez-le puis réactivez-le pour abonner un nouveau webhook.
- L'intégration retire elle-même son webhook quand vous désactivez le Zap ou supprimez le déclencheur.
- Révoquer la clé API qui les a créés les supprime. Consultez Révoquer une clé.
- Un agent peut en avoir jusqu'à 25, en plus des 5 que vous ajoutez vous-même.
Un webhook pour un formulaire
Un formulaire de chat peut avoir un webhook à lui, qui ne reçoit que les événements form.submitted de ce formulaire. Vous l'ajoutez et le gérez dans l'éditeur du formulaire, dans l'onglet Actions, sous Webhook for this form, et non dans la carte Webhooks.
- Il a son propre secret de signature, affiché une seule fois, et il est envoyé, signé, retenté et journalisé exactement comme les webhooks de cette page, avec la même enveloppe et les mêmes données
form.submitted. - Il n'envoie que
form.submitted, et uniquement pour son formulaire. Ses événements ne peuvent pas être modifiés, et un événement de test fonctionne comme décrit plus bas. - Il ne compte pas dans les 5 webhooks de l'agent et ne figure pas dans la carte Webhooks.
- Les webhooks de l'agent abonnés à Form submitted continuent de recevoir les envois de tous les formulaires, y compris ceux d'un formulaire qui a son propre webhook. Chaque webhook reçoit son propre envoi, avec son propre identifiant.
- Supprimer le formulaire supprime son webhook et son historique d'envois.
Le secret de signature
Chaque webhook a son propre secret de signature, qui commence par whsec_. Il ne s'affiche en entier qu'une seule fois, juste après l'ajout du webhook ou la création d'un nouveau secret. Ensuite, la carte n'en montre que les quatre derniers caractères.
Si vous perdez le secret ou pensez que quelqu'un d'autre le connaît, cliquez sur New secret. L'ancien secret cesse de fonctionner immédiatement : transmettez tout de suite le nouveau à votre récepteur.
Ce qui est envoyé
Chaque envoi est une requête POST avec un corps JSON et ces en-têtes :
| En-tête | Valeur |
|---|---|
Content-Type | application/json |
User-Agent | intoCHAT-Webhooks/1.0 |
X-IntoChat-Event | Le nom de l'événement, par exemple lead.created |
X-IntoChat-Delivery | L'identifiant de l'envoi. Il reste le même à chaque nouvelle tentative. |
X-IntoChat-Timestamp | Le moment où cette tentative a été envoyée, en secondes Unix |
X-IntoChat-Signature | sha256= suivi de la signature ; voir plus bas |
Le corps a toujours la même enveloppe. id est l'identifiant de l'envoi, la même valeur que X-IntoChat-Delivery :
{
"id": "DELIVERY_ID",
"event": "lead.created",
"created_at": "2026-10-07T09:30:00.000Z",
"agent": { "id": "AGENT_ID", "name": "Acme Assistant" },
"data": { }
}
Données de lead.created
| Champ | Contenu |
|---|---|
leadId | L'identifiant du lead |
agentId, agentName | L'agent qui a collecté le lead |
email | L'adresse e-mail, ou null |
phone | Le numéro de téléphone, ou null |
name | Le nom saisi dans le formulaire, ou null. Un nom n'est jamais tiré d'un message du chat. |
customFields | Les réponses à vos champs personnalisés, sous forme de liste de { "id", "label", "value" }. Vide s'il n'y en a pas. |
source | form ou chat |
conversationId | La conversation d'où vient le lead, ou null |
collectedAt | Le moment de l'enregistrement du lead, en heure ISO 8601 UTC |
identity | Uniquement pour un visiteur vérifié avec la vérification d'identité : { "userId", "name", "email" }. Absent sinon. |
Données de handoff.requested
| Champ | Contenu |
|---|---|
conversationId | La conversation transférée |
visitorEmail | L'adresse donnée par le visiteur pour la réponse |
summary | Ce dont le visiteur a besoin, dans les mots de l'agent |
page | La page où le chat a commencé, ou null |
country | Le code pays à deux lettres du visiteur, ou null |
requestedAt | Le moment de l'envoi du transfert, en heure ISO 8601 UTC |
test | true pour un transfert depuis le Playground, sinon false |
ticket | Uniquement quand les tickets helpdesk ont ouvert un ticket pour ce transfert : { "provider", "id", "url" }, où provider vaut zendesk, freshdesk ou hubspot, id est le numéro du ticket sous forme de chaîne et url l'ouvre dans votre helpdesk. Absent sinon. |
Données de form.submitted
| Champ | Contenu |
|---|---|
submissionId | L'identifiant de l'envoi |
formId, formName | Le formulaire envoyé |
agentId, agentName | L'agent qui a affiché le formulaire |
answers | Les réponses du visiteur, sous forme de liste de { "id", "label", "value" }, dans l'ordre du formulaire. Les champs facultatifs laissés vides n'y figurent pas. |
conversationId | La conversation dans laquelle le formulaire a été envoyé |
submittedAt | Le moment où l'envoi a été enregistré, en heure ISO 8601 UTC |
identity | Uniquement pour un visiteur vérifié avec la vérification d'identité : { "userId", "name", "email" }. Absent sinon. |
Données de booking.created
| Champ | Contenu |
|---|---|
bookingId | L'identifiant de la réservation dans intoCHAT |
provider | Le calendrier : calcom ou calendly |
providerBookingId | L'identifiant de la réservation dans Cal.com, ou l'URI de l'invité dans Calendly, par exemple https://api.calendly.com/scheduled_events/…/invitees/… |
agentId, agentName | L'agent avec lequel le rendez-vous a été réservé |
eventTypeId, eventTypeUri, eventTitle | Le type d'événement réservé : eventTypeId est le numéro Cal.com et eventTypeUri l'URI Calendly. L'autre vaut null. |
startAt, endAt | Le début et la fin du rendez-vous, en heures ISO 8601 UTC |
timeZone | Le fuseau horaire du visiteur, par exemple Europe/Berlin, ou UTC si son navigateur n'en a pas fourni |
attendeeName, attendeeEmail | Le nom et l'adresse e-mail saisis par le visiteur |
providerStatus | accepted, ou pending si vous devez d'abord confirmer la réservation dans Cal.com. Les réservations Calendly sont toujours accepted. |
conversationId | La conversation dans laquelle le rendez-vous a été réservé |
createdAt | Le moment où la réservation a été enregistrée, en heure ISO 8601 UTC |
identity | Uniquement pour un visiteur vérifié avec la vérification d'identité : { "userId", "name", "email" }. Absent sinon. |
Données de live_chat.requested
| Champ | Contenu |
|---|---|
conversationId | La conversation dans laquelle le visiteur a demandé une personne |
visitorMessage | Le dernier message du visiteur, raccourci à 500 caractères avec … à la fin s'il est plus long |
page | La page où le chat a commencé, ou null |
country | Le code pays à deux lettres du visiteur, ou null |
requestedAt | Le moment où l'agent a demandé à votre équipe de rejoindre le chat, en heure ISO 8601 UTC |
L'événement n'indique pas si quelqu'un a rejoint le chat. Qui en a pris la main, et quand, apparaît dans la boîte de réception Live chat et dans la transcription.
Données de return.requested
| Champ | Contenu |
|---|---|
returnRequestId | L'identifiant de la demande dans intoCHAT |
provider | La boutique : shopify ou woocommerce |
orderName, orderId | La commande telle que votre boutique l'affiche, par exemple #1042, et son identifiant dans la boutique |
email | L'adresse e-mail de la commande. Le visiteur a prouvé qu'il la connaît, ou la vérification d'identité de votre site l'a transmise. |
kind | return ou exchange |
items | Les articles, chacun sous la forme { "title", "quantity" }. Le titre inclut la variante quand le produit a été commandé en plusieurs variantes, par exemple Wool scarf - Blue. |
reason | Le motif, dans les mots du visiteur |
status | requested |
agentId, agentName | L'agent avec lequel la demande a été faite |
conversationId | La conversation dans laquelle la demande a été faite |
createdAt | Le moment où la demande a été enregistrée, en heure ISO 8601 UTC |
Rien n'a été approuvé ni modifié dans votre boutique. Traitez le retour dans la boutique, puis marquez-le comme traité dans la liste Returns de l'onglet Leads.
Les noms de champ de tous les événements utilisent le camelCase.
Événement de test
Send test event envoie une requête avec "event": "test" et ces données : { "message": "This is a test event from intoCHAT. Your webhook is set up correctly." }. Elle part quels que soient les événements choisis, même si le webhook est en pause, et n'est tentée qu'une fois. Comme ses données diffèrent des vrais événements, un outil qui associe les champs à partir d'un exemple a besoin d'un vrai événement, par exemple un lead que vous envoyez vous-même depuis votre site.
Vérifier la signature
Vérifiez chaque requête avant de lui faire confiance. X-IntoChat-Signature vaut sha256= suivi du HMAC-SHA256 en hexadécimal de l'horodatage, d'un point et du corps brut, soit ${timestamp}.${rawBody}, avec le secret de signature du webhook comme clé. L'horodatage est la valeur de X-IntoChat-Timestamp.
- Calculez la signature sur le corps exactement tel qu'il arrive, avant d'analyser le JSON.
- Comparez en temps constant.
- Refusez les horodatages anciens, pour qu'une requête interceptée ne puisse pas être rejouée. L'exemple ci-dessous accepte 5 minutes.
Cet exemple Node.js est le même que sous Verify signatures dans la carte Webhooks, qui propose un bouton Copy :
const crypto = require("crypto")
// rawBody: the request body exactly as received, before JSON parsing.
function verifyIntoChatWebhook(rawBody, headers, secret) {
const timestamp = headers["x-intochat-timestamp"]
const signature = headers["x-intochat-signature"] || ""
// Reject anything older than 5 minutes, so a captured request can't be replayed.
const age = Math.abs(Date.now() / 1000 - Number(timestamp))
if (!timestamp || !(age <= 300)) return false
const expected = "sha256=" + 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)
}
Si votre outil ne sait pas vérifier les signatures, traitez l'adresse du webhook comme un mot de passe : toute personne qui la connaît peut y envoyer des requêtes.
Répondre et gérer les doublons
- Répondez avec n'importe quel statut
2xxen moins de 10 secondes. Tout le reste compte comme un échec : un autre code de statut, une réponse trop tardive, une erreur de connexion ou de certificat. - Les redirections ne sont pas suivies. Une réponse
3xxcompte comme un échec : indiquez l'adresse finale. - Un même événement peut arriver plusieurs fois, par exemple si votre serveur l'a enregistré mais a répondu trop tard. Utilisez
X-IntoChat-Delivery, ou l'iddu corps, pour ignorer un envoi déjà traité. - Pour un même événement, chaque webhook reçoit son propre envoi, avec son propre identifiant.
Nouvelles tentatives
- La première tentative part juste après l'événement. Si elle échoue, jusqu'à deux nouvelles tentatives rapides suivent en quelques secondes.
- Si elles échouent aussi, l'envoi affiche Retrying et une tâche planifiée réessaie plus tard. Les tentatives s'arrêtent après 6 au total ou 24 heures après l'événement, selon ce qui arrive en premier. L'envoi est alors marqué Failed.
- La tâche planifiée tourne actuellement une fois par jour. En pratique, un envoi qui échoue encore après les tentatives rapides bénéficie d'une ou deux tentatives de plus, dans la journée environ qui suit l'événement.
- Un envoi vers une adresse qui s'avère pointer vers un réseau privé échoue immédiatement, sans nouvelle tentative.
- Chaque nouvelle tentative garde l'identifiant de l'envoi et est signée à nouveau avec un nouvel horodatage.
Envois récents
Cliquez sur Recent deliveries sous un webhook pour voir ses 20 derniers envois. Chacun indique son statut (Sending, Retrying, Delivered ou Failed), l'événement, l'heure, le nombre de tentatives et le statut HTTP. Un envoi en cours de nouvelles tentatives indique quand la prochaine est prévue, et un envoi qui n'a pas abouti affiche l'erreur, par exemple No response within 10 seconds.
Un envoi en échec a un bouton Resend qui le retente une fois, immédiatement. Les envois sont supprimés au bout de 30 jours.
Étapes suivantes
- Choisissez ce que demande le formulaire : Collecte de leads.
- Permettez aux visiteurs de joindre votre équipe par e-mail : Transfert par e-mail.
- Permettez à votre équipe de rejoindre le chat : Chat en direct.
- Recueillez des informations avec un formulaire sous la réponse de l'agent, et donnez à un formulaire son propre webhook : Formulaires de chat.
- Permettez aux visiteurs de réserver des rendez-vous dans le chat : Réservation avec Cal.com ou Calendly.
- Répondez aux questions sur les commandes et recueillez les demandes de retour : Statut des commandes et retours.
- Publiez les nouveaux leads, les transferts et les demandes de chat en direct dans un canal Slack : Alertes Slack.
- Utilisez intoCHAT dans Zapier ou Make : Zapier et Make.
- Un envoi échoue sans cesse ? Consultez Dépannage.