Webhooks
Signature verification (V1 JWT / V3 HMAC) and event catalog, as published on developer.ringover.com
Ringover calls a URL you configure in the Dashboard (Developer → Webhooks) whenever an event occurs. There is no POST /webhooks management API documented on the public site — configuration is dashboard-only.
This differs from the local OpenAPI text
The OpenAPI file behind this site's API Reference describes a raw shared-secret check (« Authorization header must equal the webhook key »). The published docs at developer.ringover.com describe a different, more precise scheme (JWT / HMAC, detailed below). Trust the published docs below for real integrations.
Securing your webhooks (signature verification)
Every call event is signed with your webhook key (shown on the webhook configuration page of the Ringover Dashboard). Two signature versions exist — verify whichever your team is configured for. The raw webhook key is never sent as-is in a header; comparing a header to the key directly is not a valid check for these events.
V1 — current default (JWT, Authorization deprecated)
The event is sent as a JWT signed with HS512, using your webhook key as the HMAC secret. The signed content is the concatenation of the webhook URL and the JSON payload. The same JWT is sent in two headers:
X-Ringover-Webhook-Signature— use this one.Authorization— kept for backward compatibility only, deprecated, do not rely on it for new integrations.
Verify with any JWT library: verify(token, webhookKey, { algorithms: ["HS512"] }). The decoded JWT exposes url (your configured endpoint) and payload (the event body: resource, event, timestamp, data, attempt).
V3 — recommended (HMAC-SHA256, fixed size)
Enabled on request today; will become the default for newly activated webhooks. Unlike V1's JWT (which grows with payload size — an issue for large events like transcriptions), V3 keeps a fixed-size signature.
Signature: Base64( HMAC-SHA256(webhook_key, messageToSign) ), where messageToSign concatenates, in order, the HTTP method (POST), and other fields described in the dashboard's webhook configuration page.
Headers:
X-Ringover-Webhook-Signature-V3— the Base64 signature.X-Ringover-Request-Signature-V3-Timestamp— the timestamp used to buildmessageToSign.
Verify by recomputing the HMAC and comparing with a constant-time check. Optionally reject requests whose timestamp is too old (replay protection).
Legacy ivr_id offset
The ivr_id in webhook response bodies is offset by 10000 for legacy reasons (an ivr_id 22000 in the dashboard is returned as 12000).
Per-event authentication (exceptions to V1/V3)
A few events use a different scheme instead of the general V1/V3 pair above:
| Event | Header | Rule |
|---|---|---|
message_event | Authorization | Must be a base64-encoded webhook key |
contact_search_event | Authorization | Must equal the webhook key (raw, no encoding) |
contact_event | x-ringover-webhook-signature | JWT signed HS512 with the key from the "Contact Call" section |
smart_routing_event | x-ringover-webhook-signature | JWT signed HS512 with the key from the IVR redirection-step config |
ivr_response_code | — | Not signed at all. No signature header is sent. Do not rely on any header to authenticate this one — restrict your endpoint by other means (secret URL path, IP allowlist) if needed. |
All other events (call_ringing, call_answered, call_hangup, call_missed, call_voicemail, comment_updated, tag_updated, record_available, voicemail_available, transcription_available, summary_available, empower) follow the general V1/V3 scheme above.
Event catalog
The published docs list 17 webhook events under the webhook tag:
| Event | Notes |
|---|---|
| Call ringing | Incoming call |
| Call answered | |
| Call hangup | Call terminated |
| Call missed | |
| Call voicemail | New voicemail |
| Voicemail available | |
| Record available | |
| Transcription available | |
| Summary available | For Ringover (non-Empower) users |
| Empower event | For Empower users — summary + transcript together in one payload |
| Comment updated | |
| Tag updated | |
| Contact event | Notes shown next to caller info during a call |
| Contact Search event | Triggered by a search in the dialer/contacts UI |
| Message event | SMS/chat sent or received |
| Smart routing event | Requires your response within 2 seconds — used for real-time call routing |
| IVR response event | "Ask for a code" IVR scenario; not signed (see above) |
Smart routing and IVR response — real-time
Both smart_routing_event and ivr_response_code expect your endpoint to answer synchronously and influence call handling. Read each operation's request/response schema carefully in the API Reference or on developer.ringover.com.
Verifying V1 (Node.js example)
const jwt = require('jsonwebtoken');
function verifyV1(token, webhookKey) {
// decoded.payload = { resource, event, timestamp, data, attempt }
// decoded.url = your configured endpoint
return jwt.verify(token, webhookKey, { algorithms: ['HS512'] });
}Verifying V3 (Node.js example)
const crypto = require('crypto');
function verifyV3(signatureB64, timestamp, method, path, body, webhookKey) {
const messageToSign = `${method}${path}${timestamp}${body}`; // exact order per dashboard docs
const expected = crypto
.createHmac('sha256', webhookKey)
.update(messageToSign)
.digest('base64');
return crypto.timingSafeEqual(
Buffer.from(signatureB64),
Buffer.from(expected),
);
}Confirm the exact byte layout of messageToSign on your webhook configuration page before shipping — the docs describe it as an ordered concatenation but the full field list is shown there per team.