Errors

How the MeetStream API reports errors — every status code, what causes it, and how to fix it.

View as Markdown

Every MeetStream API error returns a JSON body with a single message field describing what went wrong:

1{ "message": "meeting_link is required." }

Branch on the HTTP status code first, then read message for the specifics. The tables below are verified against the live API.

Status codes at a glance

StatusMeaningTypical cause
200 OKSuccessRequest completed
201 CreatedBot createdPOST /bots/create_bot succeeded
202 AcceptedStill processingData not ready yet (transcript / per-participant streams) — poll again
400 Bad RequestValidation errorMissing/invalid field, unsupported provider, value out of range
401 UnauthorizedNo API keyAuthorization header missing
403 ForbiddenInvalid API keyKey is wrong, revoked, or malformed
404 Not FoundResource or route not foundUnknown bot_id / transcript_id, or wrong path
409 ConflictDuplicateA deduplication_key (or re-scheduled event) already maps to a bot
429 Too Many RequestsRate limitedSlow down; honor the Retry-After header
500 Internal Server ErrorServer errorTransient MeetStream error — retry with backoff
503 Service UnavailableTemporarily unavailableOverload / maintenance — retry with backoff
507Idempotent replayA retried Idempotency-Key replayed the original bot — treat as success

The Authorization header is always Token YOUR_API_KEY (not Bearer). A missing header returns 401; a present-but-invalid key returns 403. See Authentication.

Authentication errors

StatusBodyFix
401{ "message": "Unauthorized" }Add the header: Authorization: Token YOUR_API_KEY
403{ "message": "Forbidden" }The key is wrong/revoked — generate a new one in the dashboard

Validation errors (400)

Returned when the request body 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:

messageCause
meeting_link is required.POST /bots/create_bot sent without meeting_link
in_call_recording_timeout must be at least 600 secondsautomatic_leave.in_call_recording_timeout below 600
recording_permission_denied_timeout must not exceed 300 secondsValue above 300 (accepted range is 60–300; below 60 also 400)
live_transcription_required.webhook_url is provided but no streaming provider found…Set a streaming provider (deepgram_streaming, assemblyai_streaming, jigsawstack_streaming, meetstream_streaming, or meeting_captions) in recording_config.transcript.provider
unsupported / unconfigured providerThe transcription provider name is invalid, or its API key isn’t configured on your account

400 messages are specific and actionable — always surface message to your logs. 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:

BodyCause
{ "message": "Bot not found" }Unknown bot_id (also returned for a bot that was deleted)
{ "message": "Transcript not found" }Unknown transcript_id
{ "message": "Not Found" }Unknown path, or a valid path called with an unsupported method

Conflict (409) — deduplication

When you pass a deduplication_key (or schedule the same calendar event twice), MeetStream returns 409 with the existing bot’s ID rather than creating a duplicate:

1{
2 "message": "deduplication_key already bound to a different meeting",
3 "existing_bot_id": "bot_...",
4 "existing_meeting_url": "https://meet.google.com/..."
5}

To change a scheduled bot instead of colliding, use PATCH /calendar/scheduled_bots/{bot_id}. See Deduplication & Idempotency Keys.

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:

1if resp.status_code in (201, 507):
2 bot = resp.json() # same bot on 507 as on the original 201

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_transcript returns { "message": "Transcript is still being processed. Current status: <state>" }.
  • Per-participant streams: get_audio_streams / get_recording_streams return { "audio_status": "in_progress", "message": ... } while the bot is still in the meeting.

The 202 forever trap. For streaming-only providers (meetstream_streaming, *_streaming), a post-call get_transcript returns 202 indefinitely — it never flips to a transcript. Streaming providers deliver data over the live webhook, not the post-call fetch. A blind retry loop will hang. Cap your retries and rely on the live stream as the record.

Rate limits (429) and server errors (500 / 503)

  • 429 Too Many Requests — you’re sending too fast. Honor the Retry-After response header and back off before retrying.
  • 500 / 503 — a transient MeetStream-side error. Retry with exponential backoff. If it persists, contact support@meetstream.ai.

Operational errors (surfaced via webhooks, not HTTP)

Some failures happen after a successful 201 — the bot was created, then couldn’t do its job. These arrive on your callback_url, not as an HTTP error. Webhook status_code is 200 for success and 500 for failure.

Event / fieldMeaningWhat to do
bot.stopped · bot_status: "NotAllowed"Bot timed out in the waiting room / lobbyAdmit bots faster, raise waiting_room_timeout, or use a signed-in bot
bot.stopped · bot_status: "Denied"Host denied the bot entryNothing automatic — the host must admit it
bot.stopped · bot_status: "Error"The bot crashed mid-sessionRetry with a fresh create_bot
bot.errorNon-terminal streaming-provider upstream error (bot keeps running; no status_code)Check your streaming provider config/keys
transcription.failed · status_code: 500Post-call transcript run failedRead message (e.g. "Deepgram API error: 401" = provider key issue); re-run with POST /bots/{bot_id}/transcribe

See Webhooks and Events for the full lifecycle and payloads.

Handling errors well

Retry only what's retryable

Retry 429, 500, 503 (with backoff, honoring Retry-After). Never retry a 400 — fix the request first.

Make retries safe

Send an Idempotency-Key on create_bot so a network retry replays the original bot (507) instead of creating duplicates.

Don't loop on 202 forever

Cap transcript polling; streaming-only providers return 202 indefinitely by design.

Always log message

Every error carries a specific message — surface it so 400/404 causes are obvious.