Gareth Wilson Gareth Wilson

Guide to RingCentral Webhooks: Features and Best Practices

Published


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

FeatureDetails
ConfigurationPOST /restapi/v1.0/subscription with eventFilters + deliveryMode (WebHook)
Endpoint validationMandatory: echo the Validation-Token request header back as a response header with 200
Per-notification checkOptional verificationToken you set; sent back as a Verification-Token header
SignatureNone (no HMAC)
TransportHTTPS required
Subscription lifetimeexpiresIn; expires and renews (now up to ~20 years, not the old ~7-day cap)
HealthBlacklisted 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 filterNotifies you when
/restapi/v1.0/account/~/extension/~/message-store/instant?type=SMSAn SMS is received
/restapi/v1.0/account/~/telephony/sessionsA call (telephony session) changes state
/restapi/v1.0/account/~/extension/~/message-storeA message-store event occurs (voicemail, fax, ...)
/restapi/v1.0/account/~/presencePresence 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.

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 verificationToken and 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-Token header, 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 expiresIn and 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.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.