Skip to main content
RevDesk POSTs an event to your URL whenever something happens in your workspace: a call ends, an SMS is delivered, a number is provisioned. Subscribe once per event type; we deliver as the events occur.

Subscribe

Unsubscribe

Event types

call_completed fires on every call end. The disposition events below fire in addition, only on the matching outcome. Subscribe to them to branch (retry, SMS fallback) without parsing call records. Answered/successful calls emit no disposition event.

Delivery

Each event is a POST with a JSON body to your webhook_url. Delivery is fire-and-forget; return a 2xx quickly and do any heavy work asynchronously. Subscribe to the same event type multiple times to fan out to multiple URLs.
Two delivery shapes. Call-disposition, SMS, and job events are delivered flat (the event object is the request body). Number-lifecycle events are delivered enveloped (triggerEvent / createdAt / payload). Both shapes are signed. Match the shape to the event family you subscribed to (see the examples below), but verify the signature the same way for all of them.Flat deliveries carry no event-name field. Branch on the payload instead: call and SMS events on status, job events on status plus the fields unique to each (job_progressed carries rationale, job_outcome_recorded carries outcome).

Signature verification (all events)

Every subscription has a signing secret (generated at creation, shown once; rotate it to get a new one). Every delivery carries three headers: Signing over {eventId}.{timestamp}.{rawBody} rather than the body alone is what makes a captured request non-replayable. Both moving parts are inside the signature: the timestamp can’t be moved forward, and the event id can’t be swapped. That second property is what lets you dedupe safely. If the id weren’t signed, anyone who captured one delivery could resend it with a fresh id inside the tolerance window and your dedupe would wave it through as a new event.
Verify first, then dedupe on X-RevDesk-Event-Id (e.g. a short-lived set or a unique column) so a retried delivery is processed at most once. The order matters: the id only means something once the signature covering it has checked out.
Legacy header (deprecated). Older integrations verified an X-revdesk-Signature-256 / X-RevDesk-Signature-256 header, a bare HMAC of the body with no timestamp. It still ships alongside the new headers during a deprecation window but offers no replay protection at all; migrate to the X-RevDesk-Signature verifier above.v1= signatures are retired. A short-lived earlier version of X-RevDesk-Signature signed {timestamp}.{rawBody}, leaving the event id unauthenticated. It is no longer sent. If your verifier filters for the v1= prefix, switch it to v2= and add the event id to the signed string as shown above.

Rotating a signing secret

Rotate from the dashboard or the API to get a fresh secret (shown once). For a grace period RevDesk signs each delivery with both the new and previous secret, so you can deploy the new secret without dropping in-flight events; once your consumers use the new secret, the old one stops signing.

Payload examples

Call disposition (call_no_answer, call_voicemail, call_busy, call_failed) — flat (signed like every event):
Outbound SMS (sms_sent, sms_delivered, sms_failed) — flat (signed like every event):
Job progress (job_started, job_progressed, job_outcome_recorded, job_completed) — flat (signed like every event). Every job event carries the five base fields; job_progressed adds the action and the reasoning behind it:
Number lifecycle (number_purchased, number_released, number_updated) — enveloped. The event data is nested under payload, and triggerEvent is the internal event name (number.purchased / number.released / number.updated):
number.updated additionally carries changed_fields — the snake_case names of the settings the update touched (e.g. ["cnam_display_name", "agent_id"]). Signed like every other event: verify X-RevDesk-Signature with the verifier above. Only the body shape differs.