> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.meetstream.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.meetstream.ai/_mcp/server.

# Bot Status and Error Code Reference

> Reference for MeetStream bot statuses, webhook events, ErrorReason codes and exact messages on Zoom, Google Meet and Microsoft Teams, with causes, fixes and create_bot HTTP errors.

Use this page to turn any bot outcome into a cause and a fix. Look up the `status`, `bot_event`, `ErrorReason` or `message` you received, then follow the link in the **What to do** column.

## Where to read these values

| Source                                                                                           | What you get                                                                                                                                                                |
| ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`GET /api/v1/bots/{bot_id}/status`](/api-reference/api-endpoints/bot-endpoints/get-bot-status)  | `{ "bot_id", "status", "custom_attributes" }`: the current status only.                                                                                                     |
| [`GET /api/v1/bots/{bot_id}/detail`](/api-reference/api-endpoints/bot-endpoints/get-bot-details) | `bot_details.Status`, `bot_details.ErrorReason` and `bot_details.StatusTimeline`. Each timeline entry is `{ "status": true, "timestamp", "message" }`, keyed by stage name. |
| [Webhooks](/guides/webhooks/webhooks-and-events)                                                 | `event`, `bot_event`, `bot_status`, `message`, `status_code`, `timestamp`, and on Google Meet join failures `failure_reason`.                                               |
| [Dashboard bot detail page](/guides/help/debugging-bots#read-the-bot-detail-page)                | The status badge, the **Bot status timeline** with each stage's message, and a friendly label for failures.                                                                 |

> **These values are not a closed enum**
>
> Statuses, `bot_event` names, `ErrorReason` codes and messages grow as MeetStream adds platforms and detection. Treat unknown values gracefully: log them, fall back to the generic handling for the event (for example, treat any unknown terminal as a failure you can retry), and never crash on a value you have not seen. Compare status strings case-insensitively, because some Google Meet paths write `FAILED` and `ERROR` in upper case.

## The bot lifecycle

```mermaid
stateDiagram-v2
    [*] --> Scheduled: join_at
    [*] --> Joining
    Scheduled --> Joining
    Scheduled --> Cancelled
    Scheduled --> Error
    Joining --> InWaitingRoom
    Joining --> Failed
    Joining --> Error
    InWaitingRoom --> InMeeting: admitted
    InWaitingRoom --> Leaving: not admitted
    InMeeting --> RecordingPermissionAllowed: Zoom
    InMeeting --> RecordingPermissionDenied: Zoom
    InMeeting --> Leaving
    RecordingPermissionAllowed --> Leaving
    RecordingPermissionDenied --> Leaving
    Leaving --> Stopped
    Leaving --> Kicked
    Leaving --> NotAllowed
    Leaving --> Denied
    Leaving --> Error
    Stopped --> MediaProcessing
    Kicked --> MediaProcessing
    MediaProcessing --> Done
    Done --> MediaExpired
```

The diagram is simplified: a scheduled bot can also be `Cancelled` before it starts or end in `Error` if it cannot be started, and a join can end early as `Failed` (the meeting blocked it) or `Error`. `Recording` is not drawn because it is recorded in the timeline without changing `status` (see below). Every platform writes `Leaving` immediately before the terminal status, except the Google Meet join blockers, which go straight from `Joining` to `Failed`.

### What each status means

| Status                       | Dashboard label                             | Terminal | Platforms          | Meaning                                                                                                                                                                                                       |
| ---------------------------- | ------------------------------------------- | -------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Scheduled`                  | Scheduled                                   | No       | All                | Created with `join_at` or from a calendar. The bot starts shortly before the join time.                                                                                                                       |
| `Joining`                    | Joining                                     | No       | All                | Dispatched and opening the meeting. Immediate bots are `Joining` as soon as `create_bot` returns `201`.                                                                                                       |
| `InWaitingRoom`              | In Waiting Room                             | No       | All                | The bot has asked to join. Sent on **every** join, even when the host admits instantly, so do not treat it as proof of a lobby.                                                                               |
| `InMeeting`                  | In Meeting                                  | No       | All                | Admitted to the meeting.                                                                                                                                                                                      |
| `Recording`                  | Recording                                   | No       | All                | Recording started. Written to `StatusTimeline` and sent as `bot.recording`, but `status` stays `InMeeting` (or `RecordingPermissionAllowed` on Zoom).                                                         |
| `RecordingPermissionAllowed` | Recording Permission Allowed                | No       | Zoom               | The host granted local recording permission. `status` keeps this value for the rest of the call.                                                                                                              |
| `RecordingPermissionDenied`  | Recording Permission Denied                 | No       | Zoom               | The host denied recording or did not answer within `recording_permission_denied_timeout`. Always followed by `Leaving` and `Stopped`.                                                                         |
| `Leaving`                    | Leaving                                     | No       | All                | Written right before every terminal status.                                                                                                                                                                   |
| `Stopped`                    | Completed (list) / Stopped (timeline)       | Yes      | All                | Clean exit: the meeting ended, an auto-leave timeout fired, you stopped the bot, or the bot lost the meeting. The `message` says which.                                                                       |
| `Kicked`                     | Kicked                                      | Yes      | All                | A participant removed the bot from the meeting. Webhooks carry `bot_status: "Stopped"` with `bot_event: "bot.kicked"`.                                                                                        |
| `NotAllowed`                 | Not Allowed (timeline: Not Admitted)        | Yes      | All                | The bot was never admitted before `waiting_room_timeout`, or a join safety check gave up.                                                                                                                     |
| `Denied`                     | Denied (timeline: Rejected or Not Admitted) | Yes      | All                | The host rejected the join request. On Zoom, also used when Zoom refuses the bot's account.                                                                                                                   |
| `Failed`                     | Failed                                      | Yes      | Google Meet, Teams | The meeting itself blocked the join: invalid link, restricted access, not started, ended, or sign-in required.                                                                                                |
| `Error`                      | Error                                       | Yes      | All                | A sign-in, token, link-format or MeetStream-side problem stopped the bot.                                                                                                                                     |
| `FAILED`, `ERROR`            | Failed, Error                               | Yes      | Google Meet        | Upper-case variants written by some Google Meet join paths. Handle them exactly like `Failed` and `Error`.                                                                                                    |
| `MediaProcessing`            | Media Processing                            | No       | All                | The post-call pipeline is preparing audio, video and transcripts.                                                                                                                                             |
| `Done`                       | Done                                        | Yes      | All                | Post-call processing finished.                                                                                                                                                                                |
| `MediaExpired`               | Media Expired                               | Yes      | All                | The bot's stored media was deleted, either by timed retention or with [`DELETE /api/v1/bots/{bot_id}/delete`](/api-reference/api-endpoints/bot-endpoints/delete-bot-data). A `data_deletion` webhook is sent. |
| `Cancelled`                  | Cancelled                                   | Yes      | All                | A calendar-scheduled bot was cancelled before it joined: the event was deleted, you unscheduled it, or you disconnected the calendar.                                                                         |

> **Note**
>
> `create_bot` returns `"status": "Active"` in its `201` body for immediate bots and `"status": "Scheduled"` for scheduled bots. `Active` is only a response value; the stored status of an immediate bot is `Joining`.

### What happens to `status` after the call

* Bots that were in the meeting (`Stopped` or `Kicked`) move to `MediaProcessing`, then `Done`.
* Bots that never got in (`NotAllowed`, `Denied`, `Failed`, `FAILED`, `ERROR`) keep that status. They still get a `bot.done` webhook, whose `bot_status` repeats the join outcome (for example `NotAllowed`).
* Bots that end in `Error` on Zoom or Teams currently also move to `MediaProcessing` and then `Done`, so their final `status` reads `Done`. To keep the real outcome, store the terminal webhook, or read the `Error` (Zoom) or `Failed` (Teams) entry in `StatusTimeline` and the `ErrorReason` from `/detail`.
* The timeline also records post-call stages: `AudioProcessing` ("Processing Audio"), `VideoProcessing` ("Processing Video"), `Uploading`, `TranscriptionReady` ("Transcript Ready") and `Done`.

## Webhook mapping

Every status change becomes one webhook delivery. Terminal statuses all share `event: "bot.stopped"`; branch on `bot_event` (or `bot_status`) for the reason.

| Status                               | `event`                            | `bot_event`           | `bot_status` on the wire                               |
| ------------------------------------ | ---------------------------------- | --------------------- | ------------------------------------------------------ |
| `Scheduled`                          | `bot.scheduled`                    | `bot.scheduled`       | `Scheduled` (payload adds `scheduled_join_time`)       |
| `Joining`                            | `bot.joining`                      | `bot.joining`         | `Joining`                                              |
| `InWaitingRoom`                      | `bot.in_waiting_room`              | `bot.in_waiting_room` | `InWaitingRoom`                                        |
| `InMeeting`                          | `bot.inmeeting`                    | `bot.inmeeting`       | `InMeeting`                                            |
| `Recording`                          | `bot.recording`                    | `bot.recording`       | `Recording`                                            |
| `RecordingPermissionAllowed` (Zoom)  | `bot.recording_permission_allowed` | same                  | `RecordingPermissionAllowed`                           |
| `RecordingPermissionDenied` (Zoom)   | `bot.recording_permission_denied`  | same                  | `RecordingPermissionDenied`                            |
| `Leaving`                            | `bot.leaving`                      | `bot.leaving`         | `Leaving`                                              |
| `Stopped`                            | `bot.stopped`                      | `bot.stopped`         | `Stopped`                                              |
| `Kicked`                             | `bot.stopped`                      | `bot.kicked`          | `Stopped`                                              |
| `Denied`                             | `bot.stopped`                      | `bot.denied`          | `Denied`                                               |
| `NotAllowed`                         | `bot.stopped`                      | `bot.notallowed`      | `NotAllowed`                                           |
| `Failed`, `Error`, `FAILED`, `ERROR` | `bot.stopped`                      | `bot.failed`          | the status as written                                  |
| Post-call finished                   | `bot.done`                         | `bot.done`            | `Done`, or the join outcome for bots that never got in |

> **Note**
>
> On Google Meet, `bot.recording` is currently delivered only for bots created with a `callback_url`. The `Recording` entry is always written to `StatusTimeline`.

You may also receive informational post-call events `bot.uploading` and `bot.transcriptionready` (their `bot_status` equals the event name), and `bot.error` in two cases: a live transcription provider failed while the bot stays in the meeting (`bot_status: "InMeeting"`), or a scheduled bot was rejected when it tried to start (see [scheduling reasons](#scheduling-and-safety-checks-all-platforms)).

### `status_code` in webhooks

`status_code` is a hint, not the outcome. Always branch on `bot_event` or `bot_status`.

| `bot_status`                            | Zoom     | Google Meet                    | Microsoft Teams |
| --------------------------------------- | -------- | ------------------------------ | --------------- |
| `Stopped`, `Kicked` (`bot.kicked`)      | 200      | 200                            | 200             |
| `NotAllowed`, `Denied`                  | 500      | 500                            | 500             |
| `Error` (and `FAILED`, `ERROR` on Meet) | 500      | 500                            | 500             |
| `Failed`                                | not used | **500**, with `failure_reason` | 500             |
| `RecordingPermissionDenied`             | 500      | not used                       | not used        |
| `bot.done`                              | 200      | 200                            | 200             |

### Message prefixes

MeetStream prefixes failure messages so you can route alerts without parsing the rest of the text:

* `Error: ` for `Error`, `ERROR` and `FAILED` (something broke: credentials, tokens, link format, or a MeetStream-side problem).
* `Failed: ` for `NotAllowed`, `Denied` and `Failed` (the meeting, host or lobby decided).
* The prefix is never doubled, and messages that already start with `Error:` or `Failed:` are left as they are.

## Error reasons by platform

`ErrorReason` is a stable PascalCase code on `GET /api/v1/bots/{bot_id}/detail`. Google Meet and Microsoft Teams bots set it for join failures and for unexpected exits. Zoom bots describe the cause in `message` instead, so the Zoom section below is keyed by message. The scheduling and safety-check reasons apply to every platform.

The dashboard shows a friendly label for failures (for example "Invalid meeting link" or "Bot not allowed to join meeting") and hides internal-only codes. The API returns the code.

### Scheduling and safety checks (all platforms)

| Code · status                          | Message                                                                                   | What it means                                                                                                                                                                                                                                              | What to do                                                                                                                               |
| -------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `ScheduledDispatchExhausted` · `Error` | `Scheduled dispatch did not start within the retry window`                                | A scheduled bot could not be started within 20 minutes after its join time, because of a temporary MeetStream-side problem.                                                                                                                                | Create a new bot without `join_at` if the meeting is still running. If it repeats, send the `bot_id` to [support](/guides/help/support). |
| `ScheduledDispatchRejected` · `Error`  | The rejection message from `create_bot` (see [HTTP errors](#http-errors-from-create_bot)) | At join time MeetStream re-checked the saved request and it failed with a 4xx, for example because the signed-in login pool was full or empty, a login domain or Zoom credentials were removed, or the link became invalid. A `bot.error` webhook is sent. | Read the message in `StatusTimeline.Error`, fix the cause, and schedule a new bot.                                                       |
| `InsufficientCredits` · `Error`        | `Low credits please recharge`                                                             | A scheduled bot reached its join time while the pay-as-you-go balance was below the minimum. A `bot.error` webhook is sent.                                                                                                                                | Add credits in **Billing**, then schedule a new bot.                                                                                     |
| `JoinTimeout` · `NotAllowed`           | none in the timeline                                                                      | The bot stayed in `Joining` for about 60 minutes without reaching the lobby or the meeting, and a safety check closed it. You may not receive a terminal webhook for this case.                                                                            | Create a new bot. If you track bots by webhook, also poll `/status` for bots that stay in `Joining` for a long time.                     |

### Google Meet

**Join blocked by the meeting.** Status `Failed`, `bot_event: "bot.failed"`, `status_code: 500`, and the webhook includes `failure_reason`.

| Code · `failure_reason`                        | Message                                              | What happened                                                                                                                                                                                                           | What to do                                                                                                                                                                                                          |
| ---------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `InvalidMeetingLink` · `invalid_meeting_link`  | `Failed: Invalid meeting link`                       | Meet showed "Check your meeting code", "Invalid video call name", "Meeting not found" or "The video call wasn't found". Typo in the code, a deleted meeting, or a link that is not a Meet meeting.                      | Use the `https://meet.google.com/abc-defg-hij` form and open it in a browser to confirm it works. See [Google Meet](/guides/platforms/google-meet).                                                                 |
| `MeetingRestricted` · `meeting_restricted`     | `Failed: Meeting access is restricted`               | Meet showed "Access to this meeting is restricted", "You don't have permission to join" or "Only people invited by the organizer". The meeting only admits people from the host's organization or people on the invite. | Use a [signed-in bot](/guides/app-integrations/google-signed-in-bots) from an allowed domain, or ask the host to relax meeting access. See [lobby troubleshooting](/guides/app-integrations/gmeet-lobby-admission). |
| `MeetingNotStarted` · `meeting_not_started`    | `Failed: Meeting has not started`                    | Meet showed "This meeting has not started". The bot arrived before the meeting could be joined.                                                                                                                         | Start the meeting first, or schedule the bot with `join_at`. See [scheduling bots](/guides/features/scheduling-bots).                                                                                               |
| `MeetingEnded` · `meeting_ended`               | `Failed: Meeting has ended`                          | Meet showed "This meeting has ended" or "Your meeting code has expired". The meeting is over or the code expired.                                                                                                       | Check the link belongs to a current meeting.                                                                                                                                                                        |
| `SignInRequired` · `sign_in_required`          | `Failed: Sign in required`                           | Meet redirected the bot to Google sign-in: the meeting does not accept anonymous guests.                                                                                                                                | Use a [signed-in bot](/guides/app-integrations/google-signed-in-bots).                                                                                                                                              |
| `GoogleSignInFailed` · `google_sign_in_failed` | `Failed: Configured Google sign-in failed`           | A signed-in bot could not complete Google sign-in. The bot never falls back to joining as a guest.                                                                                                                      | Check the login is active and the domain's SSO settings match the [signed-in bot guide](/guides/app-integrations/google-signed-in-bots).                                                                            |
| `CantJoinCall` · `cant_join_call`              | Starts with `Failed: You can't join this video call` | Meet showed "You can't join this video call", "meeting" or "call". Google refused the guest join, even after MeetStream retried.                                                                                        | Use a [signed-in bot](/guides/app-integrations/google-signed-in-bots), confirm the meeting allows external guests, and retry later.                                                                                 |

**Lobby and host decisions.**

| Code · status                       | Message                           | What it means                                                                                                                         | What to do                                                                                                                                                                                                                     |
| ----------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `WaitingRoomTimeout` · `NotAllowed` | `Failed: Not admitted to meeting` | Nobody admitted the bot within `waiting_room_timeout` (60 to 600 seconds, default 600). The bot withdraws its request when it leaves. | Make sure someone who can admit is in the meeting and sees the request. See [lobby troubleshooting](/guides/app-integrations/gmeet-lobby-admission), or use a [signed-in bot](/guides/app-integrations/google-signed-in-bots). |
| `HostDenied` · `Denied`             | `Failed: Host denied join`        | Meet showed "You've been denied entry to this meeting" or "Someone in the call denied your request to join".                          | A person decided; ask the host to admit the bot next time.                                                                                                                                                                     |
| `JoinHang` · `NotAllowed`           | Starts with `Failed: `            | The join page did not reach the lobby within about five minutes.                                                                      | Create a new bot. If it repeats for the same meeting, contact [support](/guides/help/support).                                                                                                                                 |

![Bot status timeline with Joining, In Waiting Room, Leaving and Not Admitted entries, final status NotAllowed after 10 minutes 23 seconds](/_fern-img/51e623bc16ea063c241094cd5c55b8b8d3bc8caa27fc2b91403654acc414c1b4.webp)

**Temporary Google Meet errors.** MeetStream retries these automatically (up to three attempts). If every attempt fails, the bot ends as `Failed` with a message ending in `(after 3 attempts)`.

| `ErrorReason`        | Message                                                                     | What to do            |
| -------------------- | --------------------------------------------------------------------------- | --------------------- |
| `NetworkError`       | `Failed: Google Meet reported a network problem (after 3 attempts)`         | Retry with a new bot. |
| `MeetTransientError` | `Failed: Google Meet reported a temporary error (after 3 attempts)`         | Retry with a new bot. |
| `BrowserUnstable`    | `Failed: Browser or display became unstable during join (after 3 attempts)` | Retry with a new bot. |

**MeetStream-side join errors.** Status `FAILED` or `ERROR`, usually with the message `Failed: Could not join meeting` or a short detail. These are not caused by your request.

`JoinFailed`, `JoinButtonTimeout`, `ClickJoinFailed`, `MeetingNotLoaded`, `NavigateFailed`, `ServicesInitFailed`, `BrowserInitFailed`, `JoinFlowException`, `FillDisplayNameFailed`, `WaitForMeetingFailed`, `BrowserPageLost`.

What to do: create a new bot. If the same meeting fails repeatedly, send the `bot_id` to [support](/guides/help/support).

**Exits during the meeting.** The bot was in the meeting, so the recording up to that point is processed normally.

| Code · status                      | Message                                             | What it means                                              |
| ---------------------------------- | --------------------------------------------------- | ---------------------------------------------------------- |
| `MeetingEndedByHost` · `Stopped`   | `Meeting ended`                                     | Meet showed that the meeting ended.                        |
| `KickedByHost` · `Kicked`          | `Bot was removed from the meeting by a participant` | Someone removed the bot.                                   |
| `ConnectionLost` · `Stopped`       | `Bot lost network connection to Google Meet`        | Meet reported a lost connection.                           |
| `LeftVoluntarily` · `Stopped`      | `Bot left the meeting`                              | Meet showed that the bot left.                             |
| `MediaConnectionsLost` · `Stopped` | `Bot lost media connections to Google Meet`         | Audio stopped arriving from Meet.                          |
| `MeetOffDomain` · `Stopped`        | `Bot is no longer on a Google Meet URL`             | The meeting page navigated away from Google Meet.          |
| `MeetingExitUnknown` · `Stopped`   | `Bot left the meeting (post-call screen)`           | Meet showed its post-call screen without a specific cause. |

Automatic-leave exits on Google Meet use `Stopped` without an `ErrorReason`: `Bot exited the call: No one joined the meeting`, `Bot exited the call: Everyone left the meeting`, `Bot exited the call: Voice inactivity for Ns (threshold: Ns)`, and `Bot exited the call: Only other bots remain (...)` with the matched names. See [automatic leave](/guides/features/automatic-leave-configuration).

### Microsoft Teams

**Lobby, host and meeting decisions.**

| Code · status                       | Message                                             | What it means                                                                                                                                                                                           | What to do                                                                                                                                                                                                                                                                                         |
| ----------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `WaitingRoomTimeout` · `NotAllowed` | `Failed: Bot not allowed to join meeting`           | Nobody admitted the bot from the lobby within `waiting_room_timeout` (60 to 1800 seconds, default 1200). Teams has no separate "meeting not started" signal, so a meeting nobody starts also ends here. | Admit the bot, or have the organizer change **Who can bypass the lobby** in the meeting options (anonymous guests bypass only when it is set to **Everyone**). See [Microsoft Teams](/guides/platforms/microsoft-teams) and [signed-in Teams bots](/guides/app-integrations/teams-signed-in-bots). |
| `JoinHang` · `NotAllowed`           | `Failed: Bot not allowed to join meeting`           | The join did not complete within `waiting_room_timeout`. Handle it like `WaitingRoomTimeout`.                                                                                                           | Same as above.                                                                                                                                                                                                                                                                                     |
| `HostDenied` · `Denied`             | `Failed: Denied to join meeting`                    | Teams showed that the request was declined or not admitted.                                                                                                                                             | A person decided; ask the organizer to admit the bot.                                                                                                                                                                                                                                              |
| `KickedByHost` · `Kicked`           | `Bot was removed from the meeting by a participant` | Teams showed "You've been removed from this meeting".                                                                                                                                                   | Nothing to fix in code.                                                                                                                                                                                                                                                                            |
| `MeetingRestricted` · `Failed`      | `Failed: Meeting access is restricted`              | Teams showed that the bot does not have permission to join.                                                                                                                                             | Use a [signed-in bot](/guides/app-integrations/teams-signed-in-bots) from an allowed tenant, or ask the organizer to allow the bot.                                                                                                                                                                |
| `InvalidMeetingLink` · `Failed`     | `Failed: Invalid meeting link`                      | Teams could not find a meeting for the link.                                                                                                                                                            | Copy the full join link from the invite. See [supported link formats](/navigation#joining).                                                                                                                                                                                                        |

**Sign-in walls and signed-in bots.**

| Code · status                                                       | Message                                                         | What it means                                                                                                                                                                                                                                                   | What to do                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TeamsSessionNotApplied` · `Error`                                  | `Error: Teams signed-in session was not applied to the meeting` | Teams asked the bot to sign in ("sign in to join this meeting", "only people in the organization can join") or showed a guest name field to a signed-in bot. **This also happens to anonymous bots** when the organizer's tenant does not allow anonymous join. | For anonymous bots, the organizer's tenant admin can turn on **Anonymous users can join a meeting** (Teams admin center, **Meetings** > **Meeting settings**, and the meeting policy of the same name; see [Microsoft's lobby settings](https://learn.microsoft.com/en-us/microsoftteams/who-can-bypass-meeting-lobby)), or you can use a [signed-in bot](/guides/app-integrations/teams-signed-in-bots). For signed-in bots, check the login and retry. |
| `TeamsSessionAuthFailed` · `Error`                                  | `Error: Teams browser session authentication failed`            | Teams showed "We couldn't authenticate you" or "app failed to init".                                                                                                                                                                                            | Retry. For signed-in bots, check the account in the [signed-in guide](/guides/app-integrations/teams-signed-in-bots).                                                                                                                                                                                                                                                                                                                                    |
| `TeamsAppInitFailed` · `Error`                                      | Starts with `Error: `                                           | A signed-in bot kept seeing "app failed to init" after two automatic retries.                                                                                                                                                                                   | Retry with a new bot.                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `TeamsLoginBadCredentials` · `Error`                                | Starts with `Error: Teams sign-in failed: `                     | Microsoft rejected the password. MeetStream never retries a wrong password and marks the login inactive.                                                                                                                                                        | Update the password, then reactivate the login in **Integrations** > **Teams Bots**.                                                                                                                                                                                                                                                                                                                                                                     |
| `TeamsLoginAccountDisabled` · `Error`                               | Starts with `Error: Teams sign-in failed: `                     | The Microsoft account is disabled. The login is marked inactive.                                                                                                                                                                                                | Re-enable the account in your tenant, then reactivate the login.                                                                                                                                                                                                                                                                                                                                                                                         |
| `TeamsLoginMfaRequired` · `Error`                                   | Starts with `Error: Teams sign-in failed: `                     | Microsoft asked for more information (multifactor authentication). MFA is not supported for bot accounts.                                                                                                                                                       | Exclude the bot account from MFA as described in the [signed-in guide](/guides/app-integrations/teams-signed-in-bots).                                                                                                                                                                                                                                                                                                                                   |
| `TeamsLoginVerificationRequired` · `Error`                          | Starts with `Error: Teams sign-in failed: `                     | Microsoft asked the account to verify its identity.                                                                                                                                                                                                             | Complete verification for the account once in a browser, then retry.                                                                                                                                                                                                                                                                                                                                                                                     |
| `TeamsLoginUnknownPage` · `Error`                                   | Starts with `Error: Teams sign-in failed: `                     | Sign-in stopped on a page MeetStream does not recognize (for example a new prompt from your tenant).                                                                                                                                                            | Sign in to the account once in a browser to clear any prompt, then retry.                                                                                                                                                                                                                                                                                                                                                                                |
| `TeamsAppSessionNotEstablished` · `Error`                           | Starts with `Error: Teams sign-in failed: `                     | Sign-in succeeded but Teams did not open a session.                                                                                                                                                                                                             | Confirm the account has a Teams license, then retry.                                                                                                                                                                                                                                                                                                                                                                                                     |
| `TeamsCredentialsFetchFailed`, `TeamsSignInBrowserFailed` · `Error` | Starts with `Error: Teams sign-in failed: `                     | MeetStream-side sign-in problem.                                                                                                                                                                                                                                | Retry with a new bot.                                                                                                                                                                                                                                                                                                                                                                                                                                    |

**MeetStream-side join errors.**

| Code · status                                        | Message                                       | What to do                                                                                                          |
| ---------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `JoinButtonTimeout` · `Error`                        | `Error: Join on web timeout after 3 attempts` | The Teams pre-join screen did not load in three attempts. Check the link opens in a browser, then retry.            |
| `JoinFlowException` · `Error`                        | Starts with `Error: `                         | Retry with a new bot.                                                                                               |
| `TeamsInternalWebSocketUnavailable` · `Error`        | Starts with `Error: `                         | Retry with a new bot. The bot stopped before clicking Join.                                                         |
| `ChromeDriverDead`, `JoinInputInfraFailed` · `Error` | Starts with `Error: `                         | MeetStream may retry the join automatically. If this is the final reason on the bot, create a new bot.              |
| `JoinRetryExhausted` · `Failed`                      | Starts with `Failed: Join failed after`       | Several automatic join attempts failed. Create a new bot and contact [support](/guides/help/support) if it repeats. |

Normal Teams exits use `Stopped` without an `ErrorReason`: `Bot exited the call: Meeting was ended by the host`, `Bot exited the call: Everyone left the meeting`, `Bot exited the call: Voice inactivity timeout`, `Bot stopped via API request`, and `Bot exited the call`.

### Zoom

Zoom bots report the cause in `message`. Match on the text after the prefix.

**Admission and permissions.**

| Status                                      | Message                                                                                                        | What it means                                                                                                                                                                                           | What to do                                                                                                                                                    |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NotAllowed`                                | `Failed: Not admitted to meeting`                                                                              | The bot was not admitted within `waiting_room_timeout` (60 to 1200 seconds, default 600). **The same timer covers a host who never starts the meeting**, so this can also mean the meeting never began. | Admit the bot, start the meeting on time, or let participants join before the host. See [Zoom](/guides/platforms/zoom).                                       |
| `Denied`                                    | `Failed: Zoom account is restricted and not allowed to join this meeting`                                      | Zoom refused the join for the bot's account.                                                                                                                                                            | Check the meeting allows guests, or join as a Zoom user with `zoom.zak_url`. See [Zoom authenticated bots](/guides/app-integrations/zoom-authenticated-bots). |
| `Kicked`                                    | `Bot was removed from the meeting by a participant`                                                            | Someone removed the bot.                                                                                                                                                                                | Nothing to fix in code.                                                                                                                                       |
| `RecordingPermissionDenied`, then `Stopped` | `Failed: Recording permission denied by host`, then `Bot exited the call: Recording permission denied by host` | The host clicked deny on the recording request. MeetStream does not ask again.                                                                                                                          | Ask the host to allow recording, or join with `zoom.zak_url` as a user who can record.                                                                        |
| `RecordingPermissionDenied`, then `Stopped` | `Failed: Recording permission timeout`, then `Bot exited the call: Recording permission timeout`               | The host did not answer within `recording_permission_denied_timeout` (60 to 300 seconds, default 60).                                                                                                   | Raise the timeout, or ask the host to watch for the prompt.                                                                                                   |

**The meeting could not be joined.** These end as `Stopped` (not a failure status), so check the message.

| Message                                                 | What it means                                                                                                                                                                                                                                                                                | What to do                                                                                                              |
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `Meeting not yet started`                               | Zoom reported that the meeting has not started. The bot stops immediately instead of waiting.                                                                                                                                                                                                | Start the meeting first, allow join before host, or schedule with `join_at`.                                            |
| `Meeting does not exist or host has not started it yet` | Zoom could not find a running meeting for that ID.                                                                                                                                                                                                                                           | Check the meeting ID and that the meeting is live.                                                                      |
| `Unable to join external meeting`                       | Zoom refused because the meeting belongs to a different Zoom account than your Meeting SDK app. Zoom requires apps to [authorize joins outside their own account](https://developers.zoom.us/changelog/meeting-sdk/requiring-authorization-for-meetings-joined-outside-of-an-apps-account/). | Pass `zoom.obf_url` or `zoom.zak_url`. See [Zoom authenticated bots](/guides/app-integrations/zoom-authenticated-bots). |
| `Meeting failed`                                        | Zoom rejected the join for a reason MeetStream does not map yet.                                                                                                                                                                                                                             | Check the passcode in the link (`?pwd=`), the meeting state, and retry.                                                 |

**The meeting ended.** Status `Stopped`.

| Message                                                    | What it means                                                         |
| ---------------------------------------------------------- | --------------------------------------------------------------------- |
| `Meeting ended by host`                                    | The host ended the meeting for everyone.                              |
| `Meeting ended - host never joined`                        | Zoom ended a join-before-host meeting because the host never arrived. |
| `Meeting ended - host started another meeting`             | The host started a different meeting, which ended this one.           |
| `Meeting ended - free meeting time limit reached`          | The host's Zoom plan time limit ended the meeting.                    |
| `Meeting disconnected before Zoom emitted an ended status` | The connection closed without an end reason from Zoom.                |
| `Meeting ended`                                            | Any other end reason.                                                 |

**Automatic leave and API stops.** Status `Stopped`: `Bot exited the call: Voice inactivity timeout`, `Bot exited the call: Everyone left the meeting`, `Bot exited the call: Maximum recording time reached`, `Bot exited the call: only other bots remain (bot_detection.using_participant_names)`, `Bot stopped via API request`, and `Bot exited the call`. See [automatic leave](/guides/features/automatic-leave-configuration).

**Errors.** Status `Error`, `bot_event: "bot.failed"`.

| Message                                                                                                      | What it means                                                                                                                                                         | What to do                                                                                                                                                      |
| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Error: Failed to join meeting: Invalid meeting_link format`                                                 | The link has no `/j/<meeting-id>` path. Personal links (`/my/`), webinar links (`/w/`), `/s/` and `/wc/join/` links are accepted by the API but cannot be joined yet. | Use `https://zoom.us/j/<meeting-id>?pwd=<passcode>`. See [supported links](/navigation#joining).                                                                |
| `Error: Failed to join meeting: ZAK token is required but could not be fetched`                              | Your `zoom.zak_url` did not return a token within 15 seconds, returned an error, or returned an unreadable body. There is no fallback to a guest join.                | Check your token server. See [Zoom authenticated bots](/guides/app-integrations/zoom-authenticated-bots).                                                       |
| `Error: Failed to join meeting: OBF token is required but could not be fetched`                              | Same, for `zoom.obf_url`.                                                                                                                                             | Check your token server and that the authorizing user is in the meeting.                                                                                        |
| `Error: Failed to join meeting: JoinMeeting failed with code N`                                              | Zoom rejected the join request with an SDK error code.                                                                                                                | Check the meeting ID and passcode, then retry.                                                                                                                  |
| `Error: Failed to connect to meeting`                                                                        | The bot could not connect within 60 seconds. A wrong or missing passcode is a common cause.                                                                           | Copy the link with its `?pwd=` passcode from the invite.                                                                                                        |
| `Error: Zoom authentication failed with result: N`                                                           | Zoom rejected your app's Meeting SDK credentials.                                                                                                                     | Re-enter the Client ID and Client Secret in **Integrations** > **Zoom**. See [Zoom Marketplace app setup](/guides/app-integrations/zoom-marketplace-app-setup). |
| `Error: Failed to start recording`, `Error: Zoom SDK initialization error: ...` and other `Error: ` messages | MeetStream-side problem.                                                                                                                                              | Retry with a new bot; contact [support](/guides/help/support) with the `bot_id` if it repeats.                                                                  |

## HTTP errors from `create_bot`

These come back synchronously, before a bot exists, so no status or webhook is created. The body is `{ "message": "..." }` unless noted. See [Errors](/errors) for the general API error model.

| HTTP | Message or body                                                                                                                                                                                                                                                                | When                                                                        | What to do                                                                                                                                           |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `meeting_link host 'acme.example.com' is not a supported meeting platform. Expected Google Meet (meet.google.com), Zoom (*.zoom.us / *.zoomgov.com), or Microsoft Teams (teams.microsoft.com / teams.live.com / *.teams.microsoft.us), or WhatsApp Calls (call.whatsapp.com).` | The host is not a supported platform.                                       | Use a Zoom, Google Meet or Teams join link. See [supported platforms](/navigation).                                                                  |
| 400  | `meeting_link looks like the GMeet site root or a marketing page, not a meeting URL: '...'` (the platform name varies: `GMeet`, `Zoom`, `Teams`, `WhatsApp`)                                                                                                                   | The link is a site root or a page such as `/signin`, `/login`, `/download`. | Copy the meeting's join link.                                                                                                                        |
| 400  | `meeting_link must use http:// or https://.`                                                                                                                                                                                                                                   | The link uses another scheme, such as `zoommtg://`.                         | Use the web join link.                                                                                                                               |
| 400  | `Zoom bots require a connected Zoom app or Zoom credentials in the user profile`                                                                                                                                                                                               | No Zoom Meeting SDK credentials are configured.                             | Add your Client ID and Secret in **Integrations** > **Zoom**. See [Zoom Marketplace app setup](/guides/app-integrations/zoom-marketplace-app-setup). |
| 400  | `Pass only one of zoom.zak_url or zoom.obf_url, not both`, `zoom.zak_url must use https`, `zoom.zak_url and zoom.obf_url are only supported for Zoom meetings`                                                                                                                 | Invalid Zoom token settings.                                                | See [Zoom authenticated bots](/guides/app-integrations/zoom-authenticated-bots).                                                                     |
| 400  | `waiting_room_timeout for GMeet must not exceed 600 seconds (got 900)` and similar range messages                                                                                                                                                                              | An `automatic_leave` value is out of range.                                 | Use the [per-platform ranges](/guides/features/automatic-leave-configuration).                                                                       |
| 400  | `google_meet.google_login_domain '...' is not registered. Register it via the admin Google login domains API first.`                                                                                                                                                           | Signed-in Google Meet bot for an unregistered domain.                       | Register the domain. See [Google signed-in bots](/guides/app-integrations/google-signed-in-bots).                                                    |
| 400  | `teams.teams_login_domain '...' is not registered. Register it via the admin Teams login domains API first.`                                                                                                                                                                   | Same, for Teams.                                                            | See [Teams signed-in bots](/guides/app-integrations/teams-signed-in-bots).                                                                           |
| 400  | `teams.login_required is not supported for personal Teams (teams.live.com) links`                                                                                                                                                                                              | Signed-in bots only work for work or school Teams meetings.                 | Remove `teams.login_required`, or use a `teams.microsoft.com` link.                                                                                  |
| 400  | `join_at must be in the future`                                                                                                                                                                                                                                                | `join_at` is in the past.                                                   | Send a future time in ISO 8601.                                                                                                                      |
| 400  | `Invalid join_at format: Cannot schedule bot more than 90 days (3 months) in the future. Requested schedule is N days in the future.`                                                                                                                                          | `join_at` is more than 90 days ahead.                                       | Schedule closer to the meeting.                                                                                                                      |
| 403  | `{"message": "Forbidden"}`                                                                                                                                                                                                                                                     | Missing or invalid API key.                                                 | Send `Authorization: Token YOUR_API_KEY`. See [Errors](/errors#authentication-and-access-errors-403).                                                |
| 403  | `{"error": "Low credits please recharge", "available_credits": 0.12, "minimum_required": 0.175}`                                                                                                                                                                               | Pay-as-you-go balance is below 30 minutes of usage.                         | Add credits in **Billing**.                                                                                                                          |
| 403  | `{"error": "Low credits please recharge", "active_bots": 1}`                                                                                                                                                                                                                   | Balance under \$1 and a bot is already running.                             | Add credits, or wait for the running bot to finish.                                                                                                  |
| 403  | `google_meet.google_login_domain '...' is not registered to this account`, or the same for `teams.teams_login_domain`                                                                                                                                                          | The domain belongs to another MeetStream account.                           | Use a domain registered to your account.                                                                                                             |
| 404  | `teams.sign_in_email '...' not found under this domain`                                                                                                                                                                                                                        | The pinned Teams login does not exist.                                      | Check `teams.sign_in_email`, or omit it to auto-pick.                                                                                                |
| 409  | `teams.sign_in_email '...' is currently in use` or `... has been deactivated; rotate its password or add accounts`                                                                                                                                                             | The pinned Teams login is busy or inactive, and `strict_email` is true.     | Wait, reactivate the login, or set `strict_email: false`.                                                                                            |
| 409  | `{"message": "deduplication_key already bound to a different meeting", ...}`                                                                                                                                                                                                   | A `deduplication_key` was reused for another meeting link.                  | See [deduplication](/guides/features/deduplication-idempotency-keys).                                                                                |
| 429  | `All Teams logins under domain '...' are currently in use`                                                                                                                                                                                                                     | Every Teams login is serving a bot (one bot per login at a time).           | Add more logins or retry later.                                                                                                                      |
| 429  | `All N active logins under domain '...' are at capacity (30 active sessions each)`, `No active Google logins are registered under domain '...'`, `Requested sign_in_email '...' is not a registered active login under domain '...'`                                           | No Google login could be allocated.                                         | Add or activate logins, or relax `sign_in_email` / `strict_email`.                                                                                   |
| 507  | `{ "bot_id", "transcript_id": null, "meeting_url", "status" }`                                                                                                                                                                                                                 | Replay of a request with the same `Idempotency-Key`.                        | Treat as success; no new bot was created. See [Errors](/errors#idempotent-replay-507).                                                               |

> **Note**
>
> For scheduled bots, the signed-in login checks run again at join time. If they fail then, the bot ends as `Error` with `ErrorReason: "ScheduledDispatchRejected"` instead of returning an HTTP error.

### Errors from in-meeting commands

Commands such as send message, send image, pause and resume go to a running bot.

| HTTP | Body                                                                                                   | When                                                                                                                                     |
| ---- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `{"error": "Command 'screenshot' is not supported on zoom bots.", "code": "unsupported_command", ...}` | The platform does not implement that command. Zoom has no screenshot command; WhatsApp calls do not support chat, images or screenshots. |
| 409  | `{"error": "Bot is not currently in a meeting.", "bot_status": "InWaitingRoom", "detail": "..."}`      | The bot is not in the meeting yet (or has left). Pause and resume also need the bot to be admitted.                                      |
| 409  | pause or resume when already paused or resumed                                                         | Nothing to do; the recording is already in that state.                                                                                   |

## Related

#### [Debugging bots](/guides/help/debugging-bots)

Read the dashboard timeline and triage a failed bot step by step.

#### [Webhooks and events](/guides/webhooks/webhooks-and-events)

Payload shapes, signing and delivery behavior.

#### [Automatic leave](/guides/features/automatic-leave-configuration)

Every timeout, its range, and which platforms honor it.

#### [Meeting platforms supported](/navigation)

What each platform supports, side by side.