
# Webhooks

Webhooks ermöglichen es <span data-t="appName">Your AI Connector</span>, Ihre anderen Geschäftstools automatisch zu benachrichtigen, sobald etwas Wichtiges passiert – etwa wenn ein neuer Kontakt erstellt, ein Termin gebucht oder eine Nachricht empfangen wird. Anstatt manuell nach Aktualisierungen zu suchen, erhalten Ihre verbundenen Systeme sofort eine Benachrichtigung, sobald ein Ereignis eintritt.


---

## Was sind Webhooks?

Stellen Sie sich einen Webhook wie eine automatische Textnachricht zwischen zwei Apps vor. Wenn in <span data-t="appName">Your AI Connector</span> etwas passiert (z. B. ein neuer Kontakt meldet sich an), sendet die Plattform sofort eine Benachrichtigung an ein System Ihrer Wahl. Sie geben eine Webadresse (die sogenannte „Webhook-URL“) an, an die diese Benachrichtigungen gesendet werden sollen – diese wird normalerweise von Ihrem CRM, Ihrer Automatisierungsplattform oder Ihrem Entwickler bereitgestellt.

> **Webhooks senden Daten nur AUS <span data-t="appName">Your AI Connector</span> heraus.** Ein Webhook ist eine Einbahnstraße *von* <span data-t="appName">Your AI Connector</span> *zu* Ihren anderen Tools. Es gibt **keine Webhook-URL, die Leads, Kontakte oder Nachrichten IN die Plattform sendet.** Um einen neuen Lead hineinzubringen – von einem Website-Formular, Ihrem CRM oder GoHighLevel – führt Ihr System stattdessen einen **API-Aufruf** durch. Siehe [API-Zugriff](api-access.md) (die Operation *Kontakt erstellen*) und [Funnels](funnels.md). Das Einzige, was Sie für die eingehende Richtung benötigen, ist Ihr **API-Schlüssel**, der sich in einem eigenen Bereich befindet – siehe [API-Zugriff](api-access.md#generating-your-api-key). Die hier beschriebene Seite **Webhooks** ist ausschließlich für die ausgehende Richtung bestimmt.

::: note
**Hinweis:** Das Einrichten von Webhooks erfordert etwas technische Konfiguration. Wenn Sie sich damit nicht wohl fühlen, geben Sie diese Seite an Ihren Entwickler weiter oder nutzen Sie eine Automatisierungsplattform wie Zapier, Make oder Pabbly, die Webhook-URLs ohne Programmieraufwand bereitstellen.
:::


Häufige Anwendungsfälle sind:

- Synchronisierung neuer Kontakte mit Ihrem CRM.
- Auslösen eines Workflows in Zapier, Make oder Pabbly, wenn ein Tag hinzugefügt wird.
- Benachrichtigung Ihres Teams in Slack, wenn ein Mensch alarmiert wird.
- Aktualisierung Ihres Kalendersystems, wenn ein Termin gebucht wird.
- Protokollierung von Gesprächszusammenfassungen in Ihrer Datenbank.

---

## Einrichten von Webhooks

1. Klicken Sie in der linken Seitenleiste auf **Einstellungen** (Zahnrad-Symbol).
2. Klicken Sie in der Einstellungs-Seitenleiste unter der Gruppe **Integrationen** auf **Webhooks**.


Auf einem Konto, für das noch keine Webhooks konfiguriert sind, sieht die Seite wie folgt aus:


3. Klicken Sie oben rechts auf **New webhook**. Ein Formular wird direkt auf der Seite geöffnet:


4. Füllen Sie Folgendes aus:
   - **Endpoint-URL** – die Webadresse, an die <span data-t="appName">Your AI Connector</span> Ereignisbenachrichtigungen sendet. Diese erhalten Sie von Ihrem externen System (CRM, Automatisierungsplattform oder eigener Server).
   - **Name** – eine Bezeichnung, die Sie später wiedererkennen (z. B. „Slack-Benachrichtigungen“ oder „CRM-Synchronisierung“). Nur für Ihre Referenz.

> **Ihre Webhook-URL muss eine öffentlich erreichbare `https://`-Adresse sein.** Einfache `http://`-Adressen, `localhost` oder Adressen in privaten Netzwerken sowie plattforminterne Adressen werden beim Speichern abgelehnt. Um von Ihrem eigenen Rechner aus zu testen, verwenden Sie einen öffentlichen Tunnel (webhook.site oder ngrok) anstelle von localhost.

5. Klicken Sie unter **Ereignisse** auf die Ereignisse, die dieser Webhook empfangen soll – alle 22 sind unter [Die 22 Webhook-Ereignisse](#the-22-webhook-events) aufgelistet.
6. *(Optional)* Aktivieren Sie **Fehlgeschlagene Zustellungen erneut versuchen**, wenn <span data-t="appName">Your AI Connector</span> bei einem vorübergehenden Fehler weitere Versuche unternehmen soll – siehe [Fehlgeschlagene Zustellungen erneut versuchen](#retrying-failed-deliveries).
7. Klicken Sie auf **Webhook erstellen**. Er erscheint in der Liste unter dem Formular, und Sie können jederzeit in seiner Zeile auf **Test** klicken, um eine Beispiel-Payload an Ihren Endpunkt zu senden.

> **Berechtigung erforderlich.** Das Hinzufügen, Bearbeiten oder Testen von Webhooks erfordert die Berechtigung „Bearbeiten“ für Integrationen (Teammitglieder mit reiner Leseansicht sehen anstelle des Formulars einen Hinweis auf den Nur-Lese-Modus).

> **Das Signieren eines Webhooks** erfordert, dass dieser bereits gespeichert wurde – öffnen Sie die Zeile eines bestehenden Webhooks, um ihn zu bearbeiten, und das Panel **Signatur-Geheimnis** erscheint am unteren Rand des Bearbeitungsformulars. Ein brandneuer, ungespeicherter Entwurf hat noch keine Signierungsoption – siehe [Signierte Payloads](#signed-payloads-verifying-a-webhook-really-came-from-us) unten.

---

## Ein Webhook für alle Ihre Kundenkonten (Agenturen)

Wenn Sie eine Agentur betreiben, müssen Sie nicht denselben Webhook für jedes Kundenkonto neu erstellen. Im Agenturkonto verfügt das Webhook-Formular über einen zusätzlichen Schalter: **Auch für alle Kundenkonten auslösen**. Aktivieren Sie diesen, damit der Webhook auch Ereignisse empfängt, die in allen Kundenkonten unter Ihrer Agentur auftreten – ein Endpoint, die gesamte Agentur.

So funktioniert es:

- **Der `user`-Block gibt an, zu welchem Kunden ein Ereignis gehört.** Jede Benachrichtigung enthält bereits einen `user`-Block, der das Konto identifiziert, in dem das Ereignis aufgetreten ist, sodass Ihre Automatisierung pro Kunde routen kann.
- **Die Einstellungen Ihres Webhooks gelten überall.** Die von Ihnen ausgewählten Ereignisse, das Signatur-Secret und die Einstellung für erneute Versuche werden auch für die Zustellungen an Kundenkonten verwendet.
- **Keine doppelten Zustellungen.** Wenn ein Kundenkonto einen eigenen Webhook hat, der auf dieselbe URL verweist, wird dieser für die Ereignisse dieses Kontos verwendet – dasselbe Ereignis kommt niemals zweimal an einem Endpoint an.
- **Kunden sehen ihn nicht.** Der Webhook erscheint nicht auf der Webhooks-Seite des Kundenkontos und Kunden können ihn nicht deaktivieren – er liegt in Ihrer Verantwortung.
- **Die Zuverlässigkeit wird pro Kundenkonto nachverfolgt.** Wenn Ihr Endpoint weiterhin fehlschlägt, wird er automatisch für das Konto deaktiviert, dessen Zustellungen fehlgeschlagen sind (siehe [Webhook-Zuverlässigkeit](#webhook-reliability)), nicht für die gesamte Agentur auf einmal.

Der Schalter erscheint nur bei Agenturkonten. Die Einstellung über die API wird ebenfalls unterstützt – siehe das Feld `apply_to_sub_accounts` in der [Webhooks-API](../api/webhooks.md#one-subscription-for-all-client-accounts-agencies).

---

## Verfügbare Auslöser-Ereignisse

Sie können jedes der 22 Webhook-Ereignisse unabhängig voneinander aktivieren oder deaktivieren. Wenn ein Ereignis ausgelöst wird, sendet <span data-t="appName">Your AI Connector</span> eine Benachrichtigung mit den relevanten Daten an Ihre Webhook-URL. Jedes Ereignis, seine Bedeutung und der `event`-Code, den es in die Payload einfügt, sind zusammen unter [Die 22 Webhook-Ereignisse](#the-22-webhook-events) weiter unten auf dieser Seite aufgeführt.

> **Gut zu wissen:** **Aufgabe erstellt**, **Aufgabe aktualisiert** und **Aufgabe abgeschlossen** sind vollständig auswählbar und werden korrekt gespeichert. **Tägliche Zusammenfassung erstellt** ist ebenfalls eine kürzlich hinzugefügte Funktion. Siehe [Webhook für abgeschlossene Aufgaben](#task-completed-webhook) weiter unten für das Format dieser Payload.

---

## Tag-basierte Webhook-Trigger

`subscribed_to_tags` begrenzt die Ereignisse eines Webhooks nicht auf ein Tag. Es schränkt lediglich ein, welche Tags eine Benachrichtigung zur Konversationszusammenfassung auslösen. Um eine Anfrage zu erhalten, wenn ein bestimmtes Tag angewendet wird, legen Sie eine Webhook-URL für dieses Tag auf der Registerkarte **Tags** des Agenten (oder der Kampagne) fest.

Das Webhook-Formular selbst enthält keine Tag-Auswahl, weder beim Erstellen eines neuen Webhooks noch beim Bearbeiten eines bestehenden. Daher kann `subscribed_to_tags` nur über die [Webhooks-API](../api/webhooks.md) oder durch eine Anfrage an den Support gelesen oder geändert werden.

> **Gut zu wissen:** Das Bearbeiten eines bestehenden Webhooks, der eine `subscribed_to_tags`-Liste enthält (Umbenennen, Ändern der Ereignisse, Umschalten der Wiederholungsversuche), löscht diese Liste nicht mehr – da das Formular keine Tag-Auswahl zum Zurücksenden enthält, bleibt die bestehende Liste beim Speichern von dieser Seite aus unverändert. (Dies war vor dem **21. Juli 2026** ein echter Fehler: Das Speichern über das Webhook-Formular löschte die Liste, da es immer eine leere Tag-Liste sendete. Wenn ein Webhook vor diesem Datum seine `subscribed_to_tags`-Liste verloren hat, muss er über die API neu konfiguriert werden.)

### Zusammenfassung für getaggte Kontakte generieren

Wenn ein Webhook eine `subscribed_to_tags`-Liste hat, können Sie **Zusammenfassung generieren** aktivieren. Wenn dies aktiviert ist, generiert <span data-t="appName">Your AI Connector</span> automatisch eine Konversationszusammenfassung für den Kontakt, sobald eines dieser Tags angewendet wird, und fügt sie in die Webhook-Daten ein – voller Kontext ohne eine separate Anfrage.

---

## Testen Ihres Webhooks

1. Öffnen Sie **Einstellungen → Integrationen → Webhooks**.
2. Klicken Sie in der Zeile Ihres Webhooks auf **Testen**.
3. Überprüfen Sie Ihr externes System, um sicherzustellen, dass die Testdaten empfangen wurden.
4. Überprüfen Sie das Datenformat, um sicherzustellen, dass Ihr System es korrekt verarbeiten kann.

Für einen vollständigen End-to-End-Test senden Sie eine Nachricht, die eines Ihrer konfigurierten Ereignisse auslösen würde (eine Broadcast-Nachricht oder eine eingehende Nachricht auf einem verbundenen Kanal), und überprüfen Sie, ob der Webhook mit den echten Daten ausgelöst wird.

::: tip
**Tipp:** Verwenden Sie während der Entwicklung ein Tool wie [webhook.site](https://webhook.site) oder [RequestBin](https://requestbin.com), um die rohen Webhook-Daten zu überprüfen, bevor Sie Ihr Produktionssystem verbinden.
:::


### Was als erfolgreiche Zustellung gilt

Egal, ob Sie auf **Test** klicken oder das Ereignis tatsächlich ausgelöst wird, wir senden dasselbe:

- Eine **POST**-Anfrage (niemals GET), wobei der Body als JSON und `Content-Type: application/json` vorliegt.
- Die Header, die unter [Signierte Payloads](#signed-payloads-verifying-a-webhook-really-came-from-us) aufgelistet sind. Signatur-Header werden erst hinzugefügt, nachdem Sie ein Signierungsgeheimnis festgelegt haben.

Wir betrachten die Zustellung als erfolgreich, wenn:

- Ihr Endpunkt mit **einem beliebigen 2xx-Status** antwortet (200, 201, 204 – alles in Ordnung).
- Er **innerhalb von 30 Sekunden** antwortet.

Ein paar Dinge, die oft überraschen:

- **Der Antwort-Body wird ignoriert.** Sie müssen kein spezielles JSON zurückgeben. Ein leeres 200 reicht aus.
- **Weiterleitungen gelten als Fehler.** Wir folgen ihnen nicht, daher wird ein 301 oder 302 (einschließlich einer Weiterleitung mit nachgestelltem Schrägstrich oder von http zu https) als fehlgeschlagene Zustellung aufgezeichnet. Speichern Sie die endgültige URL, nicht eine, die weiterleitet.
- **Query-Strings werden vollständig unterstützt.** `https://your-app.com/hook?token=abc123` wird exakt so gesendet, wie Sie es gespeichert haben; ein Token im Query-String funktioniert also genauso gut wie im Pfad.
- **Ihre URL muss `https://` und öffentlich erreichbar sein.** Adressen, die zur eigenen Infrastruktur von <span data-t="appName">Your AI Connector</span> gehören, werden abgelehnt, aber Ihre eigenen Endpunkte auf Google Cloud Functions, Cloud Run, App Engine, Firebase Hosting oder anderswo sind in Ordnung.
- **Eine Firewall oder ein Bot-Schutz vor Ihrem Endpunkt kann uns blockieren.** Der häufigste Fall ist Cloudflare: Wenn für Ihre Zone der „Bot Fight Mode“ oder eine verwaltete Challenge aktiviert ist, erhält unsere Anfrage eine „Just a moment...“-Challenge-Seite mit einem 403-Status, anstatt Ihren Server zu erreichen – und eine Server-zu-Server-Anfrage kann niemals eine Browser-Challenge bestehen. Daher schlagen sowohl der **Test**-Button als auch echte Ereignisse auf die gleiche Weise fehl. Der Test-Button zeigt Ihnen an, wenn dies geschieht („Cloudflare is showing a bot challenge to our request“). Beheben Sie dies in Cloudflare mit einer Security-/WAF-Regel, die Challenges für Ihren Webhook-Pfad (oder für den `Webhook-Delivery/1.0` User-Agent) überspringt, und klicken Sie dann erneut auf **Test**.
- **Falls Ihre Firewall stattdessen eine IP-Allowlist benötigt** (zum Beispiel beim kostenlosen Cloudflare-Tarif, bei dem der einfache Bot Fight Mode nicht durch eine WAF-Regel übersprungen werden kann, aber eine auf „Zulassen“ gesetzte IP-Zugriffsregel davor greift), können wir helfen: Jede Zustellung, ob über den **Test**-Button oder ein Live-Ereignis, wird von einer festen IPv4-Adresse gesendet (keine Bereiche, kein IPv6, kein Wechsel). Kontaktieren Sie den Support und wir geben Ihnen die Adresse zur Aufnahme in die Allowlist. Behalten Sie die [Signaturprüfung](#signed-payloads-verifying-a-webhook-really-came-from-us) als Ihre eigentliche Vertrauensprüfung bei, da diese jedes Payload validiert, unabhängig davon, woher es stammt.
- **Das Testergebnis zeigt Ihnen genau, was Ihr Endpunkt geantwortet hat.** Ein fehlgeschlagener Test zeigt nun den tatsächlichen Grund an (den HTTP-Status, den Ihr Endpunkt zurückgegeben hat, ein Timeout oder dass wir die Adresse überhaupt nicht erreichen konnten), anstatt eines generischen Fehlers. Ein Test für einen gespeicherten Webhook wird bei aktivierter Signatur signiert gesendet, genau wie ein Live-Ereignis.

### Verwendung von n8n, Make oder Zapier („Test-URL“ vs. „Produktions-URL“)

Automatisierungsplattformen stellen Ihnen normalerweise zwei verschiedene Webhook-Adressen zur Verfügung, was oft zu Verwirrung führt:

- Eine **Test-URL** (in n8n enthält sie `/webhook-test/`). Diese empfängt nur Daten, während Sie die Arbeitsfläche aktiv beobachten und gerade auf **Listen for test event** (oder **Test workflow**) geklickt haben. Sie erfasst ein einzelnes Ereignis und beendet dann das Zuhören – daher fängt ein mehrmaliges Klicken auf **Testen** in <span data-t="appName">Your AI Connector</span> nur das erste Ereignis ab, und auch nur dann, wenn das Empfangsfenster in diesem Moment aktiv ist. Zum Testen: Klicken Sie zuerst in n8n auf **Listen for test event**, kehren Sie dann zu <span data-t="appName">Your AI Connector</span> zurück und klicken Sie einmal auf **Testen**.
- Eine **Produktions-URL** (in n8n enthält sie `/webhook/`, kein `-test`). Diese URL fügen Sie für Live-Ereignisse in <span data-t="appName">Your AI Connector</span> ein. Sie funktioniert erst, wenn Ihr Workflow auf **Aktiv** geschaltet ist. Wenn der Workflow nicht aktiv ist, weist n8n die Anfrage mit einem Fehler "404 / webhook not registered" zurück, obwohl <span data-t="appName">Your AI Connector</span> die Daten korrekt gesendet hat.

Kurz gesagt: Testen Sie mit der Test-URL während des Empfangsmodus, aber damit der Webhook bei echten Kontakten weiterhin funktioniert, speichern Sie die **Produktions-URL** in <span data-t="appName">Your AI Connector</span> und stellen Sie sicher, dass der Workflow **Active** ist.

---

## Webhook-Datenformat

Wenn ein Webhook ausgelöst wird, sendet <span data-t="appName">Your AI Connector</span> strukturierte Daten (JSON) an Ihre Webhook-URL. Wenn Sie eine Automatisierungsplattform wie Zapier oder Make verwenden, werden diese Daten automatisch für Sie geparst. Wenn Sie eine eigene Integration erstellen:

```json
{
  "event": "contactCreated",
  "contact": { "id": "<contact-id>", "first_name": "Jane", "...": "..." },
  "campaign": { "id": "<campaign-id>", "name": "AI Receptionist", "status": "Live" },
  "agent": { "id": "<agent-id>", "name": "Front Desk" },
  "user": { "id": "<account-id>", "email": "owner@example.com" }
}
```

| Feld | Beschreibung |
|---|---|
| `event` | Der exakte Ereignis-String, der die Benachrichtigung ausgelöst hat (zum Beispiel `contactCreated`, `booked`). Dies ist **nicht** das Anzeige-Label, das in der Ereignisliste erscheint; jedes Label und der dazugehörige Code finden sich unter [Die 22 Webhook-Ereignisse](#the-22-webhook-events). |
| `contact` | Der Kontakt, auf den sich das Ereignis bezieht, oder `null` bei Ereignissen, die nicht an einen Kontakt gebunden sind (wie `creditsRecharged`). |
| `campaign` | Die Kampagne, zu der der Kontakt gehört, oder `null`, falls keine vorhanden ist. |
| `agent` | Der Agent, der die Konversation bearbeitet, oder `null`, falls keiner zugewiesen ist. |
| `user` | Grundlegende Identitätsinformationen für das Konto, dem die Daten gehören. |

> **`campaign` oder `agent` — normalerweise eines von beiden, nicht beides.** Wenn Ihr Konto Agenten verwendet, sind Ihre Kontakte einem Agenten statt einer Kampagne zugeordnet, daher kommt `campaign` als `null` an und `agent` gibt an, wer es bearbeitet hat. Ältere kampagnenbasierte Konten sehen dies umgekehrt. Lesen Sie den jeweils ausgefüllten Wert; gehen Sie nicht davon aus, dass `campaign` immer vorhanden ist.

> **Der `agent`-Block wurde am 15. August 2026 eingeführt.** Er steht neben `campaign` bei den Ereignissen, die mit einer Unterhaltung verknüpft sind – ein abgeschlossener Chat, „Nicht stören“, eine Fortsetzung, eine Archivierung aufgehoben, eine KI-Pause, eine neue Nachricht, eine Unterhaltungszusammenfassung und der Webhook, den Sie für ein Tag festlegen können – und enthält den `id` und `name` des bearbeitenden Agenten oder `null`, wenn kein Agent beteiligt ist. Er ist rein additiv: Jedes Feld, das Sie bereits erhalten, bleibt unverändert, sodass ein Empfänger, den Sie vor diesem Datum erstellt haben, ohne Aktualisierungen weiterhin funktioniert.

Einige Ereignisse fügen ihren eigenen zusätzlichen Block auf oberster Ebene hinzu. Zum Beispiel fügt **Appointment Booked** einen `appointment`-Block hinzu (siehe [Appointment Booked Webhook](#appointment-booked-webhook)), **New Message** fügt einen vollständigen `message`-Block mit dem Text hinzu (siehe [New Message Webhook](#new-message-webhook)), und **Deliveries** sowie **Reads** fügen einen kurzen `message`-Block mit nur der ID und dem Status der Nachricht hinzu (siehe [Deliveries and Reads Webhook](#deliveries-and-reads-webhook)).

> **Deliveries und Reads teilen Ihnen mit, welche Nachricht es war, aber nicht, was darin stand.** Sie enthalten einen `message`-Block mit der `id` und dem `status` der Nachricht – und diese `id` ist dieselbe `messageId`, die der [Send Message Endpoint](../api/messages.md#send-a-message) zurückgibt, sodass Sie eine Zustellungs- oder Lesebestätigung genau der Nachricht zuordnen können, die Sie gesendet haben – jedoch ohne den Nachrichtentext. **Replies** enthält überhaupt keinen `message`-Block. Wenn Sie die gesendeten oder empfangenen Wörter benötigen, abonnieren Sie zusätzlich **New Message**.

> **Zwei Dinge, die Sie wissen sollten, bevor Sie Ihren Empfänger schreiben.** Es gibt kein `timestamp`-Feld und keinen `data`-Wrapper. Jeder Block befindet sich auf der obersten Ebene des JSON-Objekts, wie oben dargestellt.

### Die 22 Webhook-Ereignisse

Die 22 Webhook-Ereignisse mit dem Anzeige-Label, das Sie in der App auswählen, und dem `event`-Code, der in der Payload gesendet wird. Der `event`-Code ist eine kurze Zeichenfolge, die **nicht** mit dem Anzeige-Label übereinstimmt. Richten Sie Ihren Empfänger daher auf den Code aus, nicht auf das Label:

| Anzeigename (in der App) | `event`-Code im Payload | Bedeutung |
|---|---|---|
| Contact Created | `contactCreated` | Ein neuer Kontakt wird Ihrem Konto hinzugefügt (manuell, per Import oder über API). |
| Contact Paused | `contact_paused` | Eine Kontaktunterhaltung wird pausiert (der Bot antwortet nicht mehr). |
| Contact Resumed | `contact_resumed` | Eine pausierte Kontaktunterhaltung wird fortgesetzt. |
| Contact Do Not Disturb | `contact_do_not_disturb_changed` | Die „Nicht stören“-Einstellung eines Kontakts wird aktiviert. |
| Contact Unarchived | `contact_unarchived` | Ein archivierter Kontakt sendet eine neue Nachricht und kehrt damit in Ihren aktiven Posteingang zurück. |
| New Message | `new_message` | Jede Nachricht, die einer Unterhaltung auf einem beliebigen Kanal hinzugefügt wird – sowohl Nachrichten, die Ihr Kontakt Ihnen sendet, als auch Nachrichten, die Ihre KI oder Ihr Team an ihn sendet. Dies ist das einzige Ereignis, das den tatsächlichen Nachrichtentext enthält (siehe [New Message Webhook](#new-message-webhook)). |
| Replies | `replied` | Ein Kontakt antwortet auf eine Nachricht. |
| Reads | `read` | Ein Kontakt liest eine Nachricht (auf Kanälen, die Lesebestätigungen unterstützen). Enthält die ID der gelesenen Nachricht – siehe [Deliveries and Reads Webhook](#deliveries-and-reads-webhook). |
| Deliveries | `delivered` oder `undelivered` | Eine Nachricht wurde erfolgreich an einen Kontakt zugestellt (`undelivered` bei Zustellungsfehlern). Enthält die ID der Nachricht – siehe [Deliveries and Reads Webhook](#deliveries-and-reads-webhook). |
| Human Alerted | `humanAlerted` | Der KI-Bot stellt fest, dass er eine Unterhaltung nicht bearbeiten kann, und markiert sie für menschliche Aufmerksamkeit. |
| Chat Concluded | `chat_concluded` | Der KI-Bot entscheidet, dass eine Unterhaltung beendet ist (Buchung erfolgt, Lead disqualifiziert usw.). |
| Appointment Booked | `booked` | Ein Kontakt bucht einen Termin über das Buchungssystem. |
| Credits Spent | `creditsSpent` | Credits werden von Ihrem Konto abgebucht. |
| Credits Recharged | `creditsRecharged` | Credits werden Ihrem Konto durch automatische Aufladung oder manuellen Kauf hinzugefügt. |
| Low Credit Balance | `lowCreditBalance` bei einer **Test**-Zustellung, `Low Credit Balance` bei einer echten | Eine Frühwarnung, dass Ihr Guthaben unter Ihren Warnschwellenwert gefallen ist (100 Credits, sofern Sie keinen eigenen festgelegt haben). Gedacht für Agenturen, deren Unterkonten alle aus einem gemeinsamen Pool schöpfen. Es enthält `balance`, `threshold` und `account_email` anstelle eines Kontaktblocks, wird maximal alle 24 Stunden gesendet, solange das Guthaben niedrig bleibt, und wird reaktiviert, sobald das Guthaben wieder über dem Schwellenwert liegt. |
| Task Created | `taskCreated` | Eine Aufgabe wird erstellt. |
| Task Updated | `taskUpdated` | Eine Aufgabe ändert sich, ohne in eine Abschlussphase zu gelangen. |
| Task Completed | `taskCompleted` | Eine Aufgabe wechselt in eine als Abschlussphase konfigurierte Phase. |
| Daily Summary Created | `dailySummaryCreated` | Ihr täglicher Zusammenfassungsbericht wird erstellt. |
| Channel Connected | `channelConnected` | **Noch nicht gesendet – auswählbar, aber derzeit wird nichts ausgegeben. Bauen Sie nicht darauf auf.** Gedacht für den Zeitpunkt, an dem ein Messaging-Kanal die Verbindung herstellt. |
| Broadcast Started | `broadcastStarted` | Ein Broadcast beginnt mit dem Senden (Status ändert sich auf „Sending“). Wird einmal pro Start ausgelöst, auch wenn ein pausierter Broadcast fortgesetzt wird. Enthält einen `broadcast`-Block anstelle eines Kontaktblocks: id, name, channel, status, previous status, die Ziel-Liste (`list_id`, `list_name`, `is_smart_list`), `scheduled_at`, `total_contacts`. |
| Broadcast Completed | `broadcastCompleted` | Ein Broadcast ist abgeschlossen (Status ändert sich auf „Sent“ oder „Failed“). Gleicher `broadcast`-Block plus `completed_at` und, falls verfügbar, `completion_summary` (`total_sent`, `permanently_failed`, `unique_replied`, `failure_rate`, `had_errors`). Verwenden Sie diese beiden, um eine Smart Broadcast List mit externen Tools zu verbinden. |

Zwei weitere Codes erscheinen nie in dieser Liste, da Sie sie nicht abonnieren: `contact_tags_updated`, gesendet von einer Webhook-URL, die für ein einzelnes Tag festgelegt wurde, und `summary_generated`, gesendet, wenn eine Chat-Zusammenfassung für ein Tag in der `subscribed_to_tags`-Liste eines Webhooks geschrieben wird.

> **Kanal verbunden wird noch nicht gesendet.** Es erscheint in der Ereignisliste, wird aber derzeit von nichts ausgelöst. Programmieren Sie nicht dagegen.

Tag-basierte und Aufgaben-Benachrichtigungen verwenden ihre eigenen separaten Formen. Siehe [Contact Tags Updated](#contact-tags-updated-webhook) und [Task Completed](#task-completed-webhook).

---

## Webhook „Kontakt erstellt“

Wird gesendet, wenn das Ereignis **Kontakt erstellt** ausgelöst wird (ein neuer Kontakt wird manuell, per Import oder über die API hinzugefügt).

### Ereignisname

`contactCreated`

### Payload-Format

```json
{
  "event": "contactCreated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Feld | Beschreibung |
|---|---|
| `event` | Immer `contactCreated` für dieses Ereignis. |
| `contact.id` | Die eindeutige ID des neuen Kontakts. |
| `contact.email` / `contact.phone_number` | E-Mail und Telefonnummer des Kontakts, falls bekannt (je nach Kanal kann eines davon leer sein). |
| `contact.first_name` / `contact.last_name` | Der Name des Kontakts, falls bekannt. |
| `contact.human_alerted` / `contact.human_alert_reason` | Ob der Kontakt für menschliche Aufmerksamkeit markiert ist und warum. |
| `contact.is_bot_active` | Ob der KI-Bot derzeit für diesen Kontakt aktiv ist. |
| `contact.ad_referral` | Meta Click-to-WhatsApp-Anzeigenzuordnung oder `null` — siehe [Click-to-WhatsApp Ad Attribution](click-to-whatsapp-attribution.md). |
| `campaign` | Die Kampagne, unter der der Kontakt erstellt wurde, oder `null`. |
| `agent` | Der dem Kontakt zugewiesene Agent oder `null`. |
| `user` | Grundlegende Identitätsinformationen für das Konto, dem der Kontakt gehört. |

> **Das "Test"-Beispiel und ein echtes Ereignis sehen leicht unterschiedlich aus.** Die Test-Schaltfläche sendet Platzhalterdaten (John Doe, eine Beispielkampagne). Ein echtes Ereignis "Kontakt erstellt" enthält die tatsächlichen Kontaktdaten, und einige Felder können je nach Kanal leer sein.

---

## New Message Webhook

Dieser Webhook wird jedes Mal ausgelöst, wenn eine Nachricht zu einer Unterhaltung auf einem beliebigen Kanal hinzugefügt wird. Er deckt beide Richtungen ab: Nachrichten, die Ihr Kontakt Ihnen sendet, und Nachrichten, die Ihre KI, Ihr Team oder eine Kampagne an ihn sendet. Dies ist der einzige Webhook, der den Nachrichtentext enthält. Verwenden Sie ihn daher, wenn Sie Unterhaltungen in ein externes System spiegeln möchten.

### Ereignisname

`new_message`

### Payload-Format

```json
{
  "event": "new_message",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "body": "Hi, are you open on Saturday?",
    "direction": "inbound",
    "status": "received",
    "created_at": "2026-07-30T17:27:06.000Z",
    "channel": "whatsapp_web"
  }
}
```

| Feld | Beschreibung |
|---|---|
| `event` | Immer `new_message` für dieses Ereignis. Beachten Sie, dass dies die exakte gesendete Zeichenfolge ist – es ist nicht das Anzeige-Label „New Message“. |
| `contact` | Der Kontakt, zu dessen Unterhaltung die Nachricht gehört. Gleiche Struktur wie bei [Contact Created](#contact-created-webhook). |
| `agent` | Der Agent, der die Unterhaltung bearbeitet (`id` und `name`), oder `null`, wenn kein Agent beteiligt ist. |
| `user` | Grundlegende Identitätsinformationen für das Konto, dem die Unterhaltung gehört. |
| `message.id` | Die eindeutige ID der Nachricht. |
| `message.body` | Der Nachrichtentext. Leer bei einer Nachricht, die nur einen Anhang (Bild, Sprachnotiz, Dokument) enthält. |
| `message.direction` | `inbound` für eine Nachricht vom Kontakt, `outbound` für eine von Ihrer KI oder Ihrem Team aus dem Posteingang gesendete Nachricht und `outbound-api` für eine Nachricht, die von einer Kampagne, einem Broadcast, einem Vorlagenversand oder der API gesendet wurde. |
| `message.status` | Wo sich die Nachricht in ihrem Lebenszyklus befindet: `received` für eingehend und `queued` / `sent` / `delivered` / `read` / `failed` / `undelivered` für ausgehend. Dies ist der Status zum Zeitpunkt der Erstellung der Nachricht. Eine ausgehende Nachricht kommt hier also normalerweise als `queued` oder `sent` an und erreicht danach `delivered` – verwenden Sie die **Deliveries**- und **Reads**-Ereignisse, wenn Sie diese späteren Übergänge benötigen. Sie enthalten dieselbe `message.id` wie dieser Block, sodass Sie den Übergang dieser Nachricht zuordnen können (siehe [Deliveries and Reads Webhook](#deliveries-and-reads-webhook)). |
| `message.created_at` | Wann die Nachricht erstellt wurde, in UTC (ISO 8601). |
| `message.channel` | Der Kanal, über den die Nachricht gesendet wurde, zum Beispiel `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `messenger`, `telegram`, `email` oder `custom`. |

> **Es gibt in dieser Payload weiterhin keinen `campaign`-Block.** „New Message“ sendet `contact`, `agent`, `user` und `message`. Der `agent`-Block wurde am **15. August 2026** hinzugefügt und gibt an, welcher Agent die Unterhaltung bearbeitet; wenn Sie zusätzlich Kampagnenkontext benötigen, suchen Sie den Kontakt über die API mithilfe von `contact.id`. |

> **Interne KI-Datensätze lösen diesen Webhook nicht aus.** Neben echten Nachrichten führt die Plattform ihre eigenen Buchhaltungszeilen in einer Unterhaltung (die Tool-Aufrufe der KI und interne Protokolle). Diese werden nie gesendet — Sie erhalten nur Nachrichten, die tatsächlich gesendet oder empfangen wurden.

---

## Deliveries and Reads Webhook

Diese beiden Ereignisse melden, was mit einer Nachricht geschah, nachdem sie <span data-t="appName">Your AI Connector</span> verlassen hat: **Deliveries** wird ausgelöst, wenn eine Nachricht den Kontakt erreicht (oder dies fehlschlägt), und **Reads** wird ausgelöst, wenn der Kontakt sie öffnet, auf Kanälen, die Lesebestätigungen unterstützen.

Beide enthalten einen `message`-Block mit der ID der Nachricht, auf die sich das Ereignis bezieht, sodass Sie das Update genau der Nachricht zuordnen können, die Sie gesendet haben.

### Ereignisnamen

`delivered` und `undelivered` für **Deliveries**, `read` für **Reads**.

### Payload-Format

```json
{
  "event": "delivered",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "status": "delivered"
  }
}
```

| Feld | Beschreibung |
|---|---|
| `event` | `delivered` oder `undelivered` für **Deliveries**, `read` für **Reads**. |
| `contact` | Der Kontakt, an den die Nachricht gesendet wurde. |
| `campaign` | Die Kampagne, zu der der Kontakt gehört, oder `null`. |
| `agent` | Der Agent, der die Unterhaltung bearbeitet, oder `null`. |
| `user` | Grundlegende Identitätsinformationen für das Konto, dem die Daten gehören. |
| `message.id` | Die ID der Nachricht, auf die sich dieses Update bezieht. Es ist derselbe Wert, den der [Send Message Endpoint](../api/messages.md#send-a-message) als `messageId` zurückgibt, und dieselbe `message.id`, die eine [New Message](#new-message-webhook)-Benachrichtigung enthält. |
| `message.status` | Der neue Status, immer dieselbe Zeichenfolge wie `event` (`delivered`, `undelivered` oder `read`). |

> **So ordnen Sie ein Update der von Ihnen gesendeten Nachricht zu.** Speichern Sie die `messageId`, die Sie erhalten, wenn Sie eine Nachricht über die API senden. Wenn eine **Deliveries**- oder **Reads**-Benachrichtigung eingeht, suchen Sie diese gespeicherte ID anhand von `message.id` im Payload – das ist Ihre Zustellungs- oder Lesebestätigung für genau diese Nachricht.

> **Hier gibt es keinen Nachrichtentext.** Der `message`-Block enthält nur die ID und den Status. Abonnieren Sie [New Message](#new-message-webhook), wenn Sie auch den Inhalt benötigen.

> **Der `message`-Block ist nur vorhanden, wenn wir wissen, um welche Nachricht es sich handelte.** Bei seltenen Updates, die wir nicht mit einer gespeicherten Nachricht verknüpfen können, wird der Block komplett weggelassen, anstatt ihn leer zu senden – prüfen Sie also, ob `message` existiert, bevor Sie `message.id` lesen.

> **Eine Benachrichtigung pro Statusänderung.** Eine einzelne ausgehende Nachricht erzeugt normalerweise eine `delivered`-Benachrichtigung und dann, auf Kanälen mit Lesebestätigungen, eine `read`-Benachrichtigung. Ein fehlgeschlagener Versand erzeugt stattdessen `undelivered`.

---

## Appointment Booked Webhook

Wird ausgelöst, wenn ein Kontakt einen Termin bucht. Es wird auf die gleiche Weise ausgelöst, egal ob die KI ihn während eines Gesprächs gebucht hat, Sie ihn manuell gebucht haben oder er über die API eingegangen ist.

### Ereignisname

`booked`

### Payload-Format

```json
{
  "event": "booked",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith"
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com"
  },
  "appointment": {
    "appointment_id": "<appointment-id>",
    "start_time": "2026-07-20T15:00:00.000Z",
    "end_time": "2026-07-20T15:30:00.000Z",
    "status": "confirmed",
    "room_name": "Room 1",
    "description": "Discovery call",
    "summary": "30 min intro",
    "google_calendar_event_id": null,
    "event": {
      "id": "<service-id>",
      "event_name": "Intro Call",
      "slot_duration": 30,
      "location": "Zoom",
      "meeting_link": "https://...",
      "event_type": "online"
    }
  }
}
```

| Feld | Beschreibung |
|---|---|
| `event` | Immer `booked` für dieses Ereignis. |
| `contact` | Die Person, die gebucht hat. `email` und `phone_number` können je nach Kanal leer sein. |
| `appointment.appointment_id` | Die eindeutige ID der Buchung. |
| `appointment.start_time` / `end_time` | Start und Ende des gebuchten Zeitfensters in UTC (ISO 8601). |
| `appointment.status` | Der aktuelle Status der Buchung. |
| `appointment.room_name` | Der Raum, in dem die Buchung vorgenommen wurde, falls verwendet. |
| `appointment.description` / `summary` | Freitextdetails, die bei der Buchung erfasst wurden. |
| `appointment.google_calendar_event_id` | Die ID von Google Kalender für das synchronisierte Ereignis. Sie ist im Webhook für den gebuchten Termin oft `null`, da das Kalenderereignis genau in dem Moment erstellt wird, in dem die Benachrichtigung gesendet wird – rufen Sie den Termin einen Moment später erneut über seine `appointment_id` ab, falls Sie sie benötigen, und erwarten Sie ein dauerhaftes `null` bei Konten, bei denen kein Google Kalender verbunden ist. |
| `appointment.event` | Der gebuchte Service: Name, Zeitfensterlänge, Ort, Meeting-Link, Typ. |

> **`google_calendar_event_id` ist in diesem Webhook oft `null`, und das ist normal.** Das Google Kalender-Ereignis wird im selben Moment erstellt, in dem diese Benachrichtigung ausgeht, daher ist die ID meist noch nicht bereit. Rufen Sie den Termin einen Moment später über seine `appointment_id` erneut ab, falls Sie sie benötigen. Sie bleibt dauerhaft `null`, wenn das Konto keinen verbundenen Google Kalender hat, warten Sie also nicht ewig darauf.

> **Die "Test"-Schaltfläche enthält nicht den `appointment`-Block.** Verwenden Sie sie, um zu bestätigen, dass Ihr Endpunkt antwortet, und führen Sie dann eine echte Buchung durch, um die vollständige Nutzlast zu sehen.

> **Zwei Fälle, in denen dieser Webhook nicht ausgelöst wird:** Termine, die aus einem externen Kalender importiert wurden, und Buchungen, die über die Formitable-Integration eingehen.

---

## Webhook für aktualisierte Kontakt-Tags

Wird ausgelöst, wenn ein Tag auf einen Kontakt **angewendet** wird und für dieses Tag eine Webhook-URL im Agenten oder der Kampagne konfiguriert ist, zu der der Kontakt gehört.

### Ereignisname

`contact_tags_updated`

### Auslösebedingungen

- Ein Tag wird auf einen Kontakt angewendet, dem ein Agent, eine Kampagne oder beides zugewiesen ist.
- Mindestens eines der angewendeten Tags hat eine Webhook-URL, die im Tab „Tags“ dieses Agenten oder dieser Kampagne festgelegt ist.

Wenn der Kontakt beides hat und die Tags der Kampagne Webhook-URLs enthalten, haben diese Vorrang; andernfalls werden die des Agenten verwendet.

Wenn mehrere Tags mit unterschiedlichen Webhook-URLs im selben Update angewendet werden, wird eine Anfrage pro URL gesendet, die jeweils nur die Tags enthält, die dieser URL zugeordnet sind.

**Das Entfernen eines Tags sendet niemals eine Anfrage.** Die meisten Nutzer verknüpfen diese URLs mit einer Aktion – eine Anzahlung einziehen, einen Slot buchen, einen Mitarbeiter benachrichtigen –, daher wurde ein Tag, das von einem Kontakt entfernt wurde, früher verwendet, um diese Aktion erneut auszuführen. Das ist nicht mehr möglich. Eine Entfernung wird weiterhin in `removed_tags` angezeigt, wenn sie im selben Update wie eine Anwendung erfolgt, die an dieselbe URL geht, sodass eine Automatisierung, die beide Arrays liest, den vollständigen Überblick behält; was sie jedoch niemals sehen wird, ist eine Anfrage, die allein durch eine Entfernung ausgelöst wurde. (Geändert am **12. August 2026**. Vor diesem Datum sandten Entfernungen ebenfalls eine Anfrage.)

### Payload-Format

```json
{
  "event": "contact_tags_updated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "is_bot_active": true,
    "ad_referral": {
      "ctwa_clid": "ARAbc123...",
      "source_id": "120210000000000",
      "source_type": "ad",
      "source_url": "https://fb.me/xxxx",
      "headline": "Get 20% off today",
      "body": "Message us now to claim your discount",
      "channel": "whatsapp"
    }
  },
  "added_tags": ["qualified-lead"],
  "removed_tags": ["new-lead"],
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Feld | Beschreibung |
|---|---|
| `event` | Immer `contact_tags_updated` für diesen Webhook. |
| `contact.id` | Die eindeutige ID des Kontakts, dessen Tags geändert wurden. |
| `contact.email` / `contact.phone_number` | Die E-Mail-Adresse/Telefonnummer des Kontakts, falls bekannt. |
| `contact.first_name` / `contact.last_name` | Der Name des Kontakts. |
| `contact.human_alerted` | Ob der Kontakt derzeit für menschliche Aufmerksamkeit markiert ist. |
| `contact.is_bot_active` | Ob der KI-Bot derzeit in der Unterhaltung dieses Kontakts aktiv ist. |
| `contact.ad_referral` | Nur vorhanden, wenn der Kontakt Sie erstmals über eine Meta Click-to-WhatsApp (CTWA)-Anzeige oder einen Beitrag erreicht hat. Andernfalls `null`. |
| `added_tags` | Array der in diesem Update angewendeten Tag-Namen. Niemals leer – eine Anwendung löst die Anfrage aus. |
| `removed_tags` | Array der in demselben Update entfernten Tag-Namen, falls vorhanden. Eine Entfernung allein sendet nichts. |
| `agent` | Der Agent, der die Unterhaltung des Kontakts bearbeitet (`id` und `name`), oder `null`, wenn kein Agent beteiligt ist. Hinzugefügt am **15. August 2026**. |
| `user` | Grundlegende Identitätsinformationen für das Konto, dem der Kontakt gehört. |

### Testen eines Tag-Webhooks

Neben dem Webhook-URL-Feld auf dem Tab „Tags“ befindet sich eine **Test**-Schaltfläche. Sie sendet sofort eine Beispiel-Payload an diese URL, damit Sie bestätigen können, dass Ihre Automatisierung diese empfängt, ohne auf eine echte Konversation warten zu müssen.

Der Test sendet dieselbe `contact_tags_updated`-Struktur wie oben gezeigt, unter Verwendung eines Platzhalter-Kontakts, mit dem Tag, das Sie testen, in `added_tags` und einem leeren `removed_tags`. Was Ihre Automatisierung im Test sieht, ist das, was sie auch in der Produktion sehen wird.

Zwei Dinge, die Sie wissen sollten:

- **Speichern Sie zuerst das Tag.** Der Test sucht das Tag anhand seines gespeicherten Namens. Ein brandneues Tag oder eine ungespeicherte Umbenennung kann daher noch nicht getestet werden. Die Schaltfläche bleibt ausgegraut, bis der Name auf dem Bildschirm mit dem gespeicherten Namen übereinstimmt.
- **Ein fehlgeschlagener Test zählt nicht gegen Ihren Webhook.** Tests tragen niemals zur automatischen Abschaltung nach wiederholten Fehlern bei, wie unter [Webhook-Zuverlässigkeit](#webhook-reliability) beschrieben.

Wenn der Test fehlschlägt, teilt Ihnen die Meldung mit, was Ihr Endpunkt geantwortet hat (zum Beispiel ein `404` oder `500`), was normalerweise ausreicht, um eine falsche URL oder einen Workflow, der nicht eingeschaltet ist, zu identifizieren.

---

## Webhook für abgeschlossene Aufgaben

> **Nur als Referenz.** Aufgaben-Webhooks (als Daten) sind hier für Entwickler dokumentiert; die Ereignisse **Aufgabe erstellt**, **Aufgabe aktualisiert** und **Aufgabe abgeschlossen** sind wie jedes andere Ereignis in der Standard-Ereignisliste im Webhook-Formular auswählbar – siehe [Verfügbare Auslöser-Ereignisse](#available-trigger-events) und [Die 22 Webhook-Ereignisse](#the-22-webhook-events).

Diese Nutzlast wird gesendet, wenn eine Aufgabe in eine Phase übergeht, die als Abschlussphase markiert ist. Eine Aufgabe, die zwischen Nicht-Abschlussphasen verschoben wird, sendet stattdessen das `taskUpdated`-Format.

### Ereignisname

`taskCompleted`

### Auslösebedingungen

- Eine Aufgabe wird aktualisiert.
- Ihr `stage`-Wert hat sich im Vergleich zum vorherigen Wert geändert.
- Die neue Phase ist in den Aufgabenphasen-Einstellungen des Kontos als Abschlussphase konfiguriert.

### Payload-Format

```json
{
  "event": "taskCompleted",
  "contact": {
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<task-id>",
    "title": "Follow up with Jane",
    "description": "Confirm pricing and send proposal",
    "type": "follow_up",
    "priority": "high",
    "stage": "<stage-id>",
    "due_date": "2026-01-20T15:00:00Z",
    "source": "ai",
    "source_detail": "<source-detail>",
    "campaign_id": "<campaign-id>",
    "linked_human_alert": "<human-alert-id>",
    "tags": ["qualified-lead"],
    "notes": "Customer requested a callback"
  }
}
```

| Feld | Beschreibung |
|---|---|
| `event` | Immer `taskCompleted` für diesen Webhook. Das gleiche Nutzlastformat wird als `taskUpdated` gesendet, wenn sich eine Aufgabe ändert, ohne in eine Abschlussphase einzutreten. |
| `contact` | Der mit der Aufgabe verknüpfte Kontakt, falls vorhanden. `null`, wenn keine Verknüpfung besteht. |
| `contact.human_alert_reason` | Der Grund, warum der Kontakt für menschliche Aufmerksamkeit markiert wurde, falls zutreffend. |
| `user` | Grundlegende Identitätsinformationen für das Konto, dem die Aufgabe gehört. |
| `message.id` | Die eindeutige ID der Aufgabe. |
| `message.title` / `description` | Der Titel und die Beschreibung der Aufgabe. |
| `message.type` | Der Aufgabentyp (zum Beispiel `follow_up`, `call`, `custom`). |
| `message.priority` | Die Aufgabenpriorität (`low`, `medium`, `high`). |
| `message.stage` | Die ID der Phase, in der sich die Aufgabe jetzt befindet. |
| `message.due_date` | Das Fälligkeitsdatum der Aufgabe, falls festgelegt. |
| `message.source` | Was die Aufgabe erstellt hat (`ai`, `manual`, `api`). |
| `message.source_detail` | Zusätzliche Details zur Quelle. |
| `message.campaign_id` | Die ID der verknüpften Kampagne oder `null`. |
| `message.linked_human_alert` | Die ID des verknüpften menschlichen Alarms, falls vorhanden. |
| `message.tags` | Auf die Aufgabe angewendete Tags. |
| `message.notes` | Freitext-Notizen zur Aufgabe. |

---

## Einen Webhook ausschalten (oder löschen)

Jeder Webhook verfügt über einen Ein-/Ausschalter direkt in seiner Zeile. Wenn Sie einen Webhook **ausschalten**, werden keine Ereignisse mehr empfangen, aber alles, was Sie konfiguriert haben – die URL, die Ereignisse, ein eventuelles Signaturgeheimnis – bleibt erhalten. Schalten Sie ihn wieder ein, und er macht dort weiter, wo er aufgehört hat; Ereignisse, die während der Deaktivierung aufgetreten sind, werden nicht nachträglich zugestellt.

Verwenden Sie diese Funktion, wenn Sie die Zustellungen vorübergehend stoppen möchten: Ihr Endpunkt wird gerade neu aufgebaut, Sie debuggen eine fehleranfällige Integration oder Sie pausieren eine Automatisierung.

Das **Löschen** eines Webhooks (das Papierkorb-Symbol in der Zeile) entfernt ihn dauerhaft, einschließlich seines Signaturgeheimnisses. Wenn Sie nur die Zustellung stoppen möchten, schalten Sie ihn stattdessen aus – löschen Sie ihn nur, wenn Sie den Endpunkt nicht mehr benötigen.

> **Dies ist nicht dasselbe, wie wenn ein Webhook automatisch deaktiviert wird.** Wenn wir Ihren Webhook nach wiederholten Fehlern deaktivieren (siehe [Webhook-Zuverlässigkeit](#webhook-reliability)), wird er durch den oben genannten Schalter nicht wieder aktiviert. Sobald Ihr Endpunkt behoben ist, bearbeiten Sie den Webhook und speichern Sie ihn mit einer geänderten URL (jede URL-Änderung reaktiviert ihn), oder rufen Sie den [Re-Enable-Endpunkt](../api/webhooks.md) über die API auf – oder bitten Sie den Support, ihn für Sie wieder zu aktivieren.

---

## Signierte Payloads (Überprüfung, ob ein Webhook wirklich von uns stammt)

Jeder, der Ihre Webhook-URL erfährt, könnte eine gefälschte Anfrage an sie senden. Wenn Sie Webhooks automatisch verarbeiten – z. B. Abrechnungen aktualisieren oder CRM-Datensätze erstellen –, ermöglicht Ihnen das Aktivieren der **Signatur**, zu überprüfen, ob jede Anfrage tatsächlich von uns stammt.

Die Signatur ist **optional und standardmäßig deaktiviert**. Sie aktivieren sie pro Webhook in der Bearbeitungsansicht des jeweiligen Webhooks (öffnen Sie die Zeile eines gespeicherten Webhooks).

### Signierung aktivieren

1. Öffnen Sie den Webhook (Einstellungen → Integrationen → Webhooks → klicken Sie auf die Zeile Ihres Webhooks).
2. Klicken Sie im Bereich **Signaturgeheimnis** auf **Generieren**.
3. Kopieren Sie das Geheimnis (es beginnt mit `whsec_`) und speichern Sie es in Ihrem empfangenden System. Behandeln Sie es wie ein Passwort.

Sie können jederzeit über dasselbe Bedienfeld zurückkehren, um das Geheimnis anzuzeigen, zu kopieren, zu rotieren oder zu deaktivieren.

### Was wir senden

Sobald die Signierung aktiviert ist, enthält jede Zustellung für diesen Webhook diese zwei zusätzlichen HTTP-Header:

| Header | Bedeutung |
|---|---|
| `X-Webhook-Signature` | Die Signatur in der Form `v1=<hex>`. |
| `X-Webhook-Timestamp` | Zeitpunkt des Versands als Unix-Zeitstempel in Sekunden. |

Diese drei sind bei **jeder** Zustellung enthalten, unabhängig davon, ob sie signiert ist oder nicht:

| Header | Bedeutung |
|---|---|
| `X-Webhook-Delivery` | Eine eindeutige ID für dieses Ereignis. Bleibt bei Wiederholungsversuchen gleich, daher ist dies der Wert, anhand dessen Sie Duplikate entfernen können. |
| `X-Webhook-Attempt` | Welcher Versuch dies ist (`1` ist der erste Versuch). |
| `X-Webhook-Event` | Der Ereignisname, damit Sie das Routing ohne Lesen des Bodys vornehmen können. |

### Überprüfung

Die Signatur ist ein HMAC-SHA256 des Strings `<timestamp>.<raw request body>`, wobei Ihr Signierungs-Secret als Schlüssel verwendet wird.

**Überprüfen Sie den rohen Anfrage-Body – die exakten Bytes, die Sie empfangen haben.** Wenn Ihr Framework das JSON analysiert und vor der Überprüfung neu serialisiert, können sich die Bytes ändern und die Signatur stimmt nicht mehr überein.

Node.js-Beispiel:

```js
const crypto = require("crypto");

function verify(rawBody, headers, secret) {
  const timestamp = headers["x-webhook-timestamp"];
  const signature = headers["x-webhook-signature"]; // "v1=<hex>"

  // Reject anything older than 5 minutes so a captured request can't be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  return crypto.timingSafeEqual(Buffer.from(signature.replace("v1=", "")), Buffer.from(expected));
}
```

Python-Beispiel:

```python
import hashlib, hmac, time

def verify(raw_body: bytes, headers, secret: str) -> bool:
    timestamp = headers["X-Webhook-Timestamp"]
    signature = headers["X-Webhook-Signature"].replace("v1=", "")

    # Reject anything older than 5 minutes so a captured request can't be replayed later.
    if abs(time.time() - int(timestamp)) > 300:
        return False

    expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()

    return hmac.compare_digest(signature, expected)
```

> **Vergleichen Sie Signaturen mit einer zeitlich sicheren Funktion** (`timingSafeEqual` / `compare_digest`), nicht mit `==`. Es kostet nichts und vermeidet eine subtile Angriffsart.

### Rotieren des Geheimnisses

Klicken Sie auf **Rotieren**, um das Geheimnis zu ersetzen. Die Umstellung erfolgt sofort: Die allererste nächste Zustellung wird nur noch mit dem neuen Geheimnis signiert. Wenn Ihr Endpunkt live ist, akzeptieren Sie für einige Minuten **sowohl** das alte als auch das neue Geheimnis, während Sie das neue bereitstellen.

Das Deaktivieren der Signierung führt lediglich dazu, dass keine Signatur-Header mehr gesendet werden.
---

## Wiederholen fehlgeschlagener Zustellungen

Standardmäßig wird eine fehlgeschlagene Zustellung nicht wiederholt – wenn Ihr System in diesem Moment ausgefallen ist, geht dieses Ereignis verloren.
Aktivieren Sie **Fehlgeschlagene Zustellungen erneut versuchen** für einen Webhook (im Erstellen/Bearbeiten-Formular), und wir werden es weiter versuchen:

| Versuch | Wann |
|---|---|
| 1 | Sofort |
| 2 | 1 Minute später |
| 3 | 5 Minuten später |
| 4 | 30 Minuten später |
| 5 | 2 Stunden später |

Das erstreckt sich über etwa **2 Stunden und 40 Minuten**, sodass ein Webhook ein Wartungsfenster oder einen kurzen Ausfall auf Ihrer Seite überstehen kann.
**Was wird wiederholt:** vorübergehende Probleme – wenn Ihr Server einen 5xx-Fehler zurückgibt, ein Timeout auftritt oder ein Verbindungsfehler vorliegt.
**Was nicht erneut versucht wird:** Wenn Ihr Endpunkt die Anfrage selbst ablehnt (jeder 4xx-Fehler), versuchen wir es nicht erneut – das erneute Senden der identischen Anfrage würde nur zur identischen Ablehnung führen.

**Welche Ereignisse werden wiederholt:** Tag-Webhooks (`contact_tags_updated`), die drei Aufgabenereignisse und die tägliche Zusammenfassung. Die anderen werden nur einmal gesendet, daher hat der Schalter bei diesen keine Funktion. Jedes Ereignis enthält weiterhin `X-Webhook-Delivery`, sodass eine einzige Deduplizierungsregel für alle gilt.

> **Aktivieren Sie Wiederholungsversuche nur, wenn Ihr Endpunkt idempotent ist.** Wiederholungsversuche bedeuten, dass dasselbe Ereignis mehr als einmal ankommen kann. Verwenden Sie den `X-Webhook-Delivery`-Header, um eine Wiederholung zu erkennen: Er bleibt bei jedem Versuch für ein Ereignis gleich, sodass Sie eine ID, die Sie bereits verarbeitet haben, sicher ignorieren können.

Wiederholungsversuche interagieren wie gewünscht mit der automatischen Abschaltung nach wiederholten Fehlern (siehe [Webhook-Zuverlässigkeit](#webhook-reliability)): Der Fehlerzähler zählt eine **gesamte Zustellung** erst, nachdem jeder Wiederholungsversuch aufgebraucht wurde – nicht jeden einzelnen Versuch.

---

## Webhook-Zuverlässigkeit

- <span data-t="appName">Your AI Connector</span> sendet Webhooks über eine sichere Verbindung (HTTPS). Stellen Sie sicher, dass die von Ihnen angegebene Webadresse HTTPS verwendet.
- Wenn Ihr System einen Fehler zurückgibt, gilt die Zustellung als fehlgeschlagen.
- Überwachen Sie die Verfügbarkeit Ihres empfangenden Systems, um keine Ereignisse zu verpassen.
- Aktivieren Sie für kritische Workflows [Fehlgeschlagene Zustellungen erneut versuchen](#retrying-failed-deliveries) und ziehen Sie zusätzlich einen Fallback-Mechanismus in Betracht.

> **Webhooks werden nach wiederholten Fehlern automatisch deaktiviert.** Wenn Ihre Webhook-URL wiederholt fehlschlägt (etwa 5 Fehler in Folge oder 3 in Folge bei Konfigurationsfehlern), stoppt <span data-t="appName">Your AI Connector</span> automatisch das Senden von Ereignissen an diese URL. Um ihn wieder zu aktivieren, sobald Ihr Endpunkt wieder einwandfrei funktioniert: Bearbeiten Sie den Webhook und speichern Sie ihn mit einer geänderten URL (jede URL-Änderung reaktiviert ihn), oder verwenden Sie den [Re-Enable-Endpunkt](../api/webhooks.md) über die API – ein erneutes Speichern mit derselben URL reicht nicht aus. Der Support kann ihn ebenfalls für Sie reaktivieren.

---

## Fehlerbehebung

| Problem | Lösung |
|---|---|
| Webhook wird nicht ausgelöst | Prüfen Sie zuerst, ob der Webhook in seiner Zeile nicht **ausgeschaltet** ist. Bestätigen Sie dann, dass die korrekten Ereignisse ausgewählt sind und Ihre URL aus dem Internet erreichbar ist. |
| Test-Ereignis funktioniert, aber echte Ereignisse nicht | Stellen Sie sicher, dass der spezifische Ereignistyp aktiviert ist. Wenn Sie eine Anfrage erwartet haben, wenn ein Tag angewendet wird, beachten Sie, dass `subscribed_to_tags` die Ereignisse eines Webhooks nicht auf ein Tag beschränkt – es schränkt nur ein, welche Tags eine Benachrichtigung zur Konversationszusammenfassung erzeugen. Um eine Anfrage zu erhalten, wenn ein spezifisches Tag angewendet wird, legen Sie eine Webhook-URL für dieses Tag auf dem Tab **Tags** des Agenten (oder der Kampagne) fest – siehe [Webhook für aktualisierte Kontakt-Tags](#contact-tags-updated-webhook). |
| Nichts kommt in n8n / Make / Zapier an | Sie verwenden wahrscheinlich die **Test-URL** der Plattform, die nur auf ein einzelnes Ereignis direkt nach dem Klicken auf "Auf Test-Ereignis warten" hört. Speichern Sie für Live-Ereignisse die **Produktions-URL** und schalten Sie den Workflow auf **Aktiv**. |
| Empfang doppelter Ereignisse | Prüfen Sie auf mehrere Webhooks, die auf dieselbe URL zeigen. Wenn **Fehlgeschlagene Zustellungen wiederholen** aktiviert ist, ist eine Wiederholung zu erwarten, wenn Ihr Endpunkt ein Ereignis akzeptiert, aber nicht rechtzeitig geantwortet hat – führen Sie eine Deduplizierung über `X-Webhook-Delivery` durch. |
| Signaturprüfung schlägt immer fehl | Fast immer, weil der Body vor der Prüfung neu serialisiert wurde. Überprüfen Sie ihn gegen den **rohen** Request-Body, signieren Sie `<timestamp>.<body>` und bestätigen Sie, dass Sie das aktuelle Secret verwenden, falls Sie es kürzlich rotiert haben. |
| Wiederholungsversuche finden nicht statt | Wiederholungsversuche sind deaktiviert, sofern sie nicht für diesen spezifischen Webhook aktiviert wurden. Wir wiederholen keine 4xx-Antworten. |
| Der `campaign`-Block ist immer `null` | Zu erwarten, wenn Ihr Konto Agenten verwendet: Kontakte sind einem Agenten statt einer Kampagne zugeordnet. Lesen Sie stattdessen den `agent`-Block – siehe [Webhook-Datenformat](#webhook-data-format). |
| Daten sind leer oder fehlerhaft | Überprüfen Sie, ob Ihr empfangendes System JSON akzeptiert. Prüfen Sie Ihre Server-Logs auf Parsing-Fehler. |
| Webhook-URL gibt Fehler zurück | Testen Sie Ihre URL mit einem Tool wie Postman oder [webhook.site](https://webhook.site). |
| Webhook wurde nach einem Ausfall komplett gestoppt | Wiederholte Fehler deaktivieren einen Webhook automatisch. Ein erneutes Speichern aktiviert ihn nicht wieder – beheben Sie Ihren Endpunkt und kontaktieren Sie dann den Support. |
| Speichern oder Testen ergibt einen Berechtigungsfehler | Sie benötigen die Berechtigung "Bearbeiten" für Integrationen. Bitten Sie den Kontoinhaber, diese zu erteilen. |
| Die `subscribed_to_tags`-Liste eines Webhooks war leer | `subscribed_to_tags` beschränkt die Ereignisse eines Webhooks nicht auf ein Tag – es schränkt nur ein, welche Tags eine Benachrichtigung zur Konversationszusammenfassung erzeugen. Das Bearbeiten über das Webhook-Formular löscht diese Liste nicht mehr (behoben am 21. Juli 2026). Wenn ein Webhook seine Liste vor diesem Datum verloren hat, legen Sie `subscribed_to_tags` erneut über die [Webhooks-API](../api/webhooks.md) fest – siehe [Tag-basierte Webhook-Trigger](#tag-based-webhook-triggers). |

---

## Nächste Schritte

- [GoHighLevel-Integration](ghl-integration.md) – verwenden Sie Webhooks, um <span data-t="appName">Your AI Connector</span> mit GHL zu integrieren.
- [API-Zugriff](api-access.md) – kombinieren Sie Webhooks mit der API für leistungsstarke Automatisierungen.
- [Tags zum Kennzeichnen von Kontakten verwenden](../get-started/creating-tags.md) – richten Sie Tags ein, die Ihre Webhooks auslösen.
