Subscribe to events
Register webhook endpoints at/(dashboard)/settings/integrations/webhooks. Each subscription
carries:
target_url: your HTTPS endpoint. Vorel POSTs the envelope here.secret: auto-generated; used as the HMAC key. Surfaced once at create time, after that only the prefix is visible (rotate by recreating).- Subscribed event list: pick the subset you want; ignore the rest.
The 19 event types
Call events carry deterministic envelope ids, so an at-least-once carrier callback cannot produce
two distinct events for the same call transition. Deduplicate on the envelope
id as you would
for any other event.conversation.created fires today only on the public-API write path (POST /v1/conversations). Internal ingest paths (inbound WhatsApp, inbound voice, webform handler)
don’t emit it yet. Adding emission there has wider blast radius (every existing customer message
would suddenly produce a webhook). When that lands, the emission point is the conversation-row
insert in the inbound message handlers; the enum already covers it.Envelope shape
Every webhook body is a JSON object of this shape:idis a unique event id, formattedevt_<uuid>. Use it as your idempotency key. Vorel’s retry ladder may redeliver the same event up to 6 times; a 5xx that succeeded server-side but failed at the network layer will replay. Idempotent processing onidis non-negotiable.event: one of the 19 names above.created_at: ISO 8601 UTC.tenant_id: the tenant whose data triggered the event. Useful when one URL receives events for multiple tenants (or for sanity-checking).data: event-specific payload. Shapes are documented per-event (TODO: per-event payload schemas live in the OpenAPI spec at the corresponding resource).
Signature verification
Every delivery carries these headers (sent lowercase; HTTP header names are case-insensitive, so match accordingly):x-event-type and x-delivery-id headers are conveniences; the authoritative event name and
event id live in the envelope body (event + id). Verify the signature before trusting the
payload:
Retry ladder
Total retry window: ~14h 35min from first attempt to dead-letter.
The classifier rules:
- 2xx response →
delivered. Terminal.delivered_atrecorded. - 4xx response →
permanent_fail. Terminal. No retry: a 4xx means we built a request the consumer rejected, and replaying it won’t change that. - 5xx response, timeout, or network error → retry per the ladder if budget remains; else
dead_letter.
Dead-letter handling
When a delivery exhausts the 6-attempt ladder:- The row’s
statusflips todead_letter. - The
response_bodycarries the last error text (truncated). - A tenant-admin alert fires (error-reporting capture + dashboard surface).
Recommended consumer behaviour
- Idempotency on
idis a contract, not a suggestion. We will redeliver under transient failure. - Verify before parsing. Tampered bodies must return 4xx + we won’t retry them.
- Ack fast. 5xx triggers a retry; 4xx triggers
permanent_fail. If your processing is slow, enqueue and ack; don’t make Vorel wait.
Before you build on a webhook
Check whether a trigger rule already covers it. The trigger engine consumes the same events and can assign, prioritise, label or call without you hosting anything. Webhooks are the right choice when the action belongs in your systems. Triggers are the right choice when the action belongs in Vorel.What’s NOT supported today
- Replay individual deliveries via API. Operator-only via the dashboard.
- Multi-event filters per subscription beyond the event-name set. No “deliver lead.created
only when
attributes.budget_max > 5_000_000” today; filter consumer-side. offering.deleted: there’s no DELETE-offering API path; soft-delete happens via the operator dashboard. The event will be added in lockstep when the tenant-side delete surface lands.- Per-event payload schemas in this docs site. Documented in the OpenAPI spec per-resource for now; a dedicated payload page is roadmap.
Related docs
- API introduction: surface overview
- Rate limits: outbound webhook delivery is itself rate-limited
- Triggers: act on the same events inside Vorel
- How it works: where webhook emission fits
