Webhooks¶
Liefere Lebenszyklus-Ereignisse einer Session sofort von Expecto an eine URL deiner Wahl. Webhooks eignen sich, um nachgelagerte BI-Pipelines anzustoßen, Slack-/Teams-Benachrichtigungen bei einer fehlgeschlagenen Session auszulösen oder das exportierte Paket ohne Polling in eigene Systeme zu übergeben.
Was du brauchst
Die Rolle Owner oder Admin in der Organisation. Jeder Endpoint gehört zu einer Organisation und optional zu einem Projekt darin.
Was geliefert wird¶
Für jede Session in der Organisation sendet Expecto bei jedem Lebenszyklus-Übergang einen Webhook:
| Ereignis | Wann es ausgelöst wird |
|---|---|
session.created |
Eine neue Session wird angelegt |
session.uploaded |
Eine Datei wird zur Session hochgeladen |
session.parsed |
Parsing fehlerfrei abgeschlossen |
session.transformed |
Transformation fehlerfrei abgeschlossen |
session.checked |
Business-Rule-Prüfungen fehlerfrei abgeschlossen |
session.confirmed |
Übermittler hat die Daten bestätigt |
session.approved |
Finale Freigabe erteilt (nur im Modus dual — der Modus single überspringt diesen Schritt) |
session.exported |
Export-Paket erzeugt und hochgeladen |
session.failed |
Eine Pipeline-Stufe ist fehlgeschlagen (parse, transform oder check). Der Payload enthält stage und reason. |
webhook.ping |
Synthetisches Test-Ereignis auf Knopfdruck |
Der Payload enthält keine Download-URL für das Export-Paket — Konsumenten
holen es authentifiziert über die API mit ihrem eigenen API-Key. Das Export-
Ereignis liefert den Paketnamen und eine Artefakt-Liste mit sha256,
row_count und size_bytes pro Datei.
Wo du es findest¶
Öffne Einstellungen → Webhooks. Der Tab listet jeden für dich sichtbaren Endpoint und bietet einen Button Webhook erstellen.

Endpoint anlegen¶
Klicke Webhook erstellen. Der Dialog hat drei Felder:
- Name — ein menschenlesbares Label, damit du Endpoints in Listen und Delivery-Logs unterscheiden kannst.
- URL — wohin Expecto Ereignisse POSTet. Muss
https://sein. Private, Loopback-, Link-Local- und Cloud-Metadaten-IP-Bereiche werden bereits bei der Anlage als SSRF-Schutz abgelehnt. Der Dev-Override (webhook_allow_http) steht nur Betreibern der Expecto-Instanz zur Verfügung, nicht in der UI. - Ereignistypen — mindestens einer. Ereignisse sind nach Namespace
(z. B.
session.*) in einem Baum gruppiert: einzelne Ereignisse anhaken, eine ganze Gruppe über deren Checkbox umschalten oder Select all / Clear verwenden. Die Auswahl lässt sich später über Edit ändern.

Nach Erstellen zeigt Expecto den Signatur-Schlüssel genau ein Mal
in einem Modal. Kopiere ihn jetzt — das ist die einzige Gelegenheit, den
Klartext zu sehen. Expecto speichert eine verschlüsselte Form und zeigt
fortan nur noch das Präfix whsec_…. Bei Verlust musst du den Schlüssel
rotieren und den Konsumenten aktualisieren.
Die Endpoint-Liste¶
Jede Zeile zeigt URL, abonnierte Ereignisse, Schlüssel-Präfix und die Badges, die den Zustand zusammenfassen:
- Disabled — der Endpoint ist pausiert; neue Ereignisse werden nicht zugestellt.
- Auto-disabled — Expecto hat den Endpoint nach 10 aufeinanderfolgenden dead-letter-Zustellungen deaktiviert (siehe Fehlerbehandlung).

Outbound-Bindings in derselben Liste¶
Neben Webhook-Endpoints zeigt die Liste auch die Outbound-Bindings der
Organisation — Regeln auf Projektebene, die Session-Events über eine
Integrationsverbindung direkt in eine externe Plattform schreiben (heute:
Salesforce). Eine Binding-Karte trägt das Badge Outbound binding plus den
Adaptertyp, zeigt statt einer URL Verbindung → Ziel (das Salesforce-Objekt),
die abonnierten Events, das zugehörige Projekt und eines der Status-Badges:
- Active — Events werden zugestellt.
- Inactive — das Binding ist pausiert.
- Auto-disabled — Expecto hat das Binding nach aufeinanderfolgenden Dead-Letter-Zustellungen pausiert; die Anzahl steht neben dem Badge.
Bindings werden im Projekt bearbeitet, nicht hier: öffne Project › Context › Outbound Bindings (die Aktion Open in project führt dorthin). Show deliveries auf der Karte öffnet dasselbe Delivery-Log wie bei Endpoints; die Spalte Result wird aus der Antwort des externen Systems befüllt.
Das Actions-Menü¶
Jede Endpoint-Karte hat rechts ein Menü Actions ▾. Die Einträge:

- Edit — Name, URL, abonnierte Ereignisse oder den benutzerdefinierten Auth-Header des Endpoints ändern. Öffnet einen Dialog, der mit den aktuellen Werten vorbefüllt ist.
- Show deliveries / Hide deliveries — klappt die Delivery-Log-Tabelle inline ein/aus (siehe unten).
- Send ping — schickt ein synthetisches
webhook.ping-Envelope an den Endpoint. Nutze dies nach dem Anlegen, um die Erreichbarkeit und die korrekte Signaturprüfung zu bestätigen. - Rotate secret — erzeugt einen neuen Signatur-Schlüssel, speichert ihn verschlüsselt und zeigt den Klartext genau einmal im selben Reveal- Modal. Der bisherige Schlüssel wird ab Bestätigung der Rotation nicht mehr akzeptiert — aktualisiere deinen Konsumenten im Gleichschritt, oder rechne mit Signaturfehlern bis dahin.
- Disable / Enable — Zustellungen pausieren und fortsetzen. Pausieren löscht weder den Endpoint noch dessen Historie; geplante Retries werden schlicht angehalten.
- Delete — entfernt Endpoint und Delivery-Historie. Nicht rückgängig zu machen.
Das Delivery-Log¶
Wähle Show deliveries, um die letzten 50 Zustellungen an den Endpoint zu sehen, neueste zuerst.

Die Spalten:
- Event — der Ereignistyp (z. B.
session.exported,webhook.ping). - Status —
pending,in_progress,succeededoderfailed. - Attempts — aktueller Versuch gegen das Maximum (Standard
6). - Code — der letzte HTTP-Status, den dein Endpoint zurückgegeben hat.
- Result — was zurückkam: bei einer erfolgreichen Outbound-Binding- Zustellung die im externen System angelegte Record-ID (z. B. die Salesforce-Record-ID), bei einer fehlgeschlagenen Zustellung der Fehlerausschnitt (Hover zeigt den vollen Text), bei einem anstehenden Retry der Zeitpunkt des nächsten Versuchs.
- When — Zeitpunkt des letzten Versuchs.
- Actions — eine Schaltfläche Replay (siehe unten).
Eine Zustellung wiederholen (Replay)¶
Replay schickt denselben Payload erneut, vergibt aber eine neue
webhook-id und signiert den Body neu, damit die Signaturprüfung weiterhin
gelingt. Nutze es, wenn ein Konsument eine Zustellung verpasst hat, oder
um etwas erneut auszuliefern, das nach Behebung des Empfängers im Zustand
failed landete. Die neue Zustellung verweist auf das Original — dein
nachgelagertes System kann nach der ursprünglichen Ereignis-ID
deduplizieren, falls Exactly-Once-Semantik gewünscht ist, oder den Replay
als frisches Ereignis behandeln.
Fehlerbehandlung¶
Gibt dein Konsument etwas außerhalb von 2xx zurück, wiederholt Expecto mit exponentiellem Backoff (Standard: Basis 30 s, Cap 1 h, insgesamt 6 Versuche) und mit Jitter pro Zustellung, damit Retries vieler Endpoints nicht synchron laufen.
Sind alle Versuche einer Zustellung aufgebraucht, wechselt sie in den
Dead-Letter-Zustand und der Consecutive-Failures-Zähler des
Endpoints erhöht sich. Nach 10 aufeinanderfolgenden dead-lettered
Zustellungen wird der Endpoint automatisch deaktiviert — Expecto setzt
disabled_reason = "consecutive_failures" und stellt keine neuen
Ereignisse mehr zu.
Um einen automatisch deaktivierten Endpoint wieder zu aktivieren, behebe den Fehler im Konsumenten und nutze Enable im Actions-Menü. Der Zähler wird zurückgesetzt und Expecto stellt neue Ereignisse ab dem nächsten zu (Ereignisse, die bereits dead-lettered wurden, werden nicht automatisch erneut versendet — bei Bedarf manuell per Replay).
Eine einzige erfolgreiche Zustellung reicht, um den Zähler zurückzusetzen — ein wackeliger Konsument, der sich innerhalb von neun Fehlern wieder fängt, löst das Auto-Disable nicht aus.
Endpoint auf ein Projekt scopen¶
Endpoints ohne Projekt sind Org-weit: sie erhalten jedes passende Session-Ereignis der Organisation, unabhängig vom Projekt der Session. Endpoints, die an ein Projekt gebunden sind, erhalten nur Ereignisse für Sessions in diesem Projekt. Nutze das Project-Scoping, wenn unter- schiedliche Teams unterschiedliche BI-Konsumenten besitzen oder ein Auftragnehmer keine anderen Projekte sehen soll.
Der Project-Scope wird programmatisch gesetzt (über API oder MCP) — er ist im aktuellen UI-Dialog nicht freigeschaltet. Der Endpoint-Listen- Filter respektiert deinen Projektzugriff, sodass Auftragnehmer nur Endpoints sehen, die zu Projekten gehören, auf die sie Zugriff haben.
Eigener Auth-Header¶
Manche Empfänger sitzen hinter einem Reverse Proxy oder API Gateway, der
vom Aufrufer (uns) eine Authentifizierung verlangt — etwa
Authorization: Bearer <token> gegen einen OAuth2-Proxy oder
X-API-Key: <key> gegen ein eigenes Gateway. Aktiviere im Create-Dialog
die Checkbox Add a custom auth header, um einen solchen zu setzen.
Trage Header-Name (z. B. Authorization) und Wert (Bearer eyJ…) ein;
der Wert wird mit demselben Fernet-Schlüssel wie der Signatur-Schlüssel
verschlüsselt und erst unmittelbar vor jedem ausgehenden Request
entschlüsselt.
Der Header-Wert ist write-only — nach dem Speichern zeigt die UI nur noch den Header-Namen, nicht den Wert. Zum Rotieren des Werts den Endpoint bearbeiten und einen neuen eintragen; zum vollständigen Entfernen des Headers per API löschen (UI dafür folgt nach).
Das ergänzt — ersetzt nicht — die HMAC-Signatur. Die Signatur authentifiziert den Absender (Expecto). Der eigene Header lässt deine Infrastruktur entscheiden, ob der Request überhaupt akzeptiert wird.
Sicherheit & Verifikation¶
Jeder Request an deine URL trägt drei Header:
webhook-id— UUID dieser Zustellung. Stabil über Retries; ändert sich bei einem Replay.webhook-timestamp— Unix-Sekunden, wann der Request signiert wurde.webhook-signature—v1,<base64-HMAC-SHA256>überwebhook-id.timestamp.body.
Verifiziere, indem du das HMAC mit dem Signatur-Schlüssel deines
Endpoints neu berechnest und in konstanter Zeit vergleichst. Lehne
Requests, die älter als 5 Minuten sind, ab
(webhook_signature_tolerance_seconds).
Beispiel-Verifikationen in Python und Node sowie eine vollständige Beschreibung des Envelope findest du in der Entwickler-Referenz unter Für Entwickler → Webhooks.