Webhooks
Empfangen Sie signierte Ereignisbenachrichtigungen, wenn Dokumente indiziert werden, Lieferungen fehlschlagen oder Endpunkte ihren Zustand ändern. Überprüfung, Wiederholungsversuche und Tests.
Webhooks senden Ereignisbenachrichtigungen als HTTPS-POST-Anfragen an Ihre Systeme, sodass Sie auf Änderungen reagieren können, ohne Polling durchführen zu müssen. Registrieren Sie einen Endpunkt in den Workspace-Einstellungen: Die URL muss HTTPS verwenden, und pro Workspace können bis zu 10 Endpunkte registriert werden. Bei der Erstellung erhalten Sie genau einmal einen Signatur-Schlüssel (mit der Präfix whsec_, im Standard-Webhooks-Format). Dieser Schlüssel ist anschließend nicht mehr abrufbar, kopieren Sie ihn daher umgehend in Ihren geheimen Speicher.
Jede Zustellung enthält einen JSON-Body mit derselben Hülle:
{
"event": "documents.indexed",
"timestamp": "2026-07-23T09:14:07.000Z",
"tenantId": "0198f2a4-6c1e-7d30-b6a1-2f9d54c08a11",
"sequence": 42,
"data": { "count": 12 }
}Die Nutzlasten sind bewusst schlank gehalten: Es werden nur IDs, Zählungen und Zeitstempel übermittelt. Behandeln Sie einen Webhook als Signal, dass sich etwas geändert hat, und holen Sie sich anschließend den aktuellen Zustand über die authentifizierte API ab. Dokumentnamen und -inhalte erscheinen niemals in der Webhook-Nutzlast.
sequence ist ein pro Endpunkt gezählter Zähler, der für diesen Endpunkt dicht gepackt ist: Aufeinanderfolgende Ereignisse, die an diesen Endpunkt zugestellt werden, tragen aufeinanderfolgende Nummern. Eine fehlende Nummer bedeutet daher, dass eine Zustellung von Ihrem Dienst nicht empfangen wurde. Die Zustellreihenfolge ist nicht garantiert, nutzen Sie daher die Sequenz (nicht die Ankunftsreihenfolge), um Ereignisse zu ordnen. Zwei wichtige Hinweise: Wiedergaben werden absichtlich außer Reihenfolge zugestellt (ein aufgeholtes Ereignis behält seine ursprüngliche, ältere Sequenz), deduplizieren Sie daher anhand von webhook-id und verwerfen Sie eine Zustellung niemals nur, weil ihre Sequenz unter Ihrer Höchstmarke liegt. Zudem kann eine Lücke auch bedeuten, dass das fehlende Ereignis noch versucht wird oder sich in einem wiederherstellbaren Zustand befindet. Behandeln Sie Lücken daher als „Prüfen Sie das Zustellprotokoll“ und nicht als Beweis für einen Verlust.
Ereigniskatalog
Abonnieren Sie einen Endpunkt für jede Kombination der folgenden Ereignistypen. Typen, die als geplant markiert sind, können bereits ausgewählt werden, senden jedoch noch keine Ereignisse. Ihre Nutzlaststruktur ist noch nicht finalisiert und wird hier veröffentlicht, sobald das Ereignis live geht.
| Ereignis | Status | Nutzlast (data) |
|---|---|---|
documents.indexed | Live | Dokumente wurden durchsuchbar. Pro Workspace aggregiert: maximal ein Ereignis pro Aggregationsfenster mit einer Zählung. |
documents.failed | Live | Dokumente sind bei der Verarbeitung endgültig fehlgeschlagen. Pro Workspace aggregiert: maximal ein Ereignis pro Aggregationsfenster mit einer Zählung. |
sync.completed | Geplant | Ein Connector-Synchronisationslauf wurde abgeschlossen. Die Nutzlaststruktur ist noch nicht final. |
sync.failed | Geplant | Ein Connector-Synchronisationslauf ist fehlgeschlagen. Die Nutzlaststruktur ist noch nicht final. |
ingestion.completed | Geplant | Ein Ingestionslauf wurde abgeschlossen. Die Nutzlaststruktur ist noch nicht final. |
ingestion.failed | Geplant | Ein Ingestionslauf ist fehlgeschlagen. Die Nutzlaststruktur ist noch nicht final. |
endpoint.disabled | Live | Ein Webhook-Endpunkt wurde nach anhaltenden Zustellfehlern automatisch deaktiviert. Wird an die anderen Endpunkte des Workspace zugestellt. |
delivery.failing | Live | Zustellungen an einen Webhook-Endpunkt beginnen zu fehlschlagen: eine frühe Warnung zu Beginn des automatischen Deaktivierungs-Grace-Fensters, zugestellt an die anderen Endpunkte des Workspace. |
webhook.ping | Live | Gerichtete Testereignisse, die über die Aktion „Test senden“ im Dashboard an genau einen Endpunkt gesendet werden. Nicht abonnierbar; data ist stets leer. |
Beispiel-data-Objekte für die Live-Ereignisse:
// documents.indexed
{ "count": 12 }
// documents.failed
{ "count": 2 }
// endpoint.disabled
{
"endpointId": "0198f2a4-6c1e-7d30-b6a1-2f9d54c08a11",
"reason": "sustained_failure",
"disabledAt": "2026-07-23T09:14:07.000Z"
}
// delivery.failing
{
"endpointId": "0198f2a4-6c1e-7d30-b6a1-2f9d54c08a11",
"failingSince": "2026-07-23T09:14:07.000Z"
}
// webhook.ping
{}Die betrieblichen Ereignisse (endpoint.disabled, delivery.failing) berichten über den Zustand anderer Endpunkte: Der Endpunkt, auf den sich ein Ereignis bezieht, wird stets von der Zustellung dieses Ereignisses ausgeschlossen, da eine Zustellung dorthin garantiert Rauschen erzeugen würde.
Überprüfung von Zustellungen
Jede Zustellung ist gemäß der Standard-Webhooks-Spezifikation signiert. Verifizieren Sie stets die Signatur, bevor Sie einer Anfrage vertrauen: Ihre Endpunkt-URL ist für jeden im Internet erreichbar.
Jede Anfrage enthält drei Header:
| Header | Wert |
|---|---|
webhook-id | Eindeutige ID dieser Zustellung. Bleibt bei automatischen Wiederholungen derselben Zustellung identisch, fungiert also auch als Idempotenzschlüssel. |
webhook-timestamp | Unix-Zeitstempel in Sekunden zum Zeitpunkt des Sendens. |
webhook-signature | Eine oder mehrere Signaturen, durch Leerzeichen getrennt, jeweils im Format v1,{base64}. |
So verifizieren Sie:
- Rekonstruieren Sie den signierten Inhalt gemäß
{webhook-id}.{webhook-timestamp}.{raw body}. Verwenden Sie die Rohdaten des Anfragekörpers genau so, wie sie empfangen wurden, bevor eine JSON-Analyse erfolgt. - Berechnen Sie HMAC-SHA256 über diesen String. Der Schlüssel ist der base64-dekodierte Teil des Secrets nach dem Präfix
whsec_(die Standard-Webhooks-Schlüsselableitung, wie sie von den Referenzbibliotheken implementiert wird). - Kodieren Sie den HMAC base64 und vergleichen Sie ihn mit jeder
v1,-Signatur im Header unter Verwendung eines zeitkonstanten Vergleichs. Die Zustellung ist authentisch, wenn eine Übereinstimmung vorliegt. - Lehnen Sie Zustellungen ab, deren
webhook-timestampmehr als 5 Minuten von Ihrer aktuellen Zeit abweicht, in beide Richtungen. Dies begrenzt die Wiederholung erfasster Anfragen.
Der Header kann mehr als eine Signatur enthalten: Während eines Grace-Fensters für die Schlüsselrotation werden Zustellungen sowohl mit dem neuen als auch mit dem alten Secret signiert (v1,NEW_SIG v1,OLD_SIG), sodass die Verifizierung unabhängig davon erfolgreich ist, welches Secret Ihr Dienst gerade verwendet.
import { createHmac, timingSafeEqual } from "node:crypto";
const TOLERANCE_SECONDS = 5 * 60;
/**
* @param {string} secret - The whsec_ signing secret from endpoint creation.
* @param {Record<string, string>} headers - Lowercased request headers.
* @param {string} rawBody - The raw request body, unparsed.
*/
export function verifyWebhook(secret, headers, rawBody) {
const id = headers["webhook-id"];
const timestamp = headers["webhook-timestamp"];
const signatureHeader = headers["webhook-signature"];
if (!id || !timestamp || !signatureHeader) return false;
const skew = Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp));
if (!Number.isFinite(skew) || skew > TOLERANCE_SECONDS) return false;
const key = Buffer.from(secret.slice("whsec_".length), "base64");
const expected = createHmac("sha256", key)
.update(`${id}.${timestamp}.${rawBody}`)
.digest();
return signatureHeader.split(" ").some((entry) => {
const comma = entry.indexOf(",");
if (comma === -1 || entry.slice(0, comma) !== "v1") return false;
const received = Buffer.from(entry.slice(comma + 1), "base64");
return received.length === expected.length && timingSafeEqual(received, expected);
});
}Da das Format der Standard-Webhooks-Spezifikation entspricht, funktionieren quelloffene Verifizierungsbibliotheken für andere Sprachen unverändert. Übergeben Sie ihnen das Secret und die drei Header.
Wiederholungen und Fehler
Ihr Endpunkt hat 10 Sekunden Zeit für eine Antwort. Eine Antwort mit einem 2xx-Status gilt als zugestellt; alles andere – einschließlich Timeouts oder Weiterleitungen (Zustellungen folgen niemals Weiterleitungen) – gilt als Fehler und wird wiederholt. Antworten Sie mit 2xx, sobald Sie das Ereignis dauerhaft akzeptiert haben, und führen Sie die aufwendige Verarbeitung asynchron durch.
Eine fehlgeschlagene Zustellung wird nach folgendem Zeitplan wiederholt:
| Versuch | Verzögerung nach dem vorherigen Fehler |
|---|---|
| 1 | sofort |
| 2 | 5 Sekunden |
| 3 | 5 Minuten |
| 4 | 30 Minuten |
| 5 | 2 Stunden |
| 6 | 5 Stunden |
| 7 | 10 Stunden |
| 8 | 10 Stunden |
Es handelt sich um 8 Versuche über etwa 27,5 Stunden, sodass ein ganztägiger Ausfall Ihrerseits keine Ereignisse verliert. Jede Verzögerung enthält bis zu 20 % zufälliges Jitter in beide Richtungen, um synchronisierte Wiederholungsstöße gegen einen sich erholenden Endpunkt zu verhindern. Wenn Ihr Endpunkt den Header Retry-After zurückgibt, wird die angeforderte Verzögerung innerhalb der Grenzen eingehalten: Sie wird zwischen der geplanten Verzögerung und dem Doppelten der geplanten Verzögerung begrenzt. Antworten mit Status 429 und zeitüberschreitende Versuche werden frühestens nach 60 Sekunden erneut versucht, unabhängig davon, wie früh der geplante Slot liegt.
Automatische Deaktivierung
Ein Endpunkt, der weiterhin fehlschlägt, wird schließlich deaktiviert, anstatt dauerhaft belastet zu werden:
- Wenn Zustellungen beginnen fehlzuschlagen, wird einmal ein
delivery.failing-Ereignis ausgelöst (zugestellt an die anderen Endpunkte des Workspace) und eine In-App-Benachrichtigung erstellt. Dies ist die frühe Warnung. - Jede erfolgreiche Zustellung setzt das Fehlerfenster zurück.
- Nach 5 Tagen aufeinanderfolgender Fehler wird der Endpunkt deaktiviert: Ein
endpoint.disabled-Ereignis wird ausgelöst (wiederum an die anderen Endpunkte), und der Ersteller des Endpunkts erhält eine E-Mail.
Ein deaktivierter Endpunkt erhält keine weiteren Zustellungen, und seine Aktionen „Test senden“ sowie „Erneut senden“ sind blockiert. Sobald Ihr Empfänger wieder funktionsfähig ist, aktivieren Sie den Endpunkt in den Workspace-Einstellungen erneut (klicken Sie auf das Statusabzeichen): Durch das erneute Aktivieren wird die Fehlerhistorie gelöscht, sodass der Endpunkt ein neues 5-Tage-Fenster startet. Ereignisse, die eintreten, während ein Endpunkt deaktiviert ist, werden in seinem Zustellprotokoll mit dem Status „verworfen“ statt einer Zustellung erfasst. Nach dem erneuten Aktivieren verwenden Sie „Test senden“, um die erfolgreiche Zustellung zu bestätigen, und dann „Fehlgeschlagen + verworfen erneut senden“, um alles nachzuholen, was der Ausfall gekostet hat – in einer Aktion.
Manuelle Nachzustellung und Tests
Das Zustellprotokoll in den Workspace-Einstellungen zeigt jeden Zustellversuch mit seinem Statuscode und der Antwort an. Dort können Sie:
- Erneut senden: Zustellt die ursprüngliche Nutzlast einer vergangenen Zustellung bytegenau als einzelnen Versuch erneut. Dies wird nicht im Wiederholungsplan berücksichtigt und zählt niemals zur automatischen Deaktivierung, sodass es sich gefahrlos zum Debuggen eines instabilen Empfängers verwenden lässt. Das erneute Senden ist eine neue Zustellung mit einer neuen
webhook-id. - Fehlgeschlagen + verworfen erneut senden: Führt eine Massenwiedergabe aller endgültig fehlgeschlagenen und verworfenen Zustellungen dieses Endpunkts durch, beginnend mit den ältesten (Zustellungen, die sich noch im automatischen Wiederholungsplan befinden, werden ausgeschlossen, sodass eine Wiedergabe niemals eine Wiederholung duplizieren kann, die ohnehin erfolgreich gewesen wäre). Wiedergaben verwenden den vollständigen Wiederholungsplan und enthalten die ursprüngliche
webhook-id: Für Ihren Dienst ist eine Wiedergabe dieselbe Nachricht wie zuvor, sodass die Idempotenzbehandlung anhand vonwebhook-iddie Nachholung sicher macht – unabhängig davon, ob das ursprüngliche Ereignis jemals angekommen ist. Große Bereiche werden in begrenzten Chargen verarbeitet: Falls noch mehr verbleiben, führen Sie den Vorgang erneut aus, und er setzt genau dort fort, wo er aufgehört hat. Wiedergaben kommen außer Reihenfolge an; ordnen Sie die nachgeholten Ereignisse anhand der Sequenzsequenceim Nutzdatenobjekt. - Test senden: Zustellt ein signiertes
webhook.ping-Ereignis mit einem leerendata-Objekt genau an diesen Endpunkt – unabhängig von seinen Ereignisabonnements. Verwenden Sie dies, um die Erreichbarkeit zu bestätigen und Ihre Signaturverifizierung vollständig zu testen.
Best Practices
- Deduplizieren Sie anhand von
webhook-id. Automatische Wiederholungen verwenden dieselbe ID, sodass das Speichern verarbeiteter IDs Ihnen genau-einmal-Verarbeitung zusätzlich zur mindestens-einmal-Zustellung bietet. - Behandeln Sie die Nutzlast niemals als aktuellen Zustand. Nutzlasten sind schlank und können verspätet eintreffen; nutzen Sie das Ereignis als Auslöser und lesen Sie den aktuellen Zustand über die API ab.
- Verlassen Sie sich nicht auf die Reihenfolge. Wiederholungen und parallele Zustellungen können dazu führen, dass Ereignisse außer Reihenfolge eintreffen.
- Antworten Sie mit 2xx vor aufwendiger Arbeit. Stellen Sie das Ereignis in eine Warteschlange und verarbeiten Sie es asynchron. Ein Handler, der die Arbeit inline durchführt, riskiert, das 10-Sekunden-Zeitlimit zu erreichen und wiederholt zu werden – aus einem Ereignis werden so mehrere doppelte Versuche.
- Rotieren Sie Secrets mit einem Grace-Fenster. Die Rotation in den Workspace-Einstellungen hält das vorherige Secret für ein von Ihnen gewähltes Fenster gültig, und währenddessen werden Zustellungen mit beiden Secrets signiert, sodass ein Rolling Deploy Ihrer Dienste niemals eine Zustellung verliert.