Webhooks & events
Subscribe to events instead of polling. A Webhook is a tenant-scoped endpoint + subscribed event set + signing secret; a Delivery is a signed, replay-protected, retried attempt to reach it.
Event catalogue
Subscribe only to catalogue events (the dispatcher’s WEBHOOK_EVENT_TYPES — nothing else is ever delivered); an unknown name returns 422 UNKNOWN_EVENT_TYPE. The AutoID print-cycle trio closes the print loop event-driven: carrier.generated ("codes ready — pull carriers/export"), then print.confirmed / print.failed fan out the print layer's POST /carriers/print-status reports (one aggregate event per outcome class with the serial list) — full walkthrough in AutoID print loop.
Types marked reserved are subscribable but do not fire yet — no platform code path emits them today. All other types are live.
Envelope
External events use the platform envelope — the WebhookEvent value object (PRD F9). Field names are exactly these; there is no Stripe-style created/livemode/data.object nesting:
{ "id": "<uuid>", "type": "product.published",
"timestamp": "2026-07-20T12:00:00.000Z", "apiVersion": "2024-12-05",
"data": { /* event-specific fields */ } }Delivery contract
- Signatures:
X-Norruva-Signature(V1) plusX-Norruva-TimestampandX-Norruva-Signature-V2(timestamped HMAC). - Replay window: 5 minutes — a stale timestamp is rejected.
- Dedup: the delivery id is stable across retries; use it for receiver-side idempotency.
- Retries:
4xx→ no retry;5xx/timeout → backoff retries. Manual redelivery is available.
POST /webhooks/{id}/rotate-secret with a 24 h overlap window. See the receiver guide.