Skip to navigation

Microsoft Teams Signed-In Bots

Join Teams meetings as a real Microsoft 365 account instead of an anonymous guest
View as Markdown

Send your Teams bot in as a signed-in Microsoft 365 account, so it can join meetings that block anonymous guests and get past lobbies that only let organizations in.

By default, a MeetStream Teams bot joins as a guest: it opens the pre-join screen, types its bot_name and asks to be let in. That fails when the organizer’s organization has turned anonymous join off, because Teams shows a sign-in wall. A signed-in bot signs in to a Microsoft 365 bot account first and joins as that account.

You register each bot account with MeetStream once. Every bot you create against its domain then signs in automatically. You never send the password with a bot request, and you can rotate or remove it at any time. Endpoint: POST /api/v1/bots/create_bot
Auth: Authorization: Token <your MeetStream API key>


Before you start

A Microsoft 365 tenant and bot accounts

Use a dedicated tenant for bot accounts, not your production one. Bot accounts must sign in with only an email and password, which means turning off multi-factor authentication (MFA) for them. With security defaults that setting applies to the whole tenant, which you should never do for real employees. One dedicated tenant can hold all of your MeetStream bot accounts; you don’t need one per end customer.

  1. Subscribe to a paid Microsoft 365 plan that includes Microsoft Teams, such as Microsoft 365 Business Basic or higher (not a “no Teams” edition). We test with Business Basic and above; Teams Essentials is untested. Avoid a trial-only tenant: Teams blocks external access with trial-only tenants by default, so other organizations would treat your bots as anonymous (Microsoft Learn).
  2. Create one standard user per bot in the Microsoft 365 admin center under Users > Active users > Add a user (Microsoft Learn):
    • Set the display name (and later a profile picture). This is the name meeting participants see.
    • Clear “Require this user to change their password when they first sign in”, which is selected by default. Otherwise the bot’s first sign-in hits a password change screen and fails.
    • Assign a license that includes Teams.
    • Don’t assign any admin role.
  3. Keep passwords from expiring. Microsoft 365 defaults to passwords that never expire. Check Settings > Org Settings > Security and Privacy > Password expiration policy > Set passwords to never expire (recommended) (Microsoft Learn).
  4. Sign in once yourself at https://teams.microsoft.com with each bot account in a private browser window. Confirm it reaches Teams with no extra prompts.
  5. Note each account’s email address and password. You register them with MeetStream in Register your tenant domain and bot accounts.

Only Microsoft 365 (work or school) Teams is supported. Personal Teams accounts and teams.live.com meetings can’t be used with signed-in bots.

Make sure Microsoft never asks the bot for more than a password

MeetStream signs in with the email and password only. If Microsoft shows any extra step, the join fails:

What Microsoft showsBot result
”More information required” (MFA or security info registration)Error, ErrorReason TeamsLoginMfaRequired
”Verify it’s you”Error, ErrorReason TeamsLoginVerificationRequired

Turn these prompts off for the bot accounts in the Microsoft Entra admin center:

Security defaults can only be on or off for the whole tenant; you can’t exclude single users. In a dedicated bot tenant, turn them off (Microsoft Learn):

  1. Sign in to the Microsoft Entra admin center as at least a Conditional Access Administrator.
  2. Go to Entra ID > Overview > Properties.
  3. Select Manage security defaults.
  4. Set Security defaults to Disabled (not recommended) and select Save.

If self-service password reset is on, keep the bot accounts out of it so Microsoft doesn’t ask them to register security info at sign-in: in the Entra admin center go to Entra ID > Password reset > Properties and set Self service password reset enabled to None, or to Selected with a group that doesn’t include the bot accounts (Microsoft Learn).

Check that the meetings will let the bot in

A signed-in bot joins with its own organization’s identity. If that organization isn’t the organizer’s, Teams treats the bot as an external participant only when both organizations allow each other in external access (Teams admin center Users > External access; Microsoft’s default is Allow all external domains). If they don’t, Teams treats the bot as anonymous and it hits the same wall as a guest bot. Which bots skip the lobby depends on the meeting’s Who can bypass the lobby option: see the lobby matrix on the Teams platform page.


How it works

Guest bot (default)Signed-in bot
Identity in the meetingAnonymous; Teams shows Unverified next to the nameYour Microsoft 365 bot account
Name in the meetingThe bot_name you set on create_botThe account’s display name. bot_name is not used.
Videobot_image_url as the bot’s video, or camera offThe same: bot_image_url is shown as the bot’s video, or camera off
Meetings that require sign-inCan’t joinCan join
Personal Teams (teams.live.com) linksCan joinNot supported
Bots per account at the same timeNot applicable1. Teams merges sign-ins from the same account into one attendee, so give each concurrent bot its own account.
Password sent per joinNot applicableNo. You register it once; the bot reads it only at sign-in time.
Here is what happens when you create a signed-in bot:
alt [No free account] [Account reserved] alt [Extra prompt, wrong password or blocked account] [Signed in] POST create_bot with teams.login_required true Check the domain is yours and reserve a free bot account 429 All Teams logins under domain are currently in use 200 with bot_id Sign in with the account email and password Sign-in stops bot.stopped webhook, status Error, ErrorReason TeamsLogin... Open Teams signed in, then the meeting pre-join screen Click Join as the bot account bot.in_waiting_room, then bot.inmeeting On leave, release the account and wipe the signed-in session Your app MeetStream API MeetStream bot Microsoft sign-in Teams meeting

Setup is done once: register your tenant domain, then add each bot account. After that, create_bot only needs the domain.


Register your tenant domain and bot accounts

The tenant domain is the part after the @ in your bot accounts’ email addresses, for example acmebots.onmicrosoft.com for bot1@acmebots.onmicrosoft.com. Every account you add must use exactly that domain. Use lowercase for the domain and the email addresses.

In the dashboard

1

Open Teams Bots

In the MeetStream dashboard, go to Integrations and select the Teams Bots tab, then click Add domain.

MeetStream dashboard Integrations page with the Teams Bots tab selected, showing No Teams domains yet and the Add domain button
Integrations > Teams Bots: (1) Integrations, (2) the Teams Bots tab, (3) Add domain.
2

Add your tenant domain

In the Add Teams domain dialog:

  1. Tenant domain: your bot accounts’ email domain, in lowercase.
  2. Display name (optional): a label for you, such as “Acme Teams bots”.
  3. Login mode: choose Always sign in. It is the only mode that signs bots in today; with Sign in if required, bots join as guests.
  4. Click Add domain.
Add Teams domain dialog with the Tenant domain, Display name and Login mode fields and the Add domain button highlighted
The Add Teams domain dialog: (1) Tenant domain, (2) Display name, (3) Login mode, (4) Add domain.
3

Add each bot account

Click the domain in the list, then + Add login. In the Add Teams login dialog, enter the Bot email and Password, keep Active and available for new bots checked, and click Add login.

Credentials are write-only: the password is never displayed again, in the dashboard or the API. The account is usable immediately.

4

Watch account health

The domain’s logins table shows each account’s Email, Active state (click it to switch an account between Active and Inactive), Lease (available, or leased while a bot is using it) and Last session (ok, login_failed, not_applied or unknown_page, with the last error).

With the API

Register the domain:

POST /api/v1/teams-login-domains

{
"domain": "acmebots.onmicrosoft.com",
"name": "Acme bot tenant",
"login_mode": "always"
}

Returns 201 with domain, name, login_mode and created_at. login_mode accepts always (the default) and if_required, but only always signs bots in today: a bot on an if_required domain joins as an anonymous guest, with no error. Add a bot account:

POST /api/v1/teams-logins

{
"domain": "acmebots.onmicrosoft.com",
"email": "bot1@acmebots.onmicrosoft.com",
"password": "<account password>",
"is_active": true
}

Returns 201 with the account’s login_id, email, is_active and lease_status. The password is write-only: no response ever returns it, including GET.

ErrorWhy
400 Public mailbox domain not allowed: <domain>outlook.com, hotmail.com, live.com and gmail.com accounts can’t be bot accounts.
400 Email domain '<a>' does not match registered domain '<b>'The email must end in exactly the registered domain.
404 Domain <domain> not registeredRegister the domain first.
409 Domain <domain> already registered / Login <email> already exists under <domain>It’s already there.
Provisioning rule of thumb: Teams allows exactly one bot per account at a time. If you need 10 signed-in Teams bots in meetings at once, register 10 accounts.

Manage domains and accounts

TaskCall
List domains, with account countsGET /api/v1/teams-login-domains
See one domain and its accountsGET /api/v1/teams-login-domains/{domain}
List a domain’s accounts, with lease_status, last_session_result and last_login_errorGET /api/v1/teams-logins?domain=acmebots.onmicrosoft.com (the domain parameter is required)
See one accountGET /api/v1/teams-logins/{login_id}
Rotate a password, or turn an account off or onPATCH /api/v1/teams-logins/{login_id} with password or is_active
Rename a domain or change its login modePATCH /api/v1/teams-login-domains/{domain} with name or login_mode
Remove an accountDELETE /api/v1/teams-logins/{login_id} (refused with 409 while a bot is using it)
Remove a domain and all of its accountsDELETE /api/v1/teams-login-domains/{domain} (refused with 409 while any account is in use)

A new password takes effect on the account’s next sign-in; a bot already in a meeting is not affected. Rotating the password also reactivates an account that was switched off after a failed sign-in. Errors from these endpoints have the shape {"error": "..."}.


Create a signed-in bot

POST /api/v1/bots/create_bot

{
"meeting_link": "https://teams.microsoft.com/l/meetup-join/...",
"bot_image_url": "https://your-cdn.example/notetaker.png",
"video_required": false,
"teams": {
"login_required": true,
"teams_login_domain": "acmebots.onmicrosoft.com"
}
}
FieldTypeRequiredBehavior
login_requiredbooleanYes, to opt intrue requests a signed-in join.
teams_login_domainstringYes, when login_required is trueA domain you registered. It must belong to your MeetStream account.
sign_in_emailstringNoPin the bot to one account in that domain instead of letting MeetStream pick. Requires login_required: true, and must use the same domain.
strict_emailbooleanNo, default trueOnly valid with sign_in_email. true: use exactly that account or fail. false: use it if it’s free, otherwise any other free account in the domain.

login_mode is not a request field; it comes from the domain. Sending teams.login_mode returns 400. Everything else on create_bot (recording, transcription, webhooks, automatic leave) works as for any other bot. See the Create Bot Payload Reference and the Teams platform guide for Teams-specific behavior.

How MeetStream picks and holds an account

  • One bot per account. An account is reserved for one bot at a time and released when that bot finishes. If a release is ever missed, the reservation expires after 13 hours.
  • Least recently used first. Without sign_in_email, MeetStream picks the active, free account that was used longest ago, which spreads sign-ins across your accounts.
  • When the reservation happens. For an immediate bot, when you call create_bot, so a full pool fails the request right away. For a scheduled bot (join_at), about two minutes before join_at, not when you schedule it. Make sure an account is free at that time.
  • No fallback to guest. If sign-in fails, the bot stops with an error instead of joining anonymously.
  • Nothing is left behind. When the bot leaves, the account is released and the signed-in browser session is wiped.
sign_in_emailstrict_emailResult
Not setNot allowedLeast recently used free account. 429 if none is free.
Settrue (default)That account only. 404 if it isn’t registered in the domain; 409 if it’s in use or inactive.
SetfalseThat account if it’s free, otherwise another free account. 404 if the email isn’t registered in the domain; 429 if nothing is free.

Sign-in errors

A failed sign-in ends the bot with status Error (webhook bot.stopped, bot_event: "bot.failed"). For failures before the bot reaches the meeting, the message starts with Error: Teams sign-in failed:. The reason is in bot_details.ErrorReason from GET /api/v1/bots/{bot_id}/detail, and in the account’s Last session (last_login_error).

ErrorReasonWhat happenedWhat to do
TeamsLoginBadCredentialsMicrosoft kept the bot on the sign-in page after the password.Fix the password, then PATCH it. The account is switched to inactive until you do.
TeamsLoginAccountDisabledMicrosoft says the account is blocked.Make sure the account is allowed to sign in (not blocked) in the Microsoft 365 admin center, then rotate the password or set is_active: true. The account is switched to inactive.
TeamsLoginMfaRequiredMicrosoft asked for more information (MFA or security info registration).Turn off MFA and security info registration for the account (see above).
TeamsLoginVerificationRequiredMicrosoft asked the account to verify its identity.Sign in once yourself with the account, clear the prompt, and check the MFA settings above.
TeamsLoginUnknownPageMicrosoft showed a page MeetStream doesn’t recognize, such as a password change or an error page.Sign in once yourself with the account and complete whatever Microsoft asks.
TeamsAppSessionNotEstablishedSign-in worked, but Teams didn’t open signed in.Check that the account has a license that includes Teams, then retry.
TeamsSessionNotAppliedThe meeting’s pre-join screen didn’t show the signed-in account.Check the Teams license and retry. (Guest bots also report this reason when Teams shows a sign-in wall.)
TeamsSessionAuthFailedTeams showed “We couldn’t authenticate you”.Retry; if it repeats, sign in manually with the account to check it.
TeamsAppInitFailedTeams kept failing to start after Join, even after 2 retries in a fresh tab.Retry the bot.
TeamsCredentialsFetchFailed or TeamsSignInBrowserFailedThe bot couldn’t start its sign-in.Retry the bot; contact support if it repeats.

Wrong passwords are never retried. One wrong attempt per bot keeps Microsoft from locking the account for your whole pool. After TeamsLoginBadCredentials or TeamsLoginAccountDisabled, MeetStream marks the account inactive (is_active: false, Inactive in the dashboard), so new bots skip it until you fix it.


Troubleshooting

create_bot errors return {"message": "..."}.

SymptomWhat to check
400 teams.teams_login_domain '<d>' is not registered. ...The domain wasn’t registered, or was typed differently. Register and use the domain in lowercase.
403 teams.teams_login_domain '<d>' is not registered to this accountThe domain belongs to a different MeetStream account.
404 teams.sign_in_email '<email>' not found under this domainThat email isn’t registered in the domain. Use the exact lowercase address you registered.
409 teams.sign_in_email '<email>' is currently in useAnother bot holds that account. Wait, or set strict_email: false.
409 teams.sign_in_email '<email>' has been deactivated; ...The account was switched off, usually after a failed sign-in. Fix and rotate its password, or set strict_email: false.
429 All Teams logins under domain '<d>' are currently in useNo active account is free: all are in use, inactive, or the domain has none. Add accounts or reactivate one.
400 teams.login_required is not supported for personal Teams (teams.live.com) linksSigned-in bots only work with work or school Teams links. Send a guest bot.
400 teams must be a JSON object. ... or teams.login_required must be a booleanThe teams block is malformed. It is rejected, not ignored; fix the JSON.
400 teams.login_mode is not caller-controlled; ...Remove login_mode from the request; set it on the domain.
The bot joined as an anonymous guest with no errorThe domain’s login mode is if_required (Sign in if required in the dashboard). Change it to always.
The bot fails to join and the account is now inactiveSee Sign-in errors. Fix the account, then rotate its password with PATCH /api/v1/teams-logins/{login_id}, which reactivates it.
The bot waits in the lobby even though it’s signed inThe meeting’s Who can bypass the lobby option doesn’t cover the bot’s organization. See the lobby matrix.
The bot’s camera or microphone stateEvery bot joins muted, with its camera off unless you set bot_image_url, whatever the account’s own Teams defaults are.