Errors
MeetStream reports problems in two places: an HTTP error when a request is rejected, and a bot status or webhook when a bot that was created successfully cannot do its job. This page covers HTTP errors. For bot-level statuses, ErrorReason codes and messages on Zoom, Google Meet and Microsoft Teams, see the Bot status and error code reference.
Most errors return a JSON body with a message field:
A few endpoints return error instead, with extra fields: in-meeting commands (send message, send image, pause, resume), the credit check on create_bot, the deduplication conflict on create_bot, and signed-in login management. Read both keys:
Branch on the HTTP status code first, then log the text for the specifics.
Status codes at a glance
For REST API requests, the Authorization header is Token YOUR_API_KEY (not Bearer). The MCP server uses Bearer. See MeetStream MCP server. A missing key, an invalid or revoked key, or a key sent with Bearer returns 403 Forbidden with { "message": "Forbidden" }. See Authentication.
Authentication and access errors (403)
Treat a 401 Unauthorized like a 403: check that you send a workspace API key as Token YOUR_API_KEY. Very high request rates from one IP address can also be blocked with 403.
Validation errors (400)
Returned when the request fails validation, before any bot is created, so a 400 never spawns a bot or consumes credits. The message names the exact problem. Common cases:
Platform-specific 400s (Zoom token URLs, Google and Teams signed-in domains, teams.live.com sign-in) are listed in HTTP errors from create_bot.
400 messages are specific and actionable. Always log them. Fix the request and retry; a 400 is never transient.
Not found (404)
The resource or route doesn’t exist. Body varies by what was missing:
Conflict (409)
Rate and capacity limits (429)
Prepaid accounts can create 5 immediate or near-term bots per minute and 50 per hour, in rolling windows. Bots scheduled at least 10 minutes ahead and idempotent or deduplication replays do not count. The create response includes Retry-After (seconds), retry_after, limit, and window (minute or hour). See Create Bot Payload Reference.
Idempotent replay (507)
If you retry POST /bots/create_bot with the same Idempotency-Key, MeetStream returns 507 with the original bot’s details: no new bot, no extra charge. Treat 507 as success:
By contrast, a deduplication_key replay returns 200 (looks like a normal create). Both are documented in the Deduplication & Idempotency guide.
Still processing (202)
202 means the request was accepted but the data isn’t ready. Poll again; don’t treat it as an error.
- Transcript not ready:
GET /transcript/{transcript_id}/get_transcriptreturns{ "message": "Transcript is still being processed. Current status: <state>" }. - Per-participant streams:
get_audio_streams/get_recording_streamsreturn{ "audio_status": "in_progress", "message": ... }while the bot is still in the meeting. - Mixed audio, video and chat:
get_audio,get_videoandget_chatsreturn202until post-call processing for that artifact finishes.
Live providers do not create a post-call transcript. With a live-only provider (*_streaming), the text goes to your live webhook during the call, and transcript_id is null. Store the live stream as the transcript of record, or start a post-call run with POST /api/v1/bots/{bot_id}/transcribe. Put a limit on any polling loop.
Server errors (500 / 503)
Most 500 and 503 responses are temporary. Retry with exponential backoff.
One 500 is final: when get_transcript returns a message that starts with Transcript processing failed, the transcription run ended. Read the message, correct the provider settings if needed, and start a new run with POST /api/v1/bots/{bot_id}/transcribe.
If any other 500 repeats, contact support@meetstream.ai with the request time and any bot_id.
Operational errors (surfaced via bot status and webhooks, not HTTP)
Some failures happen after a successful 201: the bot was created, then couldn’t join or had to leave. These arrive as a terminal webhook on your callback_url or workspace endpoints, and in the bot’s status. Every ending uses event: "bot.stopped"; the reason is in bot_event.
