> 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.

# MeetStream — Microsoft Teams Signed-In Bots

How to send a MeetStream Teams bot in as a **real, signed-in Microsoft 365
identity** instead of an anonymous guest.

By default, a MeetStream Teams bot joins as a guest: it lands on the prejoin
screen, types its display name, and asks to be let in. That fails outright
if the meeting organizer has disabled anonymous join — the bot hits a sign-in
wall with no fallback. A **signed-in bot** carries a real Microsoft 365
account and can join those meetings directly.

MeetStream never asks you to give up your production Microsoft 365 tenant —
you register a dedicated bot account once, and every bot you create against
that account signs in as it automatically. You never re-send the password
per join; you gave it to us once at registration, and can rotate or revoke
it at any time.

**Endpoint:** `POST /api/v1/bots/create_bot`  
**Auth:** `Authorization: Token <your MeetStream user API key>`

---

## 1) What you need before you start

**A dedicated Microsoft 365 tenant — not your production one.** Getting a bot
account ready for automated sign-in requires org-wide security settings
(disabling security defaults, disabling self-service password reset) that
you should never apply to real employee accounts. One dedicated tenant covers
all of your MeetStream bot accounts — you don't need one per end customer.

1. Buy **Microsoft 365 Business Basic** (or higher). Teams Essentials is
   untested — use Business Basic or above.
2. In the Microsoft 365 admin center, create a **standard, non-admin user**
   for each bot account you want. Assign it a Teams license, and set its
   display name and profile picture now — that's what meeting participants
   will see, since a signed-in bot's identity always comes from the
   Microsoft account.
3. In Entra ID:
   - **Disable** "security defaults" (otherwise MFA registration blocks the
     very first automated sign-in).
   - Set self-service password reset to **None** for these accounts.
4. Record each bot account's email and password — you'll need them once, to
   register the account with MeetStream (§3).

Only **Microsoft 365 (work/school) Teams** is supported. Personal Teams
(`teams.live.com`) accounts cannot be used for signed-in bots.

---

## 2) How it works, at a glance

| | Guest bot (default) | Signed-in bot |
|---|---|---|
| Identity in the meeting | Anonymous guest, labeled `(Guest)` / `(Unverified)` | Your Microsoft 365 account |
| Display name / avatar | `bot_name` you set on `create_bot` | Comes from the Microsoft account, overrides `bot_name` |
| Can join sign-in-required meetings | No | Yes |
| Bots per account, at once | N/A | **1** — Teams merges same-email sign-ins into a single attendee, so give each bot its own account |
| Your account password sent per join | N/A | **No** — you register it once; MeetStream doesn't re-collect it on every call |

Set up is two API calls, done once (or once per bot account): register your
tenant domain, then add each bot account. After that, `create_bot` just
references the domain.

---

## 3) Register your tenant and bot accounts

### Register your domain

`POST /api/v1/teams-login-domains`

```json
{
  "domain": "bots.acme.com",
  "name": "Acme bot tenant",
  "login_mode": "always"
}
```

Set `login_mode` to `"always"` — this guarantees every bot for this domain
joins signed in. (`if_required`, which would only sign in when a meeting
demands it, is not yet supported for Teams; use `"always"` for now.)

### Add a bot account

`POST /api/v1/teams-logins`

```json
{
  "domain": "bots.acme.com",
  "email": "bot1@bots.acme.com",
  "password": "<account password>",
  "is_active": true
}
```

The password is **write-only** — no API response ever returns it, including
`GET`. The account is available for a bot to use immediately; there's no
provisioning delay to wait out.

If an account's password changes, `PATCH /api/v1/teams-logins/{login_id}`
with a new `password` — it takes effect on the account's next join. If a bad
password causes a join to fail, MeetStream deactivates the account
automatically (`is_active` flips to `false`) so it's skipped until you rotate
the password.

**Provisioning rule of thumb:** unlike some other platforms, Teams allows
exactly **one bot per account at a time**. If you need 10 concurrent
signed-in Teams bots, register 10 accounts.

---

## 4) Create a signed-in bot

`POST /api/v1/bots/create_bot`

```json
{
  "meeting_link": "https://teams.microsoft.com/l/meetup-join/...",
  "bot_name": "MeetStream Notetaker",
  "teams": {
    "login_required": true,
    "teams_login_domain": "bots.acme.com"
  }
}
```

| Field | Type | Required | Behaviour |
|---|---|---|---|
| `login_required` | bool | Yes (to opt in) | Set `true` to request a signed-in join. |
| `teams_login_domain` | string | Yes, if `login_required` | The domain you registered in §3. Must belong to your account. |
| `sign_in_email` | string | No | Pin the bot to one specific account instead of auto-picking. |
| `strict_email` | bool | No, default `true` | With `sign_in_email`: `true` fails if that exact account is busy or unhealthy; `false` falls back to any other available account in the domain. |

Everything else on `create_bot` (recording options, webhooks, etc.) works
the same as any other bot — see the
[Create Bot Payload Reference](/api-reference/create-bot-payload-reference).

Note: because your Microsoft account's own name and picture are shown to
meeting participants, `bot_name` and `bot_image_url` are **not** applied on a
signed-in join.

---

## 5) Troubleshooting

| Symptom | What to check |
|---|---|
| `400` "not registered" | The domain in `teams_login_domain` hasn't been registered via §3, or was typed wrong. |
| `403` on domain/account use | The domain or account belongs to a different MeetStream account than the caller's. |
| `404` on `sign_in_email` | That email isn't registered under `teams_login_domain`. |
| `409` on `sign_in_email` with `strict_email: true` | That specific account is currently in use by another bot, or has been deactivated after a prior sign-in failure — rotate its password or set `strict_email: false`. |
| `409`, no `sign_in_email` | None of the domain's accounts are both active and free right now. Wait, or add/rotate an account. |
| `429` "all Teams logins ... in use" | Every account in the domain is currently leased to another bot. Add more accounts for higher concurrency. |
| Bot joins as an anonymous guest, no error | Double-check `login_required: true` is actually inside the `teams` object and the request body is valid JSON — a malformed `teams` block is dropped rather than causing the whole request to fail closed. |
| Bot's camera/mic don't match your account's usual defaults | The bot always explicitly turns audio/video on or off per your `create_bot` recording settings, regardless of what the signed-in account's own defaults are. |
| Bot fails to join and the account got deactivated | The live sign-in hit a bad password or a disabled/locked account. Rotate the password via `PATCH /api/v1/teams-logins/{login_id}` — that reactivates it. |

---

## 6) Related

- [Create Bot Payload Reference](/api-reference/create-bot-payload-reference)
- [Create your First Bot](/guides/get-started/create-your-first-bot) for guest joins to meetings that don't require sign-in
- [Microsoft Teams platform guide](/guides/platforms/microsoft-teams)