# Webhooks

> Andere Systeme bei Veröffentlichungen, Änderungsanfragen und fertigen Builds benachrichtigen – mit signierten Aufrufen.

Webhooks rufen eine Adresse deiner Wahl auf, sobald in Docsello etwas passiert – zum Beispiel, um einen Slack-Kanal zu
benachrichtigen, einen Such-Index neu aufzubauen oder eine Übersetzung anzustoßen. Du verwaltest sie unter
**API & Tokens**, Abschnitt **Webhooks**.

## Webhook anlegen

Die **URL** eintragen, die gewünschten Ereignisse ankreuzen und **Webhook hinzufügen** klicken. Die URL muss öffentlich
erreichbar sein.

| Ereignis | Wann |
|---|---|
| `page.published` | Eine Seite wurde veröffentlicht |
| `page.deleted` | Eine Seite (samt Unterseiten) wurde in den Papierkorb verschoben |
| `space.created` | Ein Bereich wurde angelegt |
| `space.updated` | Ein Bereich wurde geändert |
| `change_request.opened` | Eine Änderungsanfrage wurde eingereicht |
| `change_request.merged` | Eine Änderungsanfrage wurde übernommen und veröffentlicht |
| `site.built` | Die Website wurde neu generiert |

Bei jedem Webhook zeigt Docsello den HTTP-Status der letzten Zustellung und unter **Secret** das Geheimnis zum Prüfen
der Signatur. **Löschen** entfernt den Webhook.

## Aufruf

Docsello schickt einen `POST` mit JSON:

```json
{
  "event": "page.published",
  "workspace": { "id": "…", "slug": "acme" },
  "data": {
    "page": { "id": "…", "path": "zahlungen/stripe", "title": "Stripe", "locale": "de" },
    "space": { "id": "…", "slug": "handbuch" },
    "revisionId": "…",
    "message": "Neue Gebühren"
  },
  "sentAt": "2026-10-02T12:00:00.000Z"
}
```

Die Header `X-Docsello-Event` (Name des Ereignisses) und `X-Docsello-Signature` kommen dazu. Antwortet deine Adresse
nicht mit einem 2xx-Status (oder nicht innerhalb von 10 Sekunden), versucht Docsello es später erneut.

## Signatur prüfen

`X-Docsello-Signature` hat die Form `sha256=<hex>` – ein HMAC-SHA256 über den unveränderten Body mit dem Secret des
Webhooks:

```js
import { createHmac, timingSafeEqual } from "node:crypto";

function isFromDocsello(rawBody, header, secret) {
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  return header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}
```

Prüfe immer den rohen Body, bevor du ihn als JSON einliest.
