FlowKit

n8n + Zoom: automating meeting recording retrieval and AI summaries

Published 11 August 2026 · 6 min read

A meeting recorded on Zoom almost always ends up in the same place: a video file in the cloud that nobody reopens. Those who attended rely on their approximate memory of the content; those who missed it wait for a recap that rarely arrives. A study by Geimer, Leach, DeSimone, Rogelberg and Warr, published in 2015 in the Journal of Business Research (see on Google Scholar), found that fewer than half of participants consider their meetings genuinely effective — and the lack of structured follow-up afterward is a recurring cause. Zoom exposes an API and webhooks that let you wire n8n directly to the end of a cloud recording, to transcribe and summarize it without anyone having to reopen the video. This guide builds that pipeline end to end.

Why start from the Zoom webhook instead of a manual upload

Our guide to transcribing and summarizing meetings with Whisper covers the generic case: a manually uploaded audio file triggers the transcription. That works for occasional use, but it assumes someone remembers to upload the file — which, in practice, rarely happens consistently. Wiring directly into Zoom's recording.completed event removes that manual step: as soon as Zoom finishes cloud-processing the recording, n8n gets notified and starts the pipeline with no intervention. It's the same principle as Cal.com's native no-show detection: a reliable server-side event beats a human reminder.

Pipeline overview

The full setup chains five building blocks: an n8n Webhook that receives recording.completed, an HTTP Request node that downloads the audio file, a call to a transcription API, a Basic LLM Chain that structures the summary, and a final distribution step (Slack, Notion, or a daily digest). Each block stays independently swappable — the same modular logic as in our other AI integration guides.

Step 1 — Create a Zoom Server-to-Server OAuth app

In the Zoom App Marketplace, the app type best suited to a server pipeline like n8n is Server-to-Server OAuth: it provides both an account-level access token (no interactive OAuth redirect to manage, so no re-authentication) and the ability to enable Event Subscriptions (webhooks) from the same configuration screen. Add the cloud_recording:read:recording scope (or :admin to cover every host on the account), then subscribe to the recording.completed event.

Step 2 — Receive the webhook in n8n and answer the validation challenge

n8n has no dedicated "Zoom Trigger" node: the generic Webhook node does the job, exactly as documented in our guide to securing n8n webhooks. Before accepting any real event, Zoom sends a validation challenge (event: "endpoint.url_validation") the moment you paste the webhook URL into the Marketplace, and then periodically every 72 hours to revalidate the endpoint. The expected response is a JSON object { "plainToken": ..., "encryptedToken": ... }, where encryptedToken is an HMAC-SHA256 of the received plainToken, computed with the app's secret token as the key. An IF node right after the Webhook separates this case (event === "endpoint.url_validation") from the normal flow, and a Crypto node computes the expected hash before sending it back via Respond to Webhook — the same mechanics detailed in our guide to the Crypto node and HMAC signatures. To test this setup before pasting the final URL into the Marketplace, a tunnel like ngrok works exactly as for testing any n8n webhook locally.

Verifying the signature on real events

On every subsequent recording.completed event, Zoom signs the request via the x-zm-signature header, computed over the string v0:{x-zm-request-timestamp}:{raw-body} with the same secret token. Recomputing this HMAC in a Crypto node and comparing it against the received header prevents a discovered webhook URL from being used to inject fake events into the pipeline — a point that matters even more here since the event triggers a file download.

Step 3 — Download the recording with the download_token

The recording.completed payload contains a recording_files array, each entry with its own download_url, and crucially a download_token field generated specifically for that webhook. Appending this token as a query parameter (?access_token={{ $json.download_token }}) on the download URL in an HTTP Request node means no separate OAuth call is needed to fetch the file — as long as it happens within 24 hours of receiving the webhook, the token's validity window. Filter on file_type === "M4A" (or MP4, depending on your needs) to download only the audio track and avoid pulling the full video unnecessarily.

Step 4 — Transcribe the audio

An HTTP Request node to a transcription API (OpenAI's Whisper, or an equivalent model) turns the downloaded binary file into text. For long meetings, split the audio into chunks under 25 MB before sending — the typical limit for this kind of API — on the same chunking principle already covered in our generic transcription guide.

Step 5 — Generate a structured AI summary

A raw forty-five-minute transcript isn't any easier to read than a video replay. A Basic LLM Chain connected to Claude or GPT, with a prompt enforcing a fixed structure — decisions made, action items with an assigned owner, open questions — turns the raw text into a recap readable in thirty seconds. Explicitly asking the model to cite the approximate timestamp of each decision (inferable from the transcript's timing) makes it easy to jump back to the exact moment in the recording when in doubt, instead of having to re-listen to everything.

Step 6 — Distribute the summary

The generated summary then goes out to Slack (a message in the relevant team channel), to an automatically created Notion page, or gets rolled up into a daily digest if meeting volume justifies it — the same principle as the Pack Inbox IA's daily digest, which applies this logic to emails rather than meetings. For teams also tracking tickets or files tied to these meetings, logging every summary into a Supabase table (see our n8n ↔ Supabase connection guide) makes the history searchable later, instead of scattered across several Slack channels.

GDPR and meeting recordings: what to define upfront

An audio or video meeting recording contains personal data under GDPR as soon as it captures the voice of identifiable participants. Three things to define before deploying this pipeline in production: informing participants that the meeting is recorded and transcribed by AI (a mention at the start of the meeting or in the invite is usually enough); limiting how long the source file is kept once the summary has been generated, on the same principle as our guide to automatic GDPR data purging; and checking that the chosen transcription API doesn't use the audio content to train its models, per the terms of whichever provider you pick.

Best practices and limitations

  • recording.completed only fires for cloud recordings, not for a local recording saved on the host's machine — worth checking in the Zoom account settings before building the pipeline.
  • The download_token expires after 24 hours: a pipeline that processes the recording immediately never hits this, but a delayed retry after an error needs to go through a regular API call with an OAuth access_token to regenerate the URL.
  • Never skip signature verification on real events, even in a test environment: once a webhook URL is known, it stays callable by anyone as long as no verification is in place.
  • Cleanly separate the validation challenge from the normal flow with an IF node at the top of the workflow, so a periodic Zoom revalidation doesn't accidentally end up in the recording-processing branch.

FAQ

Frequently asked questions

Does n8n have a native "Zoom Trigger" node?

No. The native "Zoom" node only covers actions (create, retrieve, update, delete a meeting) via an OAuth2 or Server-to-Server credential. To react to a Zoom event like recording.completed, you need the generic Webhook node, exactly as with Cal.com before its dedicated Trigger was added, or as described in our guide on securing n8n webhooks.

Do you need to answer the validation challenge on every webhook received?

No, only when you first configure the URL in the Zoom Marketplace, and then during the automatic revalidations Zoom performs periodically (roughly every 72 hours). An IF node that checks event === "endpoint.url_validation" before any other processing is enough to isolate this special case from the normal recording.completed event flow.

Does the webhook's download_token expire quickly?

Yes, it's only valid for 24 hours. For a pipeline that processes the recording within a minute of the webhook firing, this is never an issue. If the workflow needs to resume a recording later (a retry after an error, for instance), you then need to go back through the Zoom API with a regular OAuth access_token to regenerate a valid download URL.

What if Zoom Cloud Recording isn't enabled on the account?

The recording.completed webhook only fires for recordings stored in the Zoom cloud, not for local recordings saved on the host's machine. The option lives in the Zoom account settings (Recording > Cloud recording) and requires a paid plan; on the free plan, only local recording is available, which makes this pipeline inapplicable without an upgrade.

Bundle FlowKit Complet

€269