Developer Docs
Sandbox · API v2PlaygroundGet API keys

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.

product.createdproduct.updatedproduct.deletedproduct.published compliance.verifiedcompliance.violation_createdpassport.anchored scan.recordedimport.completedimport.failed carrier.generatedprint.confirmedprint.failed

Envelope

External events use the platform envelope, the WebhookEvent value object. Field names are exactly these; there is no Stripe-style created/livemode/data.object nesting:

JSON
{ "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) plus X-Norruva-Timestamp and X-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.
  • Delivery durability varies by event type: print.confirmed, print.failed, and carrier.generated ride the durable outbox → event bus → dispatch path, with a persisted delivery record and retry cron backing the signature/replay/dedup/retry guarantees above. product.created, product.updated, product.published, import.completed, and import.failed are emitted best-effort (non-outbox), if the emitting process fails between the domain action and dispatch, the webhook is simply not sent, with no queued retry of the emission itself. A durable-emission upgrade for these types is tracked as a follow-up.
One gap to know. There is no local end-to-end receiver harness yet (signing/retry are unit-verified). Secret rotation IS available, POST /webhooks/{id}/rotate-secret with a 24 h overlap window. See the receiver guide.
Was this page helpful?
Thanks, noted.Feedback goes to the docs team by email.