How to Set Up a Microsoft Teams Meeting Bot with Unified
November 7, 2026
Overview
Microsoft Teams (meeting bot) (microsoftteamsmeetingbot) is the integration that gives you a calendar_bot and calendar_botevents for Microsoft Teams meetings. It is separate from Microsoft Teams and Microsoft Teams (bot): existing connections don't change, and your end users connect Microsoft Teams (meeting bot) on its own.
A Teams meeting bot never joins the meeting and captures no media. It monitors the meeting through Microsoft Graph and reports it after the meeting ends:
- the call record: start and end times, participants, and
BOT_STATUS_CHANGEtoCALL_ENDED PARTICIPANT_JOINED/PARTICIPANT_LEFT, with times from the call recordRECORDING_READY, with the bot'srecording_idset to acalendar_recordingon the same connection, andBOT_STATUS_CHANGEtoDONE- the Teams transcript, one
TRANSCRIPT_RECEIVEDper transcript line
No data arrives while the meeting is running.
The same connection also gives you the meeting-related Microsoft Teams objects: calendar_calendar, calendar_event, calendar_busy, calendar_webinar, calendar_recording, uc_call and uc_recording. They work as on the Microsoft Teams integration (calendar_event and uc_call have native webhooks), and their scopes are requested only when you select their permissions.
For how to create bots and receive events, see How to Build a Meeting Bot with Unified.
⚠️ Important: your own Entra app, with admin consent
Microsoft Teams (meeting bot) needs your own Microsoft Entra app. Unified has no shared credentials for this integration.
Call records need the Microsoft Graph application permission CallRecords.Read.All. It can't be requested during the user's OAuth sign-in. Unified gets an app-only token for it with your app's client ID and secret, against the user's tenant.
So the same Entra app your users authorize must also have CallRecords.Read.All (application) with admin consent in each customer's tenant. Only a Privileged Role Administrator or Global Administrator can grant it. Without it, creating the calendar_botevent webhook fails.
The delegated recording, transcript and AI insight permissions (OnlineMeetingRecording.Read.All, OnlineMeetingTranscript.Read.All, OnlineMeetingAiInsight.Read.All) need admin consent too. Users can consent on their own only to User.Read, OnlineMeetings.Read, Calendars.Read and the sign-in scopes.
What you'll need
- A Microsoft Entra app registration (see How to get your Microsoft Azure AD OAuth 2 credentials)
- A tenant admin in each customer tenant who can grant admin consent
- End users who sign in with work or school accounts (delegated OAuth)
Step 1: Register the Entra app
- In the Microsoft Entra admin center, go to Entra ID > App registrations > New registration. Under supported account types, choose Multiple Entra ID tenants: Unified signs users in through the
commonendpoint, so a single-tenant app fails for every user withAADSTS50194. - Add a Web redirect URI for your Unified region:
- US:
https://api.unified.to/oauth/code - EU:
https://api-eu.unified.to/oauth/code - AU:
https://api-au.unified.to/oauth/code
- US:
- Create a client secret and copy its Value (not its Secret ID), with the Application (client) ID. Secrets expire after at most 24 months; replace the secret in Unified before it expires.
Step 2: Add Microsoft Graph permissions
Delegated permissions
| Permission | Unified permission | Used for |
|---|---|---|
User.Read, openid, email, profile, offline_access | all | Sign-in and token refresh |
OnlineMeetings.Read | calendar_bot_read, calendar_bot_write, calendar_botevent_read, calendar_recording_read | Find the meeting by its join link; read recordings |
Calendars.Read | calendar_bot_write, calendar_event_read | Create a bot from a calendar event_id; list events |
OnlineMeetingRecording.Read.All | calendar_botevent_read, calendar_recording_read | Recording notifications and reads |
OnlineMeetingTranscript.Read.All | calendar_botevent_read, calendar_recording_read | Transcript notifications and reads |
OnlineMeetingAiInsight.Read.All | calendar_recording_read | Reading the calendar_recording a bot points to (AI insights need a Microsoft 365 Copilot licence for each user) |
| If you select other permissions (calendars, busy, webinars, calls), add the same delegated permissions the Microsoft Teams integration uses for them. |
Application permission
| Permission | Used for |
|---|---|
CallRecords.Read.All | The call-record subscription and reads. Needs admin consent. |
| Then select Grant admin consent (in your own tenant), and have each customer's tenant admin consent to the app in theirs: the application permission, and the delegated recording, transcript and AI insight permissions. |
Step 3: Enter your credentials in Unified
- In the Unified app, open Integrations and activate Microsoft Teams (meeting bot).
- Enter your Entra app's client ID and client secret.
- Select the permissions you need:
calendar_bot_read,calendar_bot_writeandcalendar_botevent_readfor bots,calendar_event_readto list events (creating a bot from anevent_idneeds onlycalendar_bot_write), andcalendar_recording_readto read recordings. Unified requests the matching delegated permissions above.
Step 4: Webhook setup
There is nothing to configure in Azure or Teams. When you create a native calendar_botevent webhook on a connection, Unified creates three Microsoft Graph subscriptions for it, and renews them automatically. (Graph limits these subscriptions to an hour; Unified creates them for 58 minutes.)
communications/callRecords(app-only token): the call record- the connected user's online meeting recordings (delegated)
- the connected user's online meeting transcripts (delegated)
Creating the webhook is all or nothing: if any of the three subscriptions can't be created, none is kept and the request fails. It returns 400 when the integration doesn't have your own Entra app's credentials, and fails when the tenant admin hasn't consented to CallRecords.Read.All.
Create the webhook before the meeting starts: Graph sends transcript notifications only when the subscription existed before transcription started. The bot must exist before the meeting ends: the call record is matched only to a bot that is still READY.
How end users connect
End users authorize Microsoft Teams (meeting bot) through Unified's authorization flow (embedded authorization or the authorization link) with their work or school account, and approve the delegated permissions. Their tenant admin must also consent to your app's CallRecords.Read.All application permission and to the delegated recording, transcript and AI insight permissions. A user who signs in before that sees AADSTS90094 (admin consent required).
App-only (client credentials) connections aren't supported: the bot looks up the meeting as the connected user.
Test the setup
- Create a
calendar_botwith the Teams join link (meeting_url, ahttps://teams.microsoft.com/...link), or with theidof acalendar_eventlisted on the same connection (event_id; the event must have a Teams join link). The bot isREADY. - Create a native webhook for
calendar_botevent/createdon the same connection. - Hold the meeting, with recording and transcription on.
- After the meeting, expect
BOT_STATUS_CHANGEtoCALL_ENDEDand participant events, thenRECORDING_READY,TRANSCRIPT_RECEIVEDevents andBOT_STATUS_CHANGEtoDONE. - Read the recording with
GET /calendar/{connection_id}/recording/{recording_id}on the same connection.
Limits
- Unsupported features return
501(Not supported by this integration: …) on create and update:join_at, and anyrecording_config, even{}. The bot records nothing itself; recordings and transcripts come from Teams when the organizer turns them on. Malformed input, such as a link that isn't a Teams join link, returns400. - After the meeting only. Microsoft delivers call records after the meeting: on average within 30 minutes, and up to 150 minutes. Recordings and transcripts can take up to 240 minutes.
- Recordings and transcripts need the organizer. They are subscribed for scheduled meetings organized by the connected user. A bot on someone else's meeting gets the call record only.
- Not covered by Graph recordings and transcripts: private-channel meetings, ad hoc calls, expired meetings, and meetings created through the API without a calendar event.
- Tenant settings: a tenant admin can turn off Graph access to transcripts; reads then fail with
403 GraphAccessToTranscriptsDisabled. - The meeting must be visible to the connected user; otherwise creating the bot returns
404, as it does for a meeting or calendar event that doesn't exist. Creating another bot while an earlier bot for exactly the same link is still active (notCALL_ENDED,DONEorFATAL) returns409. - Only
nameis updated.meeting_urlandevent_idin an update are ignored. - Large meetings: only the first page of call-record participants (130) and sessions (60) is read.
- Several webhooks on one connection: call-record events go to whichever webhook's notification is processed first. Recording and transcript events go to every webhook.
- Recurring meetings: recordings and transcripts attach to a bot only when created between the bot's
created_atand itsended_at, so another occurrence doesn't attach. - A meeting with no recording stays in
CALL_ENDED. - Deleting a bot deletes it; no event is sent.
Troubleshooting
❌ Creating a bot returns 400
- The link isn't a
https://teams.microsoft.com/...join link - The calendar event has no Teams join link
❌ Creating a bot returns 404
- The meeting or calendar event doesn't exist
- The connected user can't see the meeting
❌ Creating a bot returns 501
The request includes join_at or recording_config. Remove them.
❌ Creating the webhook fails
400: the integration doesn't have your own Entra app's client ID and secret (Step 3)- The tenant admin hasn't consented to
CallRecords.Read.All(Step 2) AADSTS7000215: the client secret is wrong; enter the secret's Value, not its Secret IDAADSTS7000222: the client secret has expired; create a new one and update it in Unified
❌ Users can't sign in
AADSTS50194: the app is single-tenant; change it to Multiple Entra ID tenants (Step 1)AADSTS90094: the tenant admin hasn't granted admin consent (Step 2)
❌ The bot stays READY after the meeting
- The bot or the
calendar_boteventwebhook was created after the meeting ended - Microsoft hasn't delivered the call record yet (up to 150 minutes)
❌ No recording or transcript events
- The connected user didn't organize the meeting
- Recording or transcription wasn't on in the meeting
- The webhook was created after transcription started
- The tenant has turned off Graph access to transcripts (
403 GraphAccessToTranscriptsDisabled) - Microsoft hasn't delivered them yet (up to 240 minutes)