Webhooks and Events
MeetStream sends an HTTP POST with a JSON body to your server every time a bot changes state and when its recordings and transcripts are ready. This page is the reference for what arrives and how to handle it.
The one rule to remember: branch on bot_event. Every payload carries both event and bot_event. They are equal for every event except a bot’s ending, where event is always bot.stopped and bot_event tells you why the bot ended.
Where events are delivered
Both receive the same payloads. If you use both with the same URL, each event is delivered once, signed.
Payload format
Bot status events look like this:
Post-call events use the same envelope but carry an artifact status instead of bot_status; see Post-call events.
The life of a bot
Platform details, such as how each platform’s lobby works, are in the Zoom, Google Meet and Microsoft Teams guides.
How a bot ends
A bot ends with exactly one ending event (the one exception, a bot you remove before it joins, is listed below). On the wire, event is always bot.stopped; bot_event names the cause:
Things that trip up handlers:
- A kick reports
bot_status: "Stopped". Onlybot_event: "bot.kicked"tells a kick apart from a normal stop. - Google Meet join blockers carry a reason. When the meeting itself prevents the join, a Google Meet bot ends with
bot_event: "bot.failed",bot_status: "Failed",status_code: 500and afailure_reason:invalid_meeting_link,meeting_not_started,meeting_ended,meeting_restricted,sign_in_required,google_sign_in_failedorcant_join_call. - A Zoom recording-permission denial ends with
bot.stopped, after abot.recording_permission_deniedevent. - Removing a bot before it joins sets its status to
Stoppedwithout an ending webhook on Zoom and Google Meet. - Workspace endpoints only receive the ending events they subscribe to. Subscribe to all five, or you will miss kicks, denials and lobby timeouts.
Every bot_status, error message and fix is listed in the status and error code reference.
Ending payloads
Post-call events
After the ending event, MeetStream processes the recording in the background. Audio, video and transcript processing run in parallel, so these events can arrive in any order. bot.done always comes last.
About bot.done:
- It is the last event for a bot and always has
status_code: 200. It means processing finished, not that every step succeeded. Check the artifact events for that. - It is sent for bots that never got into the meeting too. For those,
bot_statuskeeps the ending status (for exampleNotAllowedorDenied) instead ofDone. - It is sent whether or not transcription was configured, including for live (streaming) transcription.
data_deletion is sent when a bot’s media is deleted, either when its retention window ends or when you call DELETE /api/v1/bots/{bot_id}/delete. The bot’s status becomes MediaExpired and media endpoints stop returning files.
Event catalog
These are all the event names MeetStream sends. The first four groups match the Subscribe to events list in the dashboard exactly. Events in the other groups are not listed in the dashboard and are delivered to every active workspace endpoint.
Live transcription results are not webhook events. They are posted to the live_transcription_required.webhook_url you set on the bot; see Live Transcription.
Signing
Deliveries to workspace endpoints carry:
Deliveries to a per-bot callback_url are not signed. Verification code for Python and Node is in Verifying Webhook Signatures.
Delivery rules
- One attempt, no automatic retries. A timeout, connection error or non-2xx response is logged as a failed delivery and is not retried. You can resend it from the dashboard: Webhooks > Logs > RESEND.
- Respond with 2xx quickly and process asynchronously. Some deliveries time out after 10 seconds, and a slow response can delay the next events for the same bot.
- At most once per bot:
bot.inmeeting, the ending event and each post-call event.bot.joiningcan repeat for scheduled bots. - No ordering guarantee between post-call events. Wait for
bot.doneif you need everything. - Duplicates are possible when you resend from the Logs tab. De-duplicate on
bot_idplusbot_event. - Unknown event names can appear. Ignore events you do not handle rather than returning an error.
Handler checklist
- Accept
POSTrequests and read the raw body before parsing it, so you can verify the signature. - Verify
X-MeetStream-Signature(workspace endpoints). - Return
2xximmediately; queue the work. - Branch on
bot_event. - On any ending event (
bot.stopped,bot.kicked,bot.denied,bot.notallowed,bot.failed), mark the session ended and record the cause. - On
audio.processed,video.processedandtranscription.processed, fetch the artifact. Or wait forbot.doneand fetch everything at once. - On
data_deletion, drop your stored references to the bot’s media.
Related: Workspace Webhook Endpoints, Set Up Local Server for Webhook, Debugging Bots, Bot status and error code reference.
