Guide to RingCentral Webhooks: Features and Best Practices
RingCentral webhooks notify your application about communications activity: an SMS arrives, a call session changes state, a voicemail is left. If you're building on RingCentral, webhooks are how you react to telephony and messaging events without polling.
This guide covers how RingCentral webhooks work, the events you'll subscribe to, the two verification mechanisms (there's no HMAC signature), subscription renewal, and the best practices for production.
What are RingCentral webhooks?
RingCentral delivers notifications to a webhook address you register via an event-filter subscription. There's no HMAC signature on notifications. Authenticity rests on two things: a mandatory Validation-Token handshake that proves you control the endpoint at subscription time, and an optional Verification-Token you set and check on every notification.
RingCentral webhook features
| Feature | Details |
|---|---|
| Configuration | POST /restapi/v1.0/subscription with eventFilters + deliveryMode (WebHook) |
| Endpoint validation | Mandatory: echo the Validation-Token request header back as a response header with 200 |
| Per-notification check | Optional verificationToken you set; sent back as a Verification-Token header |
| Signature | None (no HMAC) |
| Transport | HTTPS required |
| Subscription lifetime | expiresIn; expires and renews (now up to ~20 years, not the old ~7-day cap) |
| Health | Blacklisted after 10 min of failed checks; reconciled ~every 15 min once healthy |
| SDKs | @ringcentral/sdk (npm), ringcentral (pip) |
Common events
RingCentral subscriptions use event-filter URIs rather than short event names:
| Event filter | Notifies you when |
|---|---|
/restapi/v1.0/account/~/extension/~/message-store/instant?type=SMS | An SMS is received |
/restapi/v1.0/account/~/telephony/sessions | A call (telephony session) changes state |
/restapi/v1.0/account/~/extension/~/message-store | A message-store event occurs (voicemail, fax, ...) |
/restapi/v1.0/account/~/presence | Presence changes |
Subscribe to the event filters you need, and consult RingCentral's event-filters reference for the full set.
Setting up RingCentral webhooks
Create a subscription with POST /restapi/v1.0/subscription, providing eventFilters, a deliveryMode of { transportType: "WebHook", address: "<https-url>" }, and an expiresIn. The address must be HTTPS. Subscriptions expire and must be renewed (via PUT /restapi/v1.0/subscription/{id} or the renew endpoint); expiresIn now allows very long lifetimes (up to ~20 years), so the old ~7-day cap no longer applies, don't hardcode 7 days.
Securing RingCentral webhooks
There's no signature, so verification is two steps.
The Validation-Token handshake (mandatory)
When you create or renew a subscription, RingCentral sends a request to your address carrying a Validation-Token request header. Echo that exact value back in a Validation-Token response header and return 200. Fail this and the subscription isn't established.
The Verification-Token (optional but recommended)
Set an arbitrary verificationToken on the subscription. RingCentral then includes it as a Verification-Token header on every notification, so you can confirm the request came from your subscription.
const VERIFICATION_TOKEN = process.env.RC_VERIFICATION_TOKEN;
app.post("/webhook", express.json(), (req, res) => {
// 1. Validation handshake: echo the Validation-Token header back
const validationToken = req.headers["validation-token"];
if (validationToken) {
res.setHeader("Validation-Token", validationToken);
return res.sendStatus(200);
}
// 2. Notification: check the optional Verification-Token
if (VERIFICATION_TOKEN &&
req.headers["verification-token"] !== VERIFICATION_TOKEN) {
return res.sendStatus(401);
}
res.sendStatus(200); // acknowledge fast
processQueue.add(req.body); // process asynchronously
});
The same in Python (Flask):
import os
from flask import request, Response
VERIFICATION_TOKEN = os.environ.get("RC_VERIFICATION_TOKEN")
@app.post("/webhook")
def webhook():
validation_token = request.headers.get("Validation-Token")
if validation_token:
return Response(status=200, headers={"Validation-Token": validation_token})
if VERIFICATION_TOKEN and request.headers.get("Verification-Token") != VERIFICATION_TOKEN:
return "", 401
# process asynchronously
return "", 200
Because there's no cryptographic signature, keep the endpoint URL secret, require HTTPS, and set the verificationToken so you have at least a shared-secret check on every notification.
RingCentral webhook limitations and pain points
No signature, only tokens
The Problem: There's no HMAC to verify. Authenticity rests on the handshake (endpoint ownership) and the optional Verification-Token (a shared secret). Without the token, any request to your URL looks legitimate.
Why It Happens: RingCentral's model is token-based, not payload-signing.
Workarounds:
- Always set a
verificationTokenand check it, require HTTPS, and keep the URL secret.
How Hookdeck Can Help: Hookdeck gives you a dedicated ingestion URL and can enforce its own verification and filtering in front of your endpoint, adding a layer beyond the token.
The Validation-Token handshake gates subscriptions
The Problem: If your endpoint doesn't echo the Validation-Token correctly (and fast), the subscription isn't created or renewed, and you receive nothing.
Why It Happens: RingCentral validates endpoint ownership before delivering.
Workarounds:
- Detect the
Validation-Tokenheader, echo it in the response header, and return 200 immediately.
How Hookdeck Can Help: Hookdeck can complete the handshake and forward verified notifications to your endpoint, so subscription setup isn't a manual concern.
Blacklisting on failed health checks
The Problem: If your endpoint fails validation or health checks within a 10-minute window, the subscription is blacklisted. It's reconciled roughly every 15 minutes once healthy, but you lose events in the meantime.
Why It Happens: RingCentral protects itself from unresponsive endpoints.
Workarounds:
- Acknowledge fast with 200 so health checks pass; monitor subscription state and renewal.
How Hookdeck Can Help: Hookdeck always responds fast to RingCentral and absorbs downstream failures itself, keeping the subscription healthy while it retries to your service.
Subscriptions expire
The Problem: Subscriptions expire per expiresIn and must be renewed. Miss the renewal and delivery stops. (The good news: the old ~7-day cap is gone, so you can set long lifetimes.)
Why It Happens: RingCentral time-boxes subscriptions, though the ceiling is now very high.
Workarounds:
- Set a long
expiresInand still track renewal; don't assume the legacy 7-day limit.
How Hookdeck Can Help: Hookdeck's observability surfaces a drop in delivery volume if a subscription lapses, so it shows up as an alert rather than silent data loss.
Best practices
Handle the handshake and set a Verification-Token
Echo the Validation-Token response header with a 200, and set and check a verificationToken on every notification.
Acknowledge fast to stay off the blacklist
Return 200 quickly and process off a queue so health checks pass. See why to process webhooks asynchronously.
Set a long expiresIn and still renew
Use a long lifetime (the 7-day cap is gone) but track renewal so subscriptions never silently lapse.
Keep the endpoint HTTPS and secret
Since there's no signature, require HTTPS and keep the URL and token confidential.
Make RingCentral webhooks production-ready
Hookdeck completes the handshake, adds verification, and durably queues every telephony and messaging event
Conclusion
RingCentral webhooks have no HMAC signature: authenticity comes from the mandatory Validation-Token handshake and an optional Verification-Token you set and check. Subscriptions expire (though the ceiling is now ~20 years, not 7 days), and a failing endpoint gets blacklisted. Handle the handshake, set the token, acknowledge fast, and renew.
Hookdeck completes the handshake, adds a verification layer RingCentral lacks, and durably queues every event at the edge, so your app processes trustworthy events without dropping any to a blacklisted subscription.
Get started with Hookdeck for free and handle RingCentral webhooks reliably in minutes.