The loop
Create an endpoint and it prints a permanent ingest URL. Everything sent there is captured whole — headers, body, the exact bytes — before anything else happens. Stream those events to a port on your machine, and replay any one of them as often as you like while you fix the handler. Forwarding runs from your own machine, so it isn't a billable delivery.
What's different about Zoom
Zoom won't let you save an event subscription until your URL answers a challenge. Click Validate and Zoom POSTs an endpoint.url_validation event carrying a plainToken; you have three seconds to return 200 or 204 with a JSON body echoing that plainToken plus encryptedToken, an HMAC SHA-256 of it salted with your webhook secret token, output in hex. A 200 on its own doesn't pass. And it isn't a one-time hurdle: Zoom re-runs the check every 72 hours, emails you after two and after four consecutive failures, and disables the subscription after six in a row.
Where the URL goes
In the Zoom App Marketplace, click Manage, open your app from Created Apps, and go to Features then Access. Under General Features, enable Event Subscriptions and add a new subscription. Choose your event types, paste the capture URL into the Event notification endpoint URL field, and click Validate — Zoom refuses to save the subscription until validation succeeds. Then Save.
Zoom's docs describe no send-test-event control. The only request Zoom fires on demand is the Validate button, which sends endpoint.url_validation and nothing else. Everything past that means performing the real action in Zoom — scheduling or starting a meeting — and letting the subscription fire on its own. To confirm what Zoom actually sent, the Get webhook logs API returns webhook call logs from the past seven days.
What Zoom sends
Almost every Zoom event is dot-separated resource.action — lowercase resource, snake_case action. The exception worth knowing is app_deauthorized, which carries no resource prefix and is delivered to a separate Deauthorization Notification Endpoint URL rather than to your event subscription.
- meeting.created
- meeting.started
- meeting.participant_joined
- meeting.ended
- recording.completed
- endpoint.url_validation
Worth knowing first
Three seconds, then it's a failure
Zoom counts a notification delivered only if your endpoint returns 200 or 204 within three seconds of the request. Anything slower is a failed delivery, regardless of what your handler eventually did with the payload. Acknowledge first and process afterwards — everything you do before responding is inside that budget.
A 4xx is never retried
Zoom retries three times: five minutes after the initial delivery attempt, twenty minutes after that retry, then sixty after the second. But only for responses of 500 and above, plus a set of Zoom-internal negative codes. Redirects and 4xx responses get no retry at all, and after three failures Zoom sends no further webhooks for that event.
No replay, a seven-day log
Nothing in Zoom's docs offers a redeliver control, so an event that burns through its three retries is gone. What you do get is the Get webhook logs API, which returns webhook call logs for an app from the past seven days — enough to see what was sent, not enough to send it again.
Verify signatures, don't allowlist IPs
Zoom signs each request with x-zm-signature, formed as v0= followed by an HMAC over the string v0:timestamp:body, where the timestamp comes from x-zm-request-timestamp. Zoom publishes its IP ranges in a support article but recommends signature verification instead, because those ranges can change at any time.
Twenty subscriptions, and duplicates
An app can hold up to twenty event subscriptions, and Zoom notes that subscriptions can carry duplicate events — the same event type selected in two of them means one action produces more than one POST. The endpoint itself must be a publicly reachable HTTPS FQDN on TLS 1.2 or later with a CA-issued certificate chain.
Signature checking is handled for you once the secret is registered — you can also check a captured signature by hand in the signature verifier.