Zoom Webhook Specs, Events, and Examples
Zoom uses webhooks to notify third-party apps of events such as Meetings, Webinars, Recordings, User Activity, Billing, and Chat Messages created.
Specifications |
|
Supported Events | |
Security Headers |
|
Documentation | |
SDKs and Sample Code |
URL Validation
When you add or change an endpoint — and every 72 hours after that — Zoom sends an endpoint.url_validation event containing a plainToken. Your endpoint must respond within 3 seconds with the token and its HMAC, proving it holds the Secret Token. After six consecutive failed validations, Zoom disables the subscription. See One Time Verification.
Sample Validation
const crypto = require('crypto')
const express = require('express')
const app = express()
const timeHeader = 'x-zm-request-timestamp'
const sigHeader = 'x-zm-signature'
const hashAlgo = 'sha256'
const encode = 'hex'
const hmacSecret = process.env.ZOOM_WEBHOOK_SECRET_TOKEN
// Use the raw body: re-serialized JSON will not match the signature
app.post('/zoom-webhook', express.raw({ type: 'application/json' }), (req, res) => {
//01: Validate replay prevention with 5 minute timeframe
const timestamp = req.get(timeHeader)
if (!timestamp || Math.abs(Date.now() - timestamp * 1000) > 5 * 60 * 1000) {
return res.status(403).send('Request expired')
}
//02: Validate signature
const message = `v0:${timestamp}:${req.body.toString('utf8')}`
const digest = Buffer.from('v0=' +
crypto.createHmac(hashAlgo, hmacSecret).update(message).digest(encode), 'utf8')
const providerSig = Buffer.from(req.get(sigHeader) || '', 'utf8')
if (providerSig.length !== digest.length || !crypto.timingSafeEqual(digest, providerSig)) {
return res.status(401).send('Request unauthorized')
}
const event = JSON.parse(req.body)
//03: Answer the URL validation challenge
if (event.event === 'endpoint.url_validation') {
const plainToken = event.payload.plainToken
const encryptedToken = crypto.createHmac(hashAlgo, hmacSecret).update(plainToken).digest(encode)
return res.json({ plainToken, encryptedToken })
}
//04: Process message
res.json({ message: "Success" })
})