Was triggert einen Webhook

  • story.published — Publish-Button oder Scheduled-Publish gefeuert.

  • story.unpublished — Story offline genommen.

  • story.deleted — Soft-Delete über Admin oder API.

  • story.moved — Slug geändert (Ordner-Move, Rename).

payload.json
{
  "action": "story.published",
  "space_id": 1,
  "story_id": 42,
  "full_slug": "blog/first-post",
  "uuid": "c3c7e0f3-...",
  "delivery_id": "whd_01HZ...",
  "timestamp": "2026-04-23T14:11:02.500Z"
}
Beispiel-Payload für story.published.
POST/api/v1/spaces/{spaceId}/webhooksBearer (Mgmt)

Neuen Webhook-Endpoint registrieren.

Request
POST /api/v1/spaces/1/webhooks
Authorization: Bearer sbmgmt_...

{
  "name": "Vercel rebuild",
  "url": "https://api.vercel.com/v1/deploy-hooks/abc",
  "events": ["story.published", "story.unpublished"],
  "secret": "<opaque, used for signature>"
}

Signatur & Retries

Jeder Request trägt X-Webhook-Signature — HMAC-SHA256 über den Raw-Body mit dem Webhook-Secret. Vor dem Auswerten eines Feldes verifizieren. Failed Deliveries (non-2xx oder Timeout nach 10 s) werden mit Exponential-Backoff bis zu 5-mal wiederholt; danach landet die Delivery als Dead-Letter im Audit-Log.

verify.ts
import { createHmac, timingSafeEqual } from 'node:crypto'

export function verify(rawBody: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha256', secret).update(rawBody).digest('hex')
  const a = Buffer.from(expected, 'hex')
  const b = Buffer.from(signature, 'hex')
  return a.length === b.length && timingSafeEqual(a, b)
}
Signatur in Node / Bun verifizieren.