# Webhooks einrichten

<Lead>
Mit Webhooks informiert die Plattform deine eigenen Systeme in Echtzeit: Bei jedem abonnierten Ereignis (zum Beispiel einer neuen Terminbuchung oder einer Website-Anfrage) sendet sie einen signierten POST-Request an eine URL deiner Wahl. Ideal für CRM-Abgleich, Zapier/Make-Automationen oder eigene Skripte.
</Lead>

## Voraussetzungen

- Die Verwaltung von Webhooks erfordert die entsprechende Berechtigung (standardmäßig Owner und Admins).
- Du brauchst einen HTTPS-Endpoint, der POST-Requests entgegennimmt und mit einem Status 2xx antwortet.

## Endpoint anlegen

<Steps>
  <Step title="Webhook-Verwaltung öffnen">
    Gehe zu **Einstellungen > Webhooks** und klicke auf **Endpoint hinzufügen**.
  </Step>
  <Step title="URL und Events festlegen">
    Trage die Ziel-URL ein und wähle die Events aus dem Katalog. Du kannst einzelne Events abonnieren oder mit **Alle Events** jedes aktuelle und künftige Event erhalten.
  </Step>
  <Step title="Signing-Secret sichern">
    Nach dem Anlegen wird das Signing-Secret (Format `whsec_...`) genau einmal angezeigt. Kopiere es sofort in deinen Passwort-Manager oder die Konfiguration deines Empfängers. Danach ist es nicht mehr einsehbar.
  </Step>
  <Step title="Test-Event senden">
    Öffne die Detailseite des Endpoints und sende ein Test-Event. Die Zustellung erscheint kurz darauf im Log. So prüfst du Erreichbarkeit und Signatur-Prüfung, bevor echte Events fließen.
  </Step>
</Steps>

## Welche Events gibt es?

Der Event-Katalog ist in Domänen gruppiert. Ein Überblick:

| Gruppe | Beispiele |
|---|---|
| Objekte | `property.created`, `property.updated`, `property.sync.completed` |
| Kontakte | `contact.sync.completed` |
| Tools | `tool.installed`, `tool.uninstalled`, `tool.run.completed`, `tool.run.failed` |
| Zugangsdaten-Tresor | `credential.created`, `credential.revealed`, `credential.external_shared` |
| DB-Leads | `db-lead.created`, `db-lead.moved`, `db-lead.scan.completed` |
| Homestaging | `homestaging.generated` |
| Website | `website_lead.received`, `website_page.published`, `website_domain.verified` |
| Termin-Booking | `booking.created`, `booking.cancelled`, `booking.rescheduled`, `booking.updated` |
| Workspace und Abrechnung | `tenant.plan_changed`, `tenant.credit_pack_purchased`, `tenant.seat_subscribed` |

Die vollständige, immer aktuelle Liste mit Beschreibung und Beispiel-Payload siehst du direkt im Event-Picker beim Anlegen des Endpoints.

## Was dein Endpoint empfängt

Jede Zustellung ist ein POST mit JSON-Body:

```json
{
  "id": "5f0f9c3a-...",
  "type": "booking.created",
  "createdAt": "2026-07-21T09:30:00.000Z",
  "data": {
    "appointmentId": "a1b2c3d4-...",
    "eventTypeId": "b2c3d4e5-...",
    "startsAt": "2026-08-03T09:30:00.000Z"
  }
}
```

Dazu kommen drei Header nach dem Standard-Webhooks-Format:

| Header | Inhalt |
|---|---|
| `webhook-id` | Eindeutige ID der Zustellung (identisch bei Wiederholungen) |
| `webhook-timestamp` | Unix-Zeitstempel in Sekunden |
| `webhook-signature` | `v1,<Base64-HMAC>` |

## Signatur prüfen

Prüfe bei jedem Empfang die Signatur, damit nur echte Plattform-Events akzeptiert werden:

1. Bilde die Zeichenkette `{webhook-id}.{webhook-timestamp}.{roher Request-Body}`.
2. Berechne HMAC-SHA256 mit deinem Signing-Secret (den Teil nach `whsec_` Base64-dekodieren).
3. Vergleiche das Base64-Ergebnis mit dem Wert nach `v1,` im `webhook-signature`-Header.

Standard-Webhooks-Bibliotheken für gängige Sprachen nehmen dir diese Schritte ab.

## Zustellung, Wiederholungen und Pausierung

- Antwortet dein Endpoint nicht mit 2xx, wiederholt die Plattform die Zustellung automatisch: nach 1, 5, 30, 120 und 720 Minuten (insgesamt bis zu 5 Versuche).
- Das Zustell-Log auf der Detailseite zeigt jeden Versuch mit Status, Antwortzeit und den ersten 2.048 Zeichen der Antwort. Einzelne Zustellungen kannst du manuell **erneut zustellen**.
- Schlagen 15 Zustellungen in Folge fehl, pausiert der Endpoint automatisch. Nach dem Beheben des Problems aktivierst du ihn wieder in der Verwaltung.

<Info title="Eigene Header">
Pro Endpoint kannst du zusätzliche HTTP-Header hinterlegen (zum Beispiel einen eigenen API-Key für dein Zielsystem). Die Signatur-Header der Plattform lassen sich nicht überschreiben.
</Info>

## Secret rotieren

Bei Verdacht auf ein geleaktes Secret: Detailseite öffnen und **Secret rotieren**. Das alte Secret wird sofort ungültig; das neue wird wieder genau einmal angezeigt. Aktualisiere dein Zielsystem direkt im Anschluss, sonst schlagen die Signatur-Prüfungen dort fehl.

## Häufige Fragen

<Faq>
  <FaqItem q="Bekomme ich Events anderer Workspaces?">
    Nein. Jeder Endpoint gehört zu genau einem Workspace und empfängt ausschließlich dessen Events.
  </FaqItem>
  <FaqItem q="In welcher Reihenfolge kommen Events an?">
    In der Regel in Entstehungsreihenfolge. Bei Wiederholungen nach Fehlern kann sich die Reihenfolge verschieben. Nutze `createdAt` aus dem Body, wenn die Reihenfolge wichtig ist.
  </FaqItem>
  <FaqItem q="Kann ich ein Event doppelt erhalten?">
    Ja, in seltenen Fällen (zum Beispiel wenn deine Antwort nach einem Timeout doch noch ankam). Verwende die `webhook-id` als Idempotenz-Schlüssel und verarbeite jede ID nur einmal.
  </FaqItem>
  <FaqItem q="Warum ist mein Endpoint pausiert?">
    Nach 15 fehlgeschlagenen Zustellungen in Folge pausiert der Endpoint automatisch, damit sich keine Warteschlange aufstaut. Behebe die Ursache (Log ansehen) und aktiviere ihn wieder.
  </FaqItem>
</Faq>
