Zoom Meeting Bots
Send API-controlled bots into Zoom meetings to record, transcribe, and interact
MeetStream bots join Zoom meetings through the Zoom Meeting SDK. Zoom is the one platform that needs a one-time setup (Google Meet and Microsoft Teams work with zero configuration) — after that, sending a bot is the same single create_bot call as everywhere else.
One-time setup
- Create a General App in the Zoom App Marketplace (Develop → Build App → General App). User-managed or admin-managed both work.
- Under Features → Embed, enable Meeting SDK.
- Save the app’s Client ID and Client Secret in MeetStream Dashboard → Integrations → Zoom. These identify the bot’s Meeting SDK app.
- For authenticated joins, configure your own OAuth callback and HTTPS token mint endpoint as described below.
Full walkthrough: Zoom Marketplace App Setup.
Development-mode limitation: with development credentials your bot can only join meetings hosted by your own Zoom account. For external meetings, configure the appropriate ZAK or OBF join and submit the app for production approval — see Zoom App Production Submission. Approval does not replace join-time authorization.
Guest, signed-in, and on-behalf-of joins
Send only one token URL. MeetStream fetches it at join time; your HTTPS server runs OAuth, stores refresh tokens, and mints the token. MeetStream does not store end-user Zoom OAuth refresh tokens for join.
For OBF, the parent must already be in the meeting and the bot is removed when that parent leaves. Do not put meeting_number on obf_url: MeetStream appends it. Mint the short-lived, single-use token when called.
use_zoom_obf and zoom_oauth_connection_user_id are rejected. See Zoom Authenticated Bots for payloads, scopes, the mint endpoint contract, and troubleshooting.
The recording permission flow
Zoom is the only platform where recording is gated on host consent. After bot.inmeeting, the bot requests recording permission and waits — so there can be a visible gap before bot.recording (on Meet and Teams it fires within about a second).
- Host grants →
bot.recording_permission_allowed→bot.recording - Host denies, or doesn’t respond within
recording_permission_denied_timeout→bot.recording_permission_denied→bot.leaving→bot.stopped(a clean stop, notbot.denied)
recording_permission_denied_timeout accepts 60–300 seconds (default 60) and is ignored on the other platforms.
Zoom-specific behavior at a glance
Troubleshooting joins
The usual causes when a Zoom bot fails to join:
- Invalid or expired meeting link
- App still in development mode and the meeting isn’t hosted by your account
- Bot stuck in the waiting room until
waiting_room_timeoutfired (bot.notallowed) - Password-protected meeting link missing its
?pwd=component - ZAK/OBF: your mint URL failed; check HTTPS reachability, endpoint authentication, and your server’s Zoom OAuth grant
- OBF: the parent is absent, or
meeting_numberwas duplicated on the mint URL
Watch it live with meetstream listen or the Debugging guide.
Next steps
Zoom FAQ
Why does my Zoom bot join but never record?
Recording on Zoom is gated on host consent. If the host doesn’t grant permission within recording_permission_denied_timeout (60s default, max 300), the bot leaves cleanly with bot.stopped. Watch for bot.recording_permission_allowed / denied webhook events.
Why can my bot only join my own meetings?
Your Zoom Marketplace app is still in development mode. Submit it for production approval and configure ZAK or OBF for external meetings.
Do password-protected Zoom links work?
Yes — pass the full invite link including the ?pwd= component as meeting_link.
How do my end users connect their own Zoom accounts?
Run OAuth on your server and pass zoom.zak_url or zoom.obf_url at create_bot. See Zoom Authenticated Bots.
Why are Zoom per-participant audio files so clean?
Zoom is the only platform whose SDK provides a dedicated raw PCM stream per participant — full isolation, each file contains only that speaker’s microphone.
