Webhook subscription lifecycle
A webhook subscription is one row — a(destination URL, events filter) pair — that moves through a lifecycle: registered → active → (on sustained failure or proven-dead response) disabled → re-enabled. This page walks that loop from the operator’s seat: what happens at each state, where to watch it, and the exact re-enable flow when a subscription has been taken out. Fill-in details that live on sibling pages are linked, not repeated — per-attempt wire semantics sit in Webhook delivery semantics and the one-event-to-many-destinations topology sits in Webhook fan-out and event sinks.
1. Register a subscription — scope, events, destination
A subscription is created either in the dashboard (Settings → Webhooks → Add endpoint) or by API (POST /api/v1/webhooks). Three fields set its contract:
url— the HTTPS destination Orbit POSTs every matching event to. Production endpoints require HTTPS, and the URL is validated to block requests to internal addresses.events— the filter for what this subscription receives: exact types (message.delivered), prefix globs (message.*), or*for everything. The filter is tenant-scoped and evaluated at fan-out time — a subscription never sees a non-matching event.secret— your signing secret. Omit it and Orbit auto-generates one; the response returns thewhsec_...cleartext exactly once.
description, custom headers, a per-endpoint timeout_seconds (1–30s), a transform config, or an agent scope can pin the subscription further — all are partial-update fields on PATCH /api/v1/webhooks/{id}.
2. Signing — the secret and its rotation
Every delivery is signed HMAC-SHA256 with your subscription’s secret; the signature lands inX-Orbit-Signature (canonical) as t=<unix>,v1=<hex> over <t>.<raw_body>. Verify before you process — a failed check must drop the delivery before your handler runs, or spoofed payloads pollute your dedup set. Copy-paste verifiers for Node.js, Python, and Go: Webhook security.
Rotation is a first-class lifecycle event, not a recreate. When you rotate the secret, Orbit opens a dual-signing grace window: new deliveries carry the new-secret signature and the previous-secret signature side-by-side (X-Orbit-Signature-Next), so your verifier keeps validating while you deploy the new key. The API exposes the full rotation loop as first-class calls — POST /api/v1/webhooks/{id}/rotate-secret, /rotation/initiate, /rotation/complete, and /rotation/cancel — so you can script it. Body-hash verification logic, the legacy X-Devotel-Signature back-compat header, and common verification failures are covered in Webhook security and Troubleshooting signature failures.
3. Delivery attempt grid — initial attempt vs. retry ladder
Each event against your subscription is delivered on a fixed grid: one initial attempt plus 9 retries, 10 attempts total, on an exponential backoff starting at 30 seconds and doubling each round with +0–20% jitter. Any2xx within 30 seconds (or within your per-endpoint timeout_seconds, if set below the platform 30s ceiling) is a success; everything else schedules a retry. If all 10 attempts fail, the event moves to your subscription’s dead-letter queue roughly 4.3 hours after the first attempt at nominal delays.
A failed-delivery timeline (endpoint returning 503 every attempt, no jitter):
The per-attempt contract — ordering, idempotency windows on both directions, and the two re-delivery causes — is the full subject of Webhook delivery semantics; this page deliberately does not restate it.
4. Failure classification — what each response means
Orbit classifies your endpoint’s response into buckets, and each bucket drives a different next step:410 Gone doubles as the deliberate single-event skip: return it for an event type you have deprecated and you route that event straight to the dead-letter queue without retrying the ladder. Reserved response codes that mean “we will never succeed here” (401/403/404/410) are documented with the retry contract in Webhook delivery semantics.
5. Circuit-breaker: when Orbit stops delivering
Orbit runs a per-subscription circuit breaker over consecutive failures. Two triggers stop delivery:- Proven-dead response — the first
401/403/404/410fires instantly (one failure, not a streak). - ~50 consecutive retryable failures — a sustained failure streak on otherwise-ordinary responses.
PATCH /api/v1/webhooks/{id} with active: false, an explicit operator-driven deactivation that uses the same neutral “no deliveries” state but is your decision rather than Orbit’s.)
6. Re-enable: the operator loop
The fix → confirm → re-enable loop is three steps. Never skip step 1 — a re-enabled subscription that immediately fails again starts a new consecutive-failure streak.- Fix the root cause on your side. Confirm your receiver returns
2xxwithin the timeout for a representative event; check TLS validity if you suspect it; fix auth if the disable was a proven-dead response. - Probe with a test fire. Fire a synthetic event against the subscription and confirm a clean
2xxround-trip:POST /api/v1/webhooks/{id}/test(or/test-fire) — no production traffic yet. - Re-enable the subscription. In the dashboard (Settings → Webhooks) toggle the endpoint back to active, or call
PATCH /api/v1/webhooks/{id}withactive: true:
7. Event catalogue discovery
You do not subscribe to a fixed enumerated list — you discover the catalogue. Three surfaces carry it depending on what you are doing:- While picking events in the dashboard — the event picker on Settings → Webhooks → Add endpoint enumerates families (
message.*,call.*,flow.execution.*,verification.*,email.*, and the rest) with names. - While integrating —
GET /api/v1/webhooks/eventsreturns the canonical event catalogue programmatically, the same source the picker reads. - While reading docs — Webhook events is the rendered catalogue, with payload shapes per event and per-family grouping; the events reference holds it as a flat list.
* receives everything; a prefix glob (message.*) receives the family; an exact type receives only that type. Subscribing a name not in the catalogue returns 422 — typo’d names cannot silently persist.
Where this fits
This page is the operator loop for ONE subscription; two sibling concept pages carry the model one level down and one level up:- Webhook delivery semantics — the per-attempt retry contract, ordering, both idempotency windows, and the dead-letter queue
- Webhook fan-out and event sinks — the one-event-to-many-destinations topology a single subscription sits inside
- Webhooks overview — endpoint setup, envelope shape, signature headers
- Webhook security — HMAC verification, rotation windows, copy-paste verifiers
- Event Sinks API — a sink destination as an alternative to per-endpoint HTTP