Webhooks
Orbit webhooks deliver real-time HTTP POST notifications to your server whenever events occur — message delivered, call completed, agent conversation ended, and more. Use webhooks to keep your systems in sync without polling. This page is the hub for everything webhook-related. It covers setup (dashboard and API), the delivery envelope, signature headers, retries, and the dead-letter queue. Two sibling pages carry the deep detail:- Build your first webhook receiver — end-to-end walkthrough: stand up a receiver, verify the signature, dedup, and handle retries
- Webhook events — the canonical catalog of every event type you can subscribe to
- Normalized inbound event envelope — the carrier-agnostic
data.normalizedblock, the unifiednormalized.inboundshare subscription, and the inbound-events catalog endpoint - Webhook security — signature verification with copy-paste verifiers for Node.js, Python, and Go
- Inspecting deliveries and replaying failures — watch every delivery across your endpoints, inspect a single attempt, and replay failures
How It Works
- You register a webhook endpoint URL in the Orbit dashboard or via the API
- When an event occurs, Orbit sends an HTTP POST with the event payload to your URL
- Your server responds with a
2xxstatus code to acknowledge receipt - If delivery fails, Orbit retries on a fixed schedule (see Retry Schedule)
Set Up a Webhook in the Dashboard
The fastest way to register an endpoint — no API call required:- Open Settings → Webhooks → Add endpoint
- Enter your HTTPS URL (plain HTTP is rejected for production endpoints)
- Pick the event types you want to receive, or subscribe to
*for everything - Copy the signing secret (
whsec_...) shown after creation — this is the only time the cleartext secret is displayed, and you need it to verify signatures
Register a Webhook via the API
secret to have Orbit auto-generate one. Either way, the response includes the full whsec_... cleartext — copy it immediately. If you supply your own, it must be at least 16 characters.
Event Payload Format
Every webhook delivery follows a consistent envelope:message.failed) additionally include optional error_code and error_message fields carrying the provider’s failure reason. They appear only when the message has a captured provider error and are absent otherwise. See the webhook events reference for the full per-event payload shapes.
Signature Headers
Every delivery is signed with HMAC-SHA256 so you can confirm it genuinely came from Orbit. Each request carries the signature in up to three headers:
All three share the same Stripe-style encoding —
t=<unix>,v1=<hex> — where t is a Unix timestamp for replay protection and v1 is the HMAC-SHA256 hex digest of <t>.<raw_body> keyed by your signing secret. Verify at least one of them before processing any delivery. Full verification logic and ready-to-use code for Node.js, Python, and Go: Webhook security.
Event Families
The catalog spans every Orbit pillar — a few common families to start with:
Subscribe to only the events you need, or pass
["*"] to receive everything. The full catalog of 256 event types (contacts, campaigns, agents, numbers, billing, and more): Webhook events.
Delivery Guarantees
- At-least-once delivery — events may be delivered more than once; use the
idfield for deduplication - Ordered by event time — events are sent in chronological order, but network conditions can cause out-of-order delivery
- 30-second timeout — your endpoint must respond within 30 seconds
Idempotency
Because delivery is at-least-once, a retry or a dead-letter replay can deliver the same event again. Deduplicate on the envelopeid field (evt_...): persist every event id you have processed and drop deliveries whose id you have already seen. Persist seen ids for at least 7 days — long enough to cover the full retry window plus the dead-letter replay window described below.
Retry Schedule and Dead-Letter Queue
If your endpoint returns a non-2xx response or times out, Orbit retries on an exponential backoff schedule. Each event gets one initial delivery plus 9 retries (10 attempts total). The backoff starts at 30 seconds and doubles with each retry, with +0–20% jitter applied (delays run up to 20% longer than nominal, never shorter):- Attempt 1: initial delivery (0s delay)
- Attempts 2–10: exponential backoff (30s → 60s → 120s → 240s → 480s → 960s → 1920s → 3840s → 7680s)
2xx within 30 seconds. Timeouts and 5xx responses always retry. Retryable 4xx responses (400/422 and similar) also retry until the backoff schedule is exhausted. A proven-dead response — 401, 403, 404, or 410 Gone — skips retries entirely, moves to the dead-letter queue, and immediately disables the endpoint (Orbit notifies the org admin). 410 Gone is also the way to permanently skip retries for a single event — for example when you have deprecated handling for that event type.
Auto-disable on failure streaks: Orbit tracks consecutive failures per endpoint and auto-disables one that exceeds 50 — the same mechanism that fires instantly on the proven-dead statuses above. Re-enable a disabled endpoint from the dashboard once it is healthy again. While an endpoint is disabled, deliveries do not keep retrying in the background.
If an endpoint accumulates 50 consecutive failures, Orbit auto-disables it and emails the org admin. Re-enable it from the dashboard once your endpoint is healthy again. Deliveries to a disabled endpoint go straight to the dead-letter queue rather than retrying.
Managing Webhooks
List your registered webhooks:Next Steps
- Build your first webhook receiver — start-to-finish receiver walkthrough with working Node and Python code
- Event Types — full catalog of available events
- Event Payloads — per-event payload walkthroughs
- Normalized inbound event envelope — one
kinddiscriminator and one unified subscription across the whole inbound family - Inspecting deliveries and replaying failures — event explorer, delivery inspector, and manual replay
- Security — signature verification with code examples
- Troubleshooting signature failures — fix common verification issues