Using webhooks
Zoom utilizes webhooks as a medium to notify third-party applications (consumer applications) about events that occur in a Zoom account. Instead of making repeated calls to pull data frequently from the Zoom API, you can use webhooks to get information on events that happen in a Zoom account.
Event notifications are sent as HTTP POST requests in JSON to the endpoint you specify in your Marketplace app.
On This Page
- Set endpoint URL
- Webhook endpoint requirements
- Objects, actions, and events
- Enable webhooks
- Verify webhook events
- Validate your webhook endpoint
- Notification delivery
Set endpoint URL
Set your Event notification endpoint URL for each event subscription in your Marketplace app. Be sure that it satisfies the Webhook endpoint requirements below.

Webhook endpoint requirements
To receive Webhooks in development and production environments, the Event notification endpoint URL that you specify for each event subscription must:
- Employ the
https://
scheme. - Support TLSv1.2+ with a valid certificate chain. The certificate of your webhook endpoint must be issued by a Certificate Authority (CA). Zoom validates the certificate on the configured URL provided by the server. Zoom will not deliver the event request if the certificate isn't valid.
- Be a fully qualified domain name (FQDN).
- Be able to accept HTTP POST requests containing JSON payloads.
- Must be able to respond with an HTTP Status Code.
Objects, actions, and events
Objects are pieces of data that form the resources provided by Zoom, such as Zoom APIs and webhooks. An event occurs when a user performs an action that causes a change in the value of an object. Events are grouped into the following types:
- Meeting
- Webinar
- Recording
- Zoom Rooms
- User
- User Activity
- Account
- Zoom Phone
- TSP
- Billing
- Chat Channel
- Chat Message
Each Zoom event type is comprised of multiple webhook events. These webhook events are defined by a common $object.$action
naming rule.
For example, the user
webhook object consists action
values such as:
activated
created
deactivated
deleted
disassociated
updated
One of the User webhook events is the user.created
event. This webhook triggers when a user is created on a Zoom account that is subscribed to the User has been created event in the User event type.
To enable webhooks for these events, you must add Event Subscriptions to your Marketplace app. Refer to the Enable webhooks section for information on enabling webhooks with event subscriptions for each app type.
Chatbot events
You can also receive events for Chatbot actions. For example, when users:
- Enter a slash command
- Edit the text of a Chatbot message
- Fill out a Chatbot form field
- Select an option in the Chatbot dropdown
- Click a Chatbot button
Enable webhooks
You can enable webhooks in any of the following Zoom App Marketplace app types:
Set Endpoint URL
Set your Event notification endpoint URL for each event subscription in your Marketplace app. Be sure that it satisfies the webhook endpoint requirements below.

Webhook Endpoint URL Requirements
To receive webhooks in development and production environments, the Event notification endpoint URL that you specify for each event subscription must:
- Be a publicly accessible
https
endpoint url that supports TLSv1.2+ with a valid certificate chain issued by a Certificate Authority (CA). - Be able to accept HTTP POST requests.
- Be able to respond with a
200
or204
HTTP Status Code.
Webhook structure
Webhooks requests contain request headers and a request body.
Request headers
Webhooks sent by Zoom contain the following headers:
Key | Value Description |
---|---|
host | The server where the request is being sent. |
user-agent | The identifier of the application that is sending the request. For example, Zoom Marketplace/1.0a |
content-type | The resource's media type. For example, application/json; charset=utf-8 |
content-length | The content length of the HTTP request body, in bytes. |
clientid | The client ID of your Marketplace application. |
authorization | This header is unique to your app and confirms the request was sent from Zoom using the webhook verification token on the Add feature page for your Marketplace app. The Verification Token will be deprecated in August 2023. We recommend that you replace your webhook verification token logic with the logic using the x-zm-signature header and the webhook secret token. |
x-zm-signature | The encrypted authorization header used to verify that webhook requests come from Zoom. |
x-zm-request-timestamp | The time the request was sent, in epoch format. |
x-zm-trackingid | A unique ID that Zoom uses to identify the request. |
Request body
The webhook request body includes the event type (event
), the event details (payload
), and the timestamp (event_ts
) of when the event occurred.
Key | Value Type | Value Description |
---|---|---|
event | string | The type of the webhook event. |
payload | object | The event details. See the reference guides for details, for example, Zoom Meeting, Phone, or Video SDK. |
event_ts | number | The timestamp of the webhook event. |
IP addresses
We strongly recommend that you Verify webhook events instead of creating an allow list of IP addresses because Zoom may update the IP ranges used at any time.
If you must create an allow list by IP Address, Zoom uses the following to send event notifications:
3.80.20.128/25
3.235.82.0/23
18.205.93.128/25
52.61.100.253
52.61.100.254
134.224.0.0/16
144.195.0.0/16
170.114.0.0/16
Verify webhook events
To verify webhook requests are sent from Zoom, Zoom includes a x-zm-signature
value in the webhook request header. You can use the new webhook secret token and the webhook request body to create a signature to compare with the x-zm-signature
header value that Zoom sends.

Follow the steps below to create your signature string to compare with the Zoom webhook x-zm-signature
header value.
1. Receive the webhook request
The webhook request body includes the following properties:
Key | Value Type | Value Description |
---|---|---|
event | string | The type of the webhook event |
payload | object | Contains the event webhook details |
event_ts | number | The timestamp of the webhook event. |
Here's an example:
{
"event": "session.started",
"payload": {
"account_id": "{ACCOUNT_ID}",
"object": {
"start_time": "2022-07-27T16:56:34Z",
"id":"{SESSION_ID}"
}
},
"event_ts": 1658940994914
}
2. Construct the message
After receiving a webhook request, construct the message string with "v0"
, the webhook request header x-zm-request-timestamp
value, and the webhook request body. Separate each section with a colon :
. For example:
v0:{WEBHOOK_REQUEST_HEADER_X-ZM-REQUEST-TIMESTAMP_VALUE}:{WEBHOOK_REQUEST_BODY}
Example string with printed values:
v0:1658940994:{"event":"session.started","payload":{"account_id":"{ACCOUNT_ID}","object":{"start_time":"2022-07-27T16:56:34Z","id":"{SESSION_ID}"}},"event_ts":1658940994914}
3. Hash the message
Once you have constructed the message string, create a HMAC SHA-256 hash. Set your webhook's secret token as the secret/salt, and the message
you constructed as the string to hash. Output in hex
format.
4. Create the signature
Then, create the signature by prepending v0=
to the hashed message. For example:
v0={HASHED_MESSAGE}
Example string with printed values:
v0=a05d830fa017433bc47887f835a00b9ff33d3882f22f63a2986a8es270341
5. Compare the signature
Now compare the signature
you created with the Zoom webhook request header x-zm-signature
value. If it matches, the webhook request came from Zoom.
Here is an example in Node.js:
const crypto = require('crypto')
const message = `v0:${request.headers['x-zm-request-timestamp']}:${JSON.stringify(request.body)}`
const hashForVerify = crypto.createHmac('sha256', ZOOM_WEBHOOK_SECRET_TOKEN).update(message).digest('hex')
const signature = `v0=${hashForVerify}`
if (request.headers['x-zm-signature'] === signature) {
// Webhook request came from Zoom
} else {
// Webhook request did not come from Zoom
}
See the Webhook sample app for an example implementation.
Validate your webhook endpoint
Zoom requires that you manually trigger webhook validation when you add a new webhook or make changes to an existing one. Subsequently, Zoom will automatically revalidate webhooks every 72 hours.
Zoom uses a challenge-response check (CRC) for webhook validation. When a CRC occurs, Zoom will make a POST request to your endpoint with a challenge request body. After your endpoint receives the request, your app needs to respond with the challenge response within 3 seconds.
To trigger the initial CRC validation, click Validate under the Event Notification Endpoint URL on the Feature page for your app. See Revalidation for revalidation details.

Follow the steps below to handle the challenge-response check flow.
1. Receive the challenge (webhook request body)
The webhook request body includes the following properties:
Key | Value Type | Value Description |
---|---|---|
event | string | The type of the webhook event, which will be "endpoint.url_validation" |
payload | object | Contains a property with the plainToken value, the string to hash. |
event_ts | number | The timestamp of the webhook event. |
Here's an example:
{
"payload": {
"plainToken": "qgg8vlvZRS6UYooatFL8Aw"
},
"event_ts": 1654503849680,
"event": "endpoint.url_validation"
}
2. Hash the plainToken
Once you receive the request body, create a HMAC SHA-256 hash. Set your webhook's secret token as the secret/salt, and the plainToken
value as the string to hash. Output in hex
format.
3. Create the response JSON object
Create a JSON object with a key of "plainToken"
with a value of the plainToken
from the request body, and a key of "encryptedToken"
with a value of the hashed plainToken
. For example:
{
"plainToken": "qgg8vlvZRS6UYooatFL8Aw",
"encryptedToken": "23a89b634c017e5364a1c8d9c8ea909b60dd5599e2bb04bb1558d9c3a121faa5"
}
4. Respond with the response JSON object
Respond with the response JSON within 3 seconds with a 200
or 204
HTTP response code.
When Zoom successfully validates the challenge response from your webhook endpoint URL, you'll see a validated message under the Event Notification Endpoint URL. If validation fails, you'll see a failed to validate message. Once you successfully complete validation, click Save.

Here is an example in Node.js:
const crypto = require('crypto')
// Webhook request event type is a challenge-response check
if(request.body.event === 'endpoint.url_validation') {
const hashForValidate = crypto.createHmac('sha256', ZOOM_WEBHOOK_SECRET_TOKEN).update(request.body.payload.plainToken).digest('hex')
response.status(200)
response.json({
"plainToken": request.body.payload.plainToken,
"encryptedToken": hashForValidate
})
}
See the Webhook sample app for an example implementation.
Revalidation
Your production and development webhook URLs will be revalidated periodically every 72 hours. Zoom will send notification emails to the account owner associated with your apps if the URL fails the revalidation, following this schedule:
- First notification email after a total of 2 consecutive failed revalidations.
- Second notification email after a total of 4 consecutive failed revalidations.
If the revalidation check fails 6 times in a row, Zoom will stop sending event notifications to the webhook URL and disable it. To enable the webhook URL to receive event notifications again, follow the steps below:
- Fix the issue that caused your webhook URL validation to fail.
- If you changed the URL, update the Event Notification Endpoint URL on the Feature page on the Zoom App Marketplace.
- Click Validate to manually re-validate the URL. If successful, you should see that it is valid.
- Click Save to save changes. If this is a private app not shared on the Marketplace, Zoom will re-enable your webhook after this step.
- If your app is a published app on the Zoom Marketplace, resubmit your app for review. After the review is completed, Zoom will re-enable your webhook.
Notification delivery
Your webhook endpoint URL should respond with either a 200
or a 204
HTTP status code within three seconds after receiving a webhook request in order for Zoom to consider the notification was successfully delivered.
Unsuccessful delivery
For any unsuccessful notification deliveries, Zoom attempts to deliver the webhook three times:
- The first attempt is sent five minutes after the initial delivery attempt.
- A second attempt is sent 30 minutes after the first attempt.
- A third attempt is sent 90 minutes after the second attempt.
If a 200
or a 204
response is received after any retry attempt, then Zoom considers the notification was successfully delivered.
However, if Zoom does not receive a 200
or a 204
response after three attempts, then no further webhooks for that event will be sent.
Delivery latency
The event_ts
response is included in the payload of all event notifications. This represents the timestamp for when the associated event occurred.
You can determine the latency in webhook delivery by calculating the difference between the delivery timestamp and the value of the event_ts
.
Need help?
If you're looking for help, try Developer Support or our Developer Forum. Priority support is also available with Premier Developer Support plans.