Webhooks
Webhooks feuern HTTP-POSTs an konfigurierte URLs, sobald Content commitet oder gelöscht wird — typisch für Search-Index-Updates, Slack-Notifications, CDN-Cache-Invalidation oder Sync zu Downstream-Systemen.
Verfügbarkeit
Webhooks sind eine Pro- und Enterprise-Funktion.
Free-Lizenzen sehen die Verwaltung im Admin, können sie aber nicht editieren — der
bestehende deployHook aus der Astro-Integration bleibt für alle
Tarife verfügbar.
Konfiguration
Im Admin: ⚙ Settings → Webhooks. Pro Webhook konfigurierbar:
Name, URL, Events, optionales HMAC-Secret. Liste wird im
_webhooks.json im Content-Repo (Single-Mode) bzw. pro Website-Repo
(Multi-Mode) gespeichert.
Events
content.save— nach jedem erfolgreichen Section/Page-Commitcontent.delete— nach Löschen einer Sectioncontent.publish— reserviert für künftige Staging-Branches (v2.x)
Payload
{
"event": "content.save",
"timestamp": "2026-05-08T12:34:56.789Z",
"website": {
"id": "kunde-a",
"repo": "kunde-a/website",
"branch": "main"
},
"user": {
"email": "redaktion@example.com",
"name": "Maria Schmidt"
},
"commit": {
"sha": "abc123…",
"message": "content(hero): heading aktualisiert"
},
"files": [
{ "path": "content/_sections/hero.json" }
]
} Headers
Setzkasten sendet vier Header. Die Signatur ist nur gesetzt, wenn ein Secret konfiguriert ist.
Content-Type: application/json
X-Setzkasten-Event: content.save
X-Setzkasten-Delivery: 9c3f8a4d-1e2b-4f6a-9b7d-1234567890ab
X-Setzkasten-Signature: sha256=<64 chars hex> Signatur verifizieren
HMAC-SHA256 über den UTF-8-Body, hex-encoded. Empfänger sollten den rohen Request-Body nutzen — JSON-Re-Stringify-Ergebnisse weichen ab und schlagen fehl. Pattern entspricht GitHub-Webhooks.
import { createHmac, timingSafeEqual } from 'node:crypto'
export function verify(req, secret) {
const sigHeader = req.headers['x-setzkasten-signature']
if (!sigHeader?.startsWith('sha256=')) return false
const expected = sigHeader.slice('sha256='.length)
const computed = createHmac('sha256', secret)
.update(req.rawBody, 'utf8')
.digest('hex')
return timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(computed, 'hex'),
)
} import hmac
import hashlib
def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
if not signature_header.startswith("sha256="):
return False
expected = signature_header[len("sha256="):]
computed = hmac.new(
secret.encode("utf-8"),
raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, computed) Idempotenz
Setzkasten retryt aktuell nicht. Empfänger sollten dennoch
X-Setzkasten-Delivery als idempotency-key behandeln — falls
eine künftige Version Retry nachzieht, ist das Empfänger-System dann
schon korrekt.
Test-Fire
Im Admin per Klick auf das Pfeil-Icon: schickt einen synthetischen Payload
(commit.sha = 0…0, leere files-Liste,
zusätzlich X-Setzkasten-Test: true). Empfänger können diese
Test-Fires auswerten oder ignorieren.
Timeout & Fehler
Pro Hook 5 Sekunden Timeout (10 s im Test-Fire). Schlägt der Request fehl, loggt der Server-Output den Fehler; der Save-Vorgang im Admin bleibt unbeeinflusst — Webhooks sind fire-and-forget.
Backwards-Compat: deployHook
Die ältere deployHook-Option in astro.config.mjs
bleibt als 1-URL-Variante bestehen — feuert nach jedem Save mit leerem
POST. Wer mehr braucht (mehrere Endpoints, Events trennen, Payload),
nutzt die hier beschriebenen Webhooks.