Leads und Übergaben per Webhook an deine Tools senden
Sende neue Leads, Übergaben und Live-Chat-Anfragen, Formulareinsendungen, gebuchte Termine und Rücksendeanfragen aus intoCHAT als signiertes JSON an deinen Server, Zapier, Make oder n8n: Events, Inhalte, Signaturen und Wiederholungen.
Ein Webhook schickt ein Ereignis deines Agenten innerhalb von Sekunden an eine Adresse deiner Wahl, als signierte JSON-Anfrage per POST. So landen neue Leads in deinem CRM, oder eine Automatisierung startet. Das funktioniert mit deinem eigenen Server und mit Automatisierungstools, die eingehende Webhooks annehmen, etwa Zapier, Make oder n8n: Du nutzt den Auslöser des Tools für eingehende Webhooks. Die eigenen intoCHAT-Apps für Zapier und Make sind fertig und werden verfügbar, sobald sie in den Verzeichnissen dieser Tools veröffentlicht sind; siehe Zapier und Make. Willst du diese Ereignisse als Nachrichten in einem Slack-Channel, brauchst du keinen Webhook: Nutze die Slack-Benachrichtigungen.
Events
| Event | Name im Dashboard | Wird gesendet, wenn |
|---|---|---|
lead.created | New lead | ein neuer Kontakt gespeichert wird, aus dem Lead-Formular oder aus Kontaktdaten, die der Besucher in den Chat geschrieben hat. |
handoff.requested | Hand-off requested | der Agent ein Gespräch per E-Mail an dein Team geschickt hat. Siehe Übergabe per E-Mail. |
form.submitted | Form submitted | ein Besucher eines deiner Chat-Formulare abgeschickt hat. |
booking.created | Meeting booked | ein Besucher im Chat einen Termin gebucht hat. Siehe Terminbuchung mit Cal.com oder Calendly. |
live_chat.requested | Live chat requested | der Agent dein Team gebeten hat, in den Chat zu kommen, weil ein Besucher nach einer Person gefragt hat, während jemand aus deinem Team online war. Siehe Live-Chat. |
return.requested | Return requested | ein Besucher darum gebeten hat, Artikel einer Bestellung zurückzusenden oder umzutauschen, die der Agent verifiziert hat. Siehe Bestellstatus und Rücksendungen. |
lead.created kommt einmal pro Kontakt. Sendet ein wiederkehrender Besucher dieselben Daten noch einmal, gibt es kein neues Event, ebenso wenig, wenn ein Chat einem dort schon gespeicherten Kontakt eine Telefonnummer hinzufügt.
handoff.requested kommt nur, wenn die E-Mail an dein Team tatsächlich verschickt wurde. Übergaben aus dem Playground lösen es ebenfalls aus, gekennzeichnet mit "test": true. Hast du Helpdesk-Tickets verbunden, kommt es, sobald das Ticket erstellt wurde oder das Erstellen fehlgeschlagen ist, meist ein paar Sekunden später, und enthält das Ticket, wenn es eines gibt.
form.submitted kommt einmal pro Einsendung. Ein Formular lässt sich pro Gespräch nur einmal abschicken, und eine Einsendung löst nie lead.created aus, auch wenn das Formular nach einer E-Mail-Adresse fragt.
booking.created kommt einmal pro Buchung, nachdem Cal.com oder Calendly sie angenommen und intoCHAT sie gespeichert hat. Eine Buchung löst nie lead.created aus. Buchungen aus dem Playground sind echte Buchungen und lösen es ebenfalls aus, ohne Test-Kennzeichen. Spätere Änderungen in Cal.com oder Calendly, etwa eine Absage, lösen kein Event aus.
live_chat.requested kommt einmal pro Anfrage, wenn der Agent dein Team bittet dazuzukommen, egal ob jemand dazukommt oder nicht. Fragt ein Besucher erneut, nachdem die Anfrage verfallen oder der Live-Chat beendet ist, kommt ein neues Event. Der Playground fordert nie einen Live-Chat an und löst dieses Event daher nie aus.
return.requested kommt einmal pro Rücksendeanfrage, sobald intoCHAT sie gespeichert hat. Jedes Gespräch kann eine Anfrage pro Bestellung senden, eine erneute Anfrage für dieselbe Bestellung löst also nichts aus. Anfragen aus dem Playground lösen es ebenfalls aus, ohne Test-Kennzeichen.
Webhook hinzufügen
- Öffne deinen Agenten und wechsle zum Tab Leads. Webhooks steht weiter unten im Tab, über Slack alerts.
- Klicke auf Add webhook.
- Füge unter Endpoint URL die Adresse ein, die dein Server oder dein Tool für eingehende Webhooks nennt.
- Lass unter Events to send die Events angehakt, die du willst: New lead, Hand-off requested, Form submitted, Meeting booked, Live chat requested und Return requested. Bei einem neuen Webhook sind alle sechs angehakt. Ein früher angelegter Webhook behält seine Events. Klicke dort auf Edit und hake Form submitted, Meeting booked, Live chat requested oder Return requested an, wenn er diese bekommen soll.
- Lass Active eingeschaltet und klicke auf Add webhook.
- Kopiere das angezeigte Signing Secret, leg es dort ab, wo dein Empfänger es lesen kann, und klicke auf I've saved it.
- Klicke auf Send test event, um die Verbindung zu prüfen. Das Ergebnis steht unter den Buttons.
Die Adresse muss mit https:// beginnen und auf einen öffentlichen Server zeigen. Private und interne Netzwerkadressen wie localhost oder 192.168.1.10 werden beim Speichern abgelehnt und vor jeder Zustellung erneut geprüft. Jeder Agent kann bis zu 5 Webhooks haben.
Webhooks, die Zapier, Make oder dein eigener Code über die REST-API abonniert haben, zählen nicht zu den 5; siehe Von Integrationen erstellte Webhooks. Ebenso wenig die Webhooks einzelner Formulare; siehe Ein Webhook für ein einzelnes Formular.
Um einen Webhook zu pausieren, ohne seine Einstellungen zu verlieren, schalte ihn aus. Er zeigt dann Paused. Events, die während der Pause passieren, werden nicht gesendet, auch nicht später. Eine Zustellung, die gerade auf eine Wiederholung wartet, schlägt beim nächsten Versuch fehl; ist der Webhook wieder aktiv, kannst du sie erneut senden. Mit Edit änderst du Adresse und Events. Remove löscht den Webhook samt Zustellverlauf.
Von Integrationen erstellte Webhooks
Eine Integration kann über die REST-API mit einem deiner API-Schlüssel einen Webhook für deinen Agenten abonnieren. Die Apps für Zapier und Make tun das, wenn du einen Zap einschaltest oder einem Szenario einen sofortigen Trigger hinzufügst.
Diese Webhooks stehen mit den anderen in der Karte Webhooks, mit einem Kennzeichen, das sagt, woher sie kommen: via Zapier, via Make oder via API. Sie werden zugestellt, signiert, wiederholt und protokolliert wie die Webhooks, die du selbst hinzufügst, und du kannst Send test event, Recent deliveries, den Schalter Active und New secret bei ihnen nutzen.
- Sie haben keinen Button Edit: Adresse und Events gehören dem Zap, dem Szenario oder dem Code, der sie angelegt hat, und eine Änderung hier würde ihn kaputt machen.
- Remove löscht einen davon. Der Zap oder das Szenario bleibt eingeschaltet, bekommt aber keine Events mehr; schalte ihn auch dort aus, oder schalte ihn aus und wieder ein, um einen neuen Webhook zu abonnieren.
- Die Integration entfernt ihren Webhook selbst, wenn du den Zap ausschaltest oder den Trigger löschst.
- Widerrufst du den API-Schlüssel, der sie erstellt hat, werden sie gelöscht. Siehe Schlüssel widerrufen.
- Ein Agent kann bis zu 25 davon haben, zusätzlich zu den 5, die du selbst hinzufügst.
Ein Webhook für ein einzelnes Formular
Ein Chat-Formular kann einen eigenen Webhook haben, der nur die Events form.submitted dieses Formulars bekommt. Du fügst ihn im Editor des Formulars im Tab Actions unter Webhook for this form hinzu und verwaltest ihn dort, nicht in der Karte Webhooks.
- Er hat ein eigenes Signing Secret, das nur einmal angezeigt wird, und wird genau wie die Webhooks hier zugestellt, signiert, wiederholt und protokolliert, mit demselben Rahmen und denselben Daten von
form.submitted. - Er sendet nur
form.submitted, nur für sein Formular. Seine Events lassen sich nicht ändern, und ein Test-Event funktioniert wie unten beschrieben. - Er zählt nicht zu den 5 Webhooks des Agenten und steht nicht in der Karte Webhooks.
- Die Webhooks des Agenten, die Form submitted empfangen, bekommen weiterhin die Einsendungen aller Formulare, auch die eines Formulars mit eigenem Webhook. Jeder Webhook bekommt eine eigene Zustellung mit eigener ID.
- Wird das Formular gelöscht, werden sein Webhook und dessen Zustellverlauf gelöscht.
Das Signing Secret
Jeder Webhook hat ein eigenes Signing Secret, das mit whsec_ beginnt. Vollständig siehst du es nur einmal, direkt nach dem Hinzufügen oder nach dem Erstellen eines neuen Secrets. Danach zeigt die Karte nur noch die letzten vier Zeichen.
Hast du das Secret verloren oder glaubst du, dass jemand anderes es kennt, klicke auf New secret. Das alte Secret funktioniert sofort nicht mehr, gib das neue also gleich an deinen Empfänger weiter.
Was gesendet wird
Jede Zustellung ist eine POST-Anfrage mit JSON-Inhalt und diesen Headern:
| Header | Wert |
|---|---|
Content-Type | application/json |
User-Agent | intoCHAT-Webhooks/1.0 |
X-IntoChat-Event | Der Name des Events, etwa lead.created |
X-IntoChat-Delivery | Die ID der Zustellung. Sie bleibt bei jeder Wiederholung gleich. |
X-IntoChat-Timestamp | Wann dieser Versuch gesendet wurde, in Unix-Sekunden |
X-IntoChat-Signature | sha256=, gefolgt von der Signatur, siehe unten |
Der Inhalt hat immer denselben Rahmen. id ist die ID der Zustellung, derselbe Wert wie 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": { }
}
Daten von lead.created
| Feld | Inhalt |
|---|---|
leadId | Die ID des Leads |
agentId, agentName | Der Agent, der den Lead erfasst hat |
email | Die E-Mail-Adresse oder null |
phone | Die Telefonnummer oder null |
name | Der Name aus dem Lead-Formular oder null. Aus einer Chat-Nachricht wird nie ein Name übernommen. |
customFields | Die Antworten auf deine eigenen Felder als Liste von { "id", "label", "value" }. Leer, wenn es keine gibt. |
source | form oder chat |
conversationId | Das Gespräch, aus dem der Lead stammt, oder null |
collectedAt | Wann der Lead gespeichert wurde, als ISO-8601-Zeit in UTC |
identity | Nur bei einem Besucher, der mit der Identitätsprüfung verifiziert wurde: { "userId", "name", "email" }. Fehlt sonst. |
Daten von handoff.requested
| Feld | Inhalt |
|---|---|
conversationId | Das übergebene Gespräch |
visitorEmail | Die Adresse, die der Besucher für die Antwort genannt hat |
summary | Was der Besucher braucht, in den Worten des Agenten |
page | Die Seite, auf der der Chat begann, oder null |
country | Der zweistellige Ländercode des Besuchers oder null |
requestedAt | Wann die Übergabe verschickt wurde, als ISO-8601-Zeit in UTC |
test | true bei einer Übergabe aus dem Playground, sonst false |
ticket | Nur wenn Helpdesk-Tickets für diese Übergabe ein Ticket geöffnet haben: { "provider", "id", "url" }, wobei provider zendesk, freshdesk oder hubspot ist, id die Nummer des Tickets als String und url das Ticket in deinem Helpdesk öffnet. Fehlt sonst. |
Daten von form.submitted
| Feld | Inhalt |
|---|---|
submissionId | Die ID der Einsendung |
formId, formName | Das abgeschickte Formular |
agentId, agentName | Der Agent, der das Formular gezeigt hat |
answers | Die Antworten des Besuchers als Liste von { "id", "label", "value" }, in der Reihenfolge des Formulars. Leer gelassene optionale Felder fehlen. |
conversationId | Das Gespräch, in dem das Formular abgeschickt wurde |
submittedAt | Wann die Einsendung gespeichert wurde, als ISO-8601-Zeit in UTC |
identity | Nur bei einem Besucher, der mit der Identitätsprüfung verifiziert wurde: { "userId", "name", "email" }. Fehlt sonst. |
Daten von booking.created
| Feld | Inhalt |
|---|---|
bookingId | Die ID der Buchung in intoCHAT |
provider | Der Kalender: calcom oder calendly |
providerBookingId | Die ID der Buchung in Cal.com oder die URI des Eingeladenen in Calendly, zum Beispiel https://api.calendly.com/scheduled_events/…/invitees/… |
agentId, agentName | Der Agent, bei dem der Termin gebucht wurde |
eventTypeId, eventTypeUri, eventTitle | Der gebuchte Ereignistyp: eventTypeId ist die Nummer aus Cal.com, eventTypeUri die URI aus Calendly. Das jeweils andere Feld ist null. |
startAt, endAt | Beginn und Ende des Termins, als ISO-8601-Zeiten in UTC |
timeZone | Die Zeitzone des Besuchers, etwa Europe/Berlin, oder UTC, wenn sein Browser keine angegeben hat |
attendeeName, attendeeEmail | Name und E-Mail-Adresse, die der Besucher eingegeben hat |
providerStatus | accepted oder pending, wenn du die Buchung erst in Cal.com bestätigen musst. Calendly-Buchungen sind immer accepted. |
conversationId | Das Gespräch, in dem der Termin gebucht wurde |
createdAt | Wann die Buchung gespeichert wurde, als ISO-8601-Zeit in UTC |
identity | Nur bei einem Besucher, der mit der Identitätsprüfung verifiziert wurde: { "userId", "name", "email" }. Fehlt sonst. |
Daten von live_chat.requested
| Feld | Inhalt |
|---|---|
conversationId | Das Gespräch, in dem der Besucher nach einer Person gefragt hat |
visitorMessage | Die letzte Nachricht des Besuchers, gekürzt auf 500 Zeichen mit … am Ende, wenn sie länger ist |
page | Die Seite, auf der der Chat begann, oder null |
country | Der zweistellige Ländercode des Besuchers oder null |
requestedAt | Wann der Agent dein Team gebeten hat dazuzukommen, als ISO-8601-Zeit in UTC |
Das Event sagt nicht, ob jemand dazugekommen ist. Wer den Chat wann übernommen hat, siehst du im Live-Chat-Posteingang und im Verlauf.
Daten von return.requested
| Feld | Inhalt |
|---|---|
returnRequestId | Die ID der Anfrage in intoCHAT |
provider | Der Shop: shopify oder woocommerce |
orderName, orderId | Die Bestellung, wie dein Shop sie anzeigt, zum Beispiel #1042, und ihre ID im Shop |
email | Die E-Mail-Adresse der Bestellung. Der Besucher hat bewiesen, dass er sie kennt, oder die Identitätsprüfung deiner Website hat sie übergeben. |
kind | return oder exchange |
items | Die Artikel, jeweils als { "title", "quantity" }. Der Titel enthält die Variante, wenn das Produkt in mehreren bestellt wurde, zum Beispiel Wool scarf - Blue. |
reason | Der Grund, in den Worten des Besuchers |
status | requested |
agentId, agentName | Der Agent, bei dem die Anfrage gestellt wurde |
conversationId | Das Gespräch, in dem die Anfrage gestellt wurde |
createdAt | Wann die Anfrage gespeichert wurde, als ISO-8601-Zeit in UTC |
In deinem Shop wurde nichts genehmigt oder geändert. Wickle die Rücksendung dort ab und markiere sie dann in der Liste Returns im Tab Leads als erledigt.
Die Feldnamen aller Events nutzen camelCase.
Test-Event
Send test event sendet eine Anfrage mit "event": "test" und diesen Daten: { "message": "This is a test event from intoCHAT. Your webhook is set up correctly." }. Sie geht raus, egal welche Events der Webhook abonniert hat, auch wenn er pausiert ist, und wird nur einmal versucht. Weil ihre Daten anders aussehen als echte Events, braucht ein Tool, das Felder anhand eines Beispiels zuordnet, dafür ein echtes Event, etwa einen Lead, den du selbst auf deiner Website absendest.
Signatur prüfen
Prüfe jede Anfrage, bevor du ihr vertraust. X-IntoChat-Signature ist sha256=, gefolgt vom hexadezimalen HMAC-SHA256 aus Zeitstempel, Punkt und unverändertem Inhalt, also ${timestamp}.${rawBody}, mit dem Signing Secret des Webhooks als Schlüssel. Der Zeitstempel ist der Wert von X-IntoChat-Timestamp.
- Berechne die Signatur über den Inhalt genau so, wie er ankommt, bevor du das JSON auswertest.
- Vergleiche in konstanter Zeit.
- Lehne alte Zeitstempel ab, damit eine abgefangene Anfrage nicht erneut abgespielt werden kann. Das Beispiel unten erlaubt 5 Minuten.
Dieses Node.js-Beispiel ist dasselbe wie unter Verify signatures in der Karte Webhooks, dort mit einem Copy-Button:
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)
}
Kann dein Tool keine Signaturen prüfen, behandle die Webhook-Adresse wie ein Passwort: Wer sie kennt, kann Anfragen an sie senden.
Antworten und Duplikate erkennen
- Antworte innerhalb von 10 Sekunden mit einem beliebigen
2xx-Status. Alles andere gilt als Fehlschlag: ein anderer Statuscode, keine Antwort in der Zeit oder ein Verbindungs- oder Zertifikatsfehler. - Weiterleitungen werden nicht verfolgt. Eine
3xx-Antwort gilt als Fehlschlag, trag also die endgültige Adresse ein. - Dasselbe Event kann mehr als einmal ankommen, etwa wenn dein Server es gespeichert, aber zu spät geantwortet hat. Nutze
X-IntoChat-Deliveryoder dieidim Inhalt, um eine schon verarbeitete Zustellung zu ignorieren. - Jeder Webhook bekommt für dasselbe Event eine eigene Zustellung mit eigener ID.
Wiederholungen
- Der erste Versuch startet direkt nach dem Event. Schlägt er fehl, folgen innerhalb weniger Sekunden bis zu zwei schnelle Wiederholungen.
- Schlagen auch diese fehl, zeigt die Zustellung Retrying, und ein geplanter Job versucht es später erneut. Die Wiederholungen enden nach insgesamt 6 Versuchen oder 24 Stunden nach dem Event, je nachdem, was zuerst eintritt. Danach ist die Zustellung als Failed markiert.
- Der geplante Job läuft derzeit einmal am Tag. In der Praxis bekommt eine Zustellung, die nach den schnellen Wiederholungen noch fehlschlägt, ein oder zwei weitere Versuche, innerhalb von etwa einem Tag nach dem Event.
- Eine Zustellung an eine Adresse, die sich als privates Netzwerk herausstellt, schlägt sofort fehl, ohne Wiederholung.
- Jede Wiederholung behält die ID der Zustellung und wird mit neuem Zeitstempel neu signiert.
Letzte Zustellungen
Klicke unter einem Webhook auf Recent deliveries, um seine letzten 20 Zustellungen zu sehen. Jede zeigt ihren Status (Sending, Retrying, Delivered oder Failed), das Event, die Uhrzeit, die Zahl der Versuche und den HTTP-Status. Eine Zustellung im Status Retrying zeigt, wann der nächste Versuch fällig ist, und eine nicht erfolgreiche zeigt den Fehler, etwa No response within 10 seconds.
Eine fehlgeschlagene Zustellung hat einen Button Resend, der sie sofort noch einmal versucht. Zustellungen werden nach 30 Tagen gelöscht.
Wie es weitergeht
- Lege fest, was das Lead-Formular abfragt: Lead-Erfassung.
- Lass Besucher dein Team per E-Mail erreichen: Übergabe per E-Mail.
- Lass dein Team in den Chat kommen: Live-Chat.
- Frag Angaben mit einem Formular unter der Antwort des Agenten ab und gib einem Formular einen eigenen Webhook: Chat-Formulare.
- Lass Besucher im Chat Termine buchen: Terminbuchung mit Cal.com oder Calendly.
- Beantworte Fragen zu Bestellungen und nimm Rücksendeanfragen an: Bestellstatus und Rücksendungen.
- Neue Leads, Übergaben und Live-Chat-Anfragen in einen Slack-Channel posten: Slack-Benachrichtigungen.
- intoCHAT in Zapier oder Make nutzen: Zapier und Make.
- Eine Zustellung schlägt immer wieder fehl? Siehe Fehlerbehebung.