Meeting apps APIs
The meeting extensibility provides APIs to enhance meeting experience. You can perform the following with help of the listed APIs:
- Build apps or integrate existing apps within meeting lifecycle.
- Use APIs to make your app aware of meeting.
- Select required APIs to improve the meeting experience.
Note
Use the Microsoft Teams JavaScript client library (TeamsJS) (Version: 1.10 and later) for single sign-on (SSO) to work in meeting side panel.
The following table provides a list of APIs available across the Microsoft Teams JavaScript library and Microsoft Bot Framework SDKs:
Method | Description | Source |
---|---|---|
Get user context | Get contextual information to display relevant content in a Microsoft Teams tab. | TeamsJS library |
Get participant | Fetch participant information by meeting ID and participant ID. | Microsoft Bot Framework SDK |
Send in-meeting notification | Provides meeting signals using the existing conversation notification API for user-bot chat and allows the bot to notify user action that shows an in-meeting notification. | Microsoft Bot Framework SDK |
Get meeting details | Get a meeting's static metadata. | Microsoft Bot Framework SDK |
Send real-time captions | Send real-time captions to an ongoing meeting. | TeamsJS library |
Share app content to stage | Share specific parts of the app to meeting stage from the app side panel in a meeting. | TeamsJS library |
Receive real-time Teams meeting events | Receive real-time meeting events, such as meeting start and end or participant join and leave. | Microsoft Bot Framework SDK |
Get incoming audio state | Allows an app to get the incoming audio state setting for the meeting user. | TeamsJS library |
Toggle incoming audio | Allows an app to toggle the incoming audio state setting for the meeting user from mute to unmute or vice-versa. | TeamsJS library |
Get user context API
Important
- By default, the new Teams client supports light theme for apps in Teams meetings. When the
app.theme
property in getContext API returns thedefault
value, Teams client is in light theme. - Earlier version of Teams clients only support Dark and Contrast theme for apps in Teams meetings
To identify and retrieve contextual information for your tab content, see get context for your Teams tab. meetingId
is used by a tab running in the meeting context and is added for the response payload.
Examples
The following are the TeamsJS v2 responses for Get user context API based on meeting type, user type, and call type:
Meeting type
The following is a JSON payload response for a channel meeting for in-tenant users:
{ "app": { "locale": "en-us", "sessionId": "ff47ec00-e6a7-4dc1-a6ae-f44110f50c94", "theme": "default", "iconPositionVertical": 0, "osLocaleInfo": { "platform": "windows", "regionalFormat": "en-in", "shortDate": "dd-MM-yyyy", "longDate": "dd MMMM yyyy", "shortTime": "HH:mm", "longTime": "HH:mm:ss" }, "parentMessageId": "1678109354022", "userClickTime": 1678109521159, "userFileOpenPreference": "inline", "host": { "name": "Teams", "clientType": "desktop", "sessionId": "c3c3c0a0-f7a1-b070-6b89-c8cd1f380042", "ringId": "ring1" }, "appLaunchId": "7346ae66-5cac-47f9-8a0d-1228dac474cb" }, "page": { "id": "Test", "frameContext": "sidePanel", "subPageId": "", "isFullScreen": false, "isMultiWindow": true, "sourceOrigin": "" }, "user": { "id": "57efa5f3-273c-47e2-a871-4879e5d849cf", "displayName": "", "isCallingAllowed": undefined, "isPSTNCallingAllowed": undefined, "licenseType": "Unknown", "loginHint": "[email protected]", "userPrincipalName": "[email protected]", "tenant": { "id": "72f988bf-86f1-41af-91ab-2d7cd011db47", "teamsSku": "enterprise" } }, "channel": { "id": "19:[email protected]", "displayName": undefined, "relativeUrl": undefined, "membershipType": undefined, "defaultOneNoteSectionId": undefined, "ownerGroupId": undefined, "ownerTenantId": undefined }, "chat": { "id": "19:[email protected]" }, "meeting": { "id": "MCMxOTo0OTY4MzgwN2ZmY2U0MzE4YWQ2ZDZkN2EyNGRiZGU0NUB0aHJlYWQudGFjdjIjMTY3ODEwOTM1NDAyMg==" }, "sharepoint": undefined, "team": { "internalId": "19:[email protected]", "displayName": undefined, "type": undefined, "groupId": undefined, "templateId": undefined, "isArchived": undefined, "userRole": 1 }, "sharePointSite": { "teamSiteUrl": "", "teamSiteDomain": "microsoft.sharepoint.com", "teamSitePath": "", "teamSiteId": "", "mySitePath": undefined, "mySiteDomain": undefined } }
User type
The following is a JSON payload response in a scheduled private meeting for a guest user:
{ "app": { "locale": "en-us", "sessionId": "268beeb4-a52d-4ba8-b1c8-8b9f0b9b3492", "theme": "default", "iconPositionVertical": 23, "osLocaleInfo": { "platform": "windows", "regionalFormat": "en-in", "longDate": "dd MMMM yyyy", "shortDate": "dd-MM-yyyy", "longTime": "HH:mm:ss", "shortTime": "HH:mm" }, "parentMessageId": "", "userClickTime": 1678023265131, "userFileOpenPreference": "inline", "host": { "name": "Teams", "clientType": "desktop", "sessionId": "967c980b-1e41-a2cd-eac0-a4bff8f73ce7", "ringId": "ring1" }, "appLaunchId": "c35c4496-f28c-4107-8e6c-2dba09fb881a" }, "page": { "id": "Test", "frameContext": "content", "subPageId": "", "isFullScreen": false, "isMultiWindow": false, "sourceOrigin": NULL }, "user": { "id": "57efa5f3-273c-47e2-a871-4879e5d849cf", "displayName": undefined, "isCallingAllowed": undefined, "isPSTNCallingAllowed": undefined, "licenseType": "Unknown", "loginHint": "[email protected]", "userPrincipalName": "[email protected]", "tenant": { "id": "72f988bf-86f1-41af-91ab-2d7cd011db47", "teamsSku": "enterprise" } }, "channel": undefined, "chat": { "id": "19:meeting_YmU5NWM3NGEtZjMyMi00ZDg4LTk4OGUtMjUzMGJkZjRhMDhm@thread.v2" }, "meeting": { "id": "MCMxOTptZWV0aW5nX1ltVTVOV00zTkdFdFpqTXlNaTAwWkRnNExUazRPR1V0TWpVek1HSmtaalJoTURobUB0aHJlYWQudjIjMA==" }, "sharepoint": undefined, "team": undefined, "sharePointSite": { "teamSiteUrl": "", "teamSiteDomain": "microsoft.sharepoint.com", "teamSitePath": "", "teamSiteId": undefined, "mySitePath": "/personal/user_microsoft_com", "mySiteDomain": "microsoft-my.sharepoint.com" } }
Call type
The following is a JSON payload response for a one-on-one call for an in-tenant user:
{ "app": { "locale": "en-us", "sessionId": "1b3dc47e-f6ae-4fe2-8ed6-844a505f3186", "theme": "dark", "iconPositionVertical": null, "osLocaleInfo": { "platform": "windows", "regionalFormat": "en-in", "shortDate": "dd-MM-yyyy", "longDate": "dd MMMM yyyy", "shortTime": "HH:mm", "longTime": "HH:mm:ss" }, "parentMessageId": "", "userClickTime": 1678088052473, "userFileOpenPreference": undefined, "host": { "name": "Teams", "clientType": "desktop", "sessionId": "", "ringId": "general" }, "appLaunchId": undefined }, "page": { "id": "Test", "frameContext": "sidePanel", "subPageId": "", "isFullScreen": undefined, "isMultiWindow": true, "sourceOrigin": "" }, "user": { "id": "e652dd92-dd63-4fcc-b5b2-2005681e8e9f", "displayName": undefined, "isCallingAllowed": undefined, "isPSTNCallingAllowed": undefined, "licenseType": "Unknown", "loginHint": "[email protected]", "userPrincipalName": "[email protected]", "tenant": { "id": "aa923623-ae61-49ee-b401-81f414b6ad5a", "teamsSku": "unknown" } }, "channel": undefined, "chat": { "id": "19:a74d8489-4455-4670-9581-7b38a8017c58_e652dd92-dd63-4fcc-b5b2-2005681e8e9f@unq.gbl.spaces" }, "meeting": { "id": "MCMxOTphNzRkODQ4OS00NDU1LTQ2NzAtOTU4MS03YjM4YTgwMTdjNThfZTY1MmRkOTItZGQ2My00ZmNjLWI1YjItMjAwNTY4MWU4ZTlmQHVucS5nYmwuc3BhY2VzIzA=" }, "sharepoint": undefined, "team": undefined, "sharePointSite": { "teamSiteUrl": undefined, "teamSiteDomain": "microsoft.sharepoint.com", "teamSitePath": undefined, "teamSiteId": undefined, "mySitePath": undefined, "mySiteDomain": undefined } }
Get participant API
The GetParticipant
API must have a bot registration and ID to generate auth tokens. For more information, see bot registration and ID.
Note
- The user type isn't included in the getParticipantRole API.
- Do not cache participant roles since the meeting organizer can change the roles any time.
- The
GetParticipant
API is only supported for distributions lists or rosters with less than 350 participants.
Query parameters
Tip
Get participant IDs and tenant IDs from the tab SSO authentication.
The Meeting
API must have meetingId
, participantId
, and tenantId
as URL parameters. The parameters are available as part of the Microsoft Teams JavaScript client library (TeamsJS) library and bot activity.
The following table includes the query parameters:
Value | Type | Required | Description |
---|---|---|---|
meetingId | String | Yes | The meeting identifier is available through Bot Invoke and TeamsJS library. |
participantId | String | Yes | The participant ID is the user ID. It's available in Tab SSO, Bot Invoke, and TeamsJS library. It's recommended to get a participant ID from the Tab SSO. |
tenantId | String | Yes | The tenant ID is required for the tenant users. It's available in Tab SSO, Bot Invoke, and TeamsJS library. It's recommended to get a tenant ID from the Tab SSO. |
Example
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
// Gets the details for the given meeting participant.
// This only works in Teams meeting scoped conversations.
TeamsMeetingParticipant participant = await TeamsInfo.GetMeetingParticipantAsync(turnContext, "yourMeetingId", "yourParticipantId", "yourParticipantTenantId").ConfigureAwait(false);
TeamsChannelAccount member = participant.User;
MeetingParticipantInfo meetingInfo = participant.Meeting;
ConversationAccount conversation = participant.Conversation;
// Sends a message activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(MessageFactory.Text($"The participant role is: {meetingInfo.Role}"), cancellationToken);
}
Property name | Description |
---|---|
user.id | ID of the user. |
user.aadObjectId | Microsoft Entra object ID of the user. |
user.name | Name of the user. |
user.givenName | First Name of the user. |
user.surname | Last Name of the user. |
user.email | Mail ID of the user. |
user.userPrincipalName | UPN of the user. |
user.tenantId | Microsoft Entra tenant ID. |
user.userRole | Role of the user. For example, 'admin' or 'user'. |
meeting.role | The participant's role in the meeting. For example, 'Organizer' or 'Presenter' or 'Attendee'. |
meeting.inMeeting | The value indicating if the participant is in the meeting. |
conversation.id | The meeting chat ID. |
conversation.isGroup | Boolean indicating whether conversation has more than two participants. |
Response codes
The following table provides the response codes:
Response code | Description |
---|---|
403 | Get participant information isn't shared with the app. If the app isn't installed in the meeting, it triggers the error response 403. If the tenant admin disables or blocks the app during live site migration, it triggers the error response 403. |
200 | The participant information is successfully retrieved. |
401 | The app responds with an invalid token. |
404 | The meeting has either expired or participants aren't available. |
Send an in-meeting notification
All users in a meeting receive the notifications sent through in-meeting notification payload. In-meeting notification payload triggers an in-meeting notification and enables you to provide meeting signals that are delivered using the existing conversation notification API for user-bot chat. You can send an in-meeting notification based on user action. The payload is available through Bot Services.
You can also send targeted in-meeting notification to a specific participant in a meeting. For more information, see Targeted in-meeting notification.
Note
- When an in-meeting notification is invoked, the content is presented as a chat message.
- You must invoke the submitTask() function to dismiss automatically after a user takes an action in the web view. This is a requirement for app submission. For more information, see Teams SDK task module.
- If you want your app to support anonymous users, initial invoke request payload must rely on
from.id
request metadata infrom
object, notfrom.aadObjectId
request metadata.from.id
is the user ID andfrom.aadObjectId
is the Microsoft Entra ID of the user. For more information, see using task modules in tabs and create and send the task module.
Query parameter
The following table includes the query parameter:
Value | Type | Required | Description |
---|---|---|---|
conversationId | String | Yes | The conversation identifier is available as part of Bot Invoke. |
Examples
Bot ID
is declared in the manifest and the bot receives a result object.
Note
- The
completionBotId
parameter of theexternalResourceUrl
is optional in the requested payload example. - The
externalResourceUrl
width and height parameters must be in pixels. For more information, see design guidelines. - The URL is the page, which loads as
<iframe>
in the in-meeting notification. The domain must be in the apps'validDomains
array in your app manifest.
// Specifies the type of text data in a message attachment.
Activity activity = MessageFactory.Text("This is a meeting signal test");
// Configures the current activity to generate a notification within Teams.
activity.TeamsNotifyUser(true, "https://teams.microsoft.com/l/bubble/APP_ID?url=<url>&height=<height>&width=<width>&title=<title>&completionBotId=BOT_APP_ID");
// Sends a message activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(activity).ConfigureAwait(false);
Property name | Description |
---|---|
type | Type of activity. |
text | The text content of the message. |
summary | The summary text of the message. |
channelData.notification.alertInMeeting | Boolean indicating if a notification is to be shown to the user while in a meeting. |
channelData.notification.externalResourceUrl | The value of the notification's external resource URL. |
replyToId | The ID of the parent or root message of the thread. |
APP_ID | App ID declared in manifest. |
completionBotId | Bot app ID. |
Response codes
The following table includes the response codes:
Response code | Description |
---|---|
201 | The activity with signal is successfully sent. |
401 | The app responds with an invalid token. |
403 | The app is unable to send the signal. 403 response code can occur because of various reasons, such as the tenant admin disables and blocks the app during live site migration. In this case, the payload contains a detailed error message. |
404 | The meeting chat doesn't exist. |
Targeted meeting notification and app icon badging API
The targetedMeetingNotification
API allows apps to send targeted in-meeting notifications and shows app icon badging to specific participants in a meeting. Apps send targeted in-meeting notifications and app icon badging based on user action. The API is available through bot API.
Prerequisite
You must configure your app manifest with RSC permissions under the webApplicationInfo
property to send targeted in-meeting notifications and shows app icon badging to specific participants in a meeting. Use the following examples to configure your manifest:
For app manifest version 1.12 and later
"webApplicationInfo": {
"id": "<<MICROSOFT-APP-ID>>",
"resource": "https://RscBasedStoreApp" },
"authorization": {
"permissions": {
"resourceSpecific": [
{
"name": "OnlineMeetingNotification.Send.Chat",
"type": "Application"
}
]
}
}
For app manifest version 1.11 and earlier
"webApplicationInfo": {
"id": "<<MICROSOFT-APP-ID>>",
"resource": "https://RscBasedStoreApp",
"applicationPermissions": [
"OnlineMeetingNotification.Send.Chat"
]
}
Note
- The API payload only permits a dialog with a URL.
- The user ID formats aadObjectid and UPN aren't supported.
Get supported user ID format for targeted in-meeting notification and app icon badging:
Example
Following is an example of request payload for targeted in-meeting notification and app icon badging:
POST /v1/meetings/{meetingId}/notification
{
"type": "targetedMeetingNotification",
"value": {
"recipients": [
"29:1I12M_iy2wTa97T6LbjTh4rJCWrtw2PZ3lxpD3yFv8j2YPnweY2lpCPPAn3RI0PP7rghfHauUz48I1t7ANhj4CA"
],
"surfaces": [
{
"surface": "meetingStage",
"contentType": "task",
"content": {
"value": {
"height": "300",
"width": "400",
"title": "Targeted meeting Notification",
"url": "https://somevalidurl.com"
}
}
}
]
},
"channelData": { // optional if a developer doesn't want to support user attributes.
"onBehalfOf": [
{
"itemid": 0,
"mentionType": "person",
"mri": "29:1mDOCfGM9825lMHlwP8NjIVMJeQAbN-ojYBT5VzQfPpnst1IFQeYB1QXC8Zupn2RhgfLIW27HmynQk-4bdx_YhA",
"displayName": "yunny chung" }
]
}
}
Property name | Description |
---|---|
meetingId |
The meeting ID is available through bot invoke and TeamsJS library. |
type |
targetedMeetingNotification |
recipients |
List of user IDs. Get user IDs for meeting participants through Get participant API. Get the entire list of chat roster using Get members API. An empty or null recipients list returns 400. |
surface |
A type of surface. The supported surface types are meetingStage and meetingTabIcon . |
surfaces |
List of surfaces where notifications can be rendered. |
contentType |
Type of content that the targeted in-meeting notification renders. The supported value is task . |
content |
TaskModuleContinueResponse |
content.value.height |
Optional; requested height of the notification. |
content.value.width |
Optional; requested width of the notification. |
content.value.title |
Optional; title of the notification. |
content.value.url |
Optional; URL to be rendered in the notification. Make sure the URL is part of validDomains in app manifest. If an empty string or no URL is provided, nothing is rendered on a meeting notification. |
ChannelData.OnBehalfOf |
Optional; this is to support User attributes. |
onBehalfOf.itemid |
Describes identification of the item. Its value must be 0. |
onBehalfOf.mentionType |
person keyword. Describes the mention of a person. |
onBehalfOf.mri |
User MRI shown as sender. |
onBehalfOf.displayName |
Optional; name of the person . Used as fallback in case the name resolution is unavailable. |
Note
If you provide an invalid input, the API returns the status code 400.
Response code
The following table includes the response codes:
Response code | Description |
---|---|
202 | Notification is successfully sent. |
207 | Notifications are sent only to a few participants. |
400 | Meeting notification request payload validation failed. |
401 | Bot token is invalid. |
403 | Bot isn't allowed to send the notification. |
404 | Meeting chat isn't found or none of the participants were found in the roster. |
Get meeting details API
The meeting details API enables your app to get a meeting's static metadata. The metadata provides data points that don't change dynamically. The API is available through Bot Services. Both private scheduled or recurring meetings and channel scheduled or recurring meetings support API with different RSC permissions respectively.
The meeting details API must have a bot registration and bot ID. It requires Bot SDK to get TurnContext
. To use the meeting details API, you must obtain different RSC permission based on the scope of any meeting, such as private meeting or channel meeting.
Note
The meeting details API is supported for scheduled private meetings, scheduled channel meeting, instant meetings (Meet now), one-on-one calls, and group calls in Teams desktop and mobile clients.
Prerequisite
To use the meeting details API, you must obtain different RSC permission based on the scope of any meeting, such as private meeting or channel meeting.
For app manifest version 1.12 and later
Use the following example to configure your app manifest's webApplicationInfo
and authorization
properties for any private meeting:
"webApplicationInfo": {
"id": "<bot id>",
"resource": "https://RscPermission",
},
"authorization": {
"permissions": {
"resourceSpecific": [
{
"name": "OnlineMeeting.ReadBasic.Chat",
"type": "Application"
}
]
}
}
Use the following example to configure your app manifest's webApplicationInfo
and authorization
properties for any channel meeting:
"webApplicationInfo": {
"id": "<bot id>",
"resource": "https://RscPermission",
},
"authorization": {
"permissions": {
"resourceSpecific": [
{
"name": "ChannelMeeting.ReadBasic.Group",
"type": "Application"
}
]
}
}
For app manifest version 1.11 and earlier
Use the following example to configure your app manifest's webApplicationInfo
property for any private meeting:
"webApplicationInfo": {
"id": "<bot id>",
"resource": "https://RscPermission",
"applicationPermissions": [
"OnlineMeeting.ReadBasic.Chat"
]
}
Use the following example to configure your app manifest's webApplicationInfo
property for any channel meeting:
"webApplicationInfo": {
"id": "<bot id>",
"resource": "https://RscPermission",
"applicationPermissions": [
"ChannelMeeting.ReadBasic.Group"
]
}
Note
- If the
ChannelMeeting.ReadBasic.Group
permission is added to the manifest, the bot receives the meeting start or end events automatically from the channel meetings created in all the teams where the bot is added. - For a one-on-one call
organizer
is the initiator of the chat and for group callsorganizer
is the call initiator. For public channel meetingsorganizer
is the person who created the channel post.
Query parameter
The following table lists the query parameter:
Value | Type | Required | Description |
---|---|---|---|
meetingId | String | Yes | The meeting identifier is available through Bot Invoke and the TeamsJS library. |
Example
// Gets the information for the given meeting id.
MeetingInfo result = await TeamsInfo.GetMeetingInfoAsync(turnContext);
// Sends a message activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(JsonConvert.SerializeObject(result));
Property name | Description |
---|---|
details.id | The meeting's ID, encoded as a BASE64 string. |
details.msGraphResourceId | The MsGraphResourceId, used specifically for MS Graph API calls. |
details.scheduledStartTime | The meeting's scheduled start time, in UTC. |
details.scheduledEndTime | The meeting's scheduled end time, in UTC. |
details.joinUrl | The URL used to join the meeting. |
details.title | The title of the meeting. |
details.type | The meeting's type (OneToOneCall, GroupCall, Scheduled, Recurring, MeetNow, ChannelScheduled, and ChannelRecurring). |
conversation.isGroup | Boolean indicating whether conversation has more than two participants. |
conversation.conversationType | The conversation type. |
conversation.id | The meeting chat ID. |
organizer.id | The Organizer's user ID. |
organizer.aadObjectId | The Organizer's Microsoft Entra object ID. |
organizer.tenantId | The Organizer's Microsoft Entra tenant ID. |
In case of recurring meeting type:
startDate: Specifies the date to start applying the pattern. The value of startDate must correspond to the date value of the start property on the event resource. The first occurrence of the meeting might not occur on this date if it doesn't fit the pattern.
endDate: Specifies the date to stop applying the pattern. The last occurrence of the meeting might not occur on this date if it doesn't fit the pattern.
Send real-time captions API
The send real-time captions API exposes a POST endpoint for Teams communication access real-time translation (CART) captions, human-typed closed captions. Text content sent to this endpoint appears to end users in a Teams meeting when they have captions enabled.
CART URL
You can get the CART URL for the POST endpoint from the Meeting options page in a Teams meeting. For more information, see CART captions in a Microsoft Teams meeting. You don't need to modify the CART URL to use CART captions.
Query Parameter
The CART URL includes the following query parameters:
Value | Type | Required | Description |
---|---|---|---|
meetingId | String | Yes | The meeting identifier is available through Bot Invoke and the TeamsJS library. For example, meetingid=%7b%22tId%22%3a%2272f234bf-86f1-41af-91ab-2d7cd0321b47%22%2c%22oId%22%3a%22e071f268-4241-47f8-8cf3-fc6b84437f23%22%2c%22thId%22%3a%2219%3ameeting_NzJiMjNkMGQtYzk3NS00ZDI1LWJjN2QtMDgyODVhZmI3NzJj%40thread.v2%22%2c%22mId%22%3a%220%22%7d |
token | String | Yes | Authorization token. For example, token=04751eac |
Example
https://api.captions.office.microsoft.com/cartcaption?meetingid=%7b%22tId%22%3a%2272f234bf-86f1-41af-91ab-2d7cd0321b47%22%2c%22oId%22%3a%22e071f268-4241-47f8-8cf3-fc6b84437f23%22%2c%22thId%22%3a%2219%3ameeting_NzJiMjNkMGQtYzk3NS00ZDI1LWJjN2QtMDgyODVhZmI3NzJj%40thread.v2%22%2c%22mId%22%3a%220%22%7d&token=gjs44ra
Method
Resource | Method | Description |
---|---|---|
/cartcaption | POST | Handle captions for meeting, which was started |
Note
Ensure that the content type for all requests is plain text with UTF-8 encoding. The body of request contains only captions.
Example
POST /cartcaption?meetingid=04751eac-30e6-47d9-9c3f-0b4ebe8e30d9&token=04751eac&lang=en-us HTTP/1.1
Host: api.captions.office.microsoft.com
Content-Type: text/plain
Content-Length: 22
Hello I’m Cortana, welcome to my meeting.
Note
Each POST request generates a new line of captions. To ensure that the end user has enough time to read the content, limit each POST request body to 80-120 characters.
Error codes
The following table provides the error codes:
Error code | Description |
---|---|
400 | Bad request. The response body has more information. For example, not of all required parameters presented. |
401 | Unauthorized. Bad or expired token. If you receive this error, generate a new CART URL in Teams. |
404 | Meeting not found or not started. If you receive this error, ensure that you start the meeting and select start captions. After captions are enabled in the meeting, you can begin POSTing captions into the meeting. |
500 | Internal server error. For more information, contact support or provide feedback. |
Receive real-time Teams meeting events
You can receive real-time meeting events such as meeting start and end or participant join and leave events.
Receive meeting start and end events
Note
Meeting start and end events are supported for scheduled and channel meetings.
The user can receive real-time meeting events. As soon as any app is associated with a meeting, the actual meeting start and end time are shared with the bot. The actual start and end time of a meeting are different from scheduled start and end time. The meeting details API provides the scheduled start and end time. The event provides the actual start and end time.
If the ChannelMeeting.ReadBasic.Group
and OnlineMeeting.ReadBasic.Chat
permissions are added in the manifest, the bot automatically starts receiving the meeting start or end events for the scheduled and channel meeting types.
Prerequisite
Your app manifest must have the webApplicationInfo
property to receive the meeting start and end events. Use the following examples to configure your manifest:
For app manifest version 1.12 and later
"webApplicationInfo": {
"id": "<bot id>",
"resource": "https://RscPermission",
},
"authorization": {
"permissions": {
"resourceSpecific": [
{
"name": "OnlineMeeting.ReadBasic.Chat",
"type": "Application"
}
{
"name": "ChannelMeeting.ReadBasic.Group",
"type": "Application"
}
]
}
}
For app manifest version 1.11 and earlier
"webApplicationInfo": {
"id": "<bot id>",
"resource": "https://RscPermission",
"applicationPermissions": [
"OnlineMeeting.ReadBasic.Chat",
"ChannelMeeting.ReadBasic.Group"
]
}
Example of getting meeting start or end events
The bot receives the meeting start and meeting end events through the OnTeamsMeetingStartAsync
and OnTeamsMeetingEndAsync
handlers. The information related to the meeting event is part of the MeetingStartEventDetails
object, which includes the metadata fields such as, meetingType
, title
, id
, joinUrl
, startTime
, and EndTime
.
Note
- Get meeting ID from
turnContext.ChannelData
. - Do not use conversation ID as meeting ID.
- Do not use meeting ID from meeting events payload
turncontext.activity.value
.
The following examples show how to capture the meeting start and end events:
Meeting Start Event
// Invoked when a Teams Meeting Start event activity is received from the connector.
protected override async Task OnTeamsMeetingStartAsync(MeetingStartEventDetails meeting, ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
// Sends a message activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(JsonConvert.SerializeObject(meeting));
}
Meeting End Event
// Invoked when a Teams Meeting End event activity is received from the connector.
protected override async Task OnTeamsMeetingEndAsync(MeetingEndEventDetails meeting, ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
// Sends a message activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(JsonConvert.SerializeObject(meeting));
}
Example of meeting start event payload
The following code provides an example of meeting start event payload:
{
"name": " application/vnd.microsoft.meetingStart",
"type": "event",
"timestamp": "2023-02-23T19:34:07.478Z",
"localTimestamp": "2023-02-23T11:34:07.478-8",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/teams/",
"from": {
"id": "user_id"
},
"conversation": {
"isGroup": true,
"conversationType": "groupchat",
"id": "conversation_id"
},
"recipient": {
"id": "28:65f50003-e15d-434a-9e14-0fcfeb3d7817"
},
"value": {
"id": "meeting_id",
"joinUrl": "join_url",
"title": "Example meeting",
"meetingType": "Scheduled",
"startTime": "2023-02-23T19:34:07.478Z"
},
"channelData": {
"tenant": {
"id": "tenant_id"
}
}
}
Example of meeting end event payload
The following code provides an example of meeting end event payload:
{
"name": " application/vnd.microsoft.meetingEnd",
"type": "event",
"timestamp": "2023-02-23T19:34:07.478Z",
"localTimestamp": "2023-02-23T11:34:07.478-8",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/teams/",
"from": {
"id": "user_id"
},
"conversation": {
"isGroup": true,
"conversationType": "groupchat",
"id": "conversation_id"
},
"recipient": {
"id": "28:65f50003-e15d-434a-9e14-0fcfeb3d7817"
},
"value": {
"id": "meeting_id",
"joinUrl": "join_url",
"title": "Example meeting",
"meetingType": "Scheduled",
"EndTime": "2023-02-23T20:30:07.478Z"
},
"channelData": {
"tenant": {
"id": "tenant_id"
}
}
}
Property name | Description |
---|---|
name | Name of the user. |
type | Activity type. |
timestamp | Local date and time of the message, expressed in ISO-8601 format. |
id | ID for the activity. |
channelId | Channel this activity is associated with. |
serviceUrl | Service URL where responses to this activity should be sent. |
from.id | ID of the user that sent the request. |
from.aadObjectId | Microsoft Entra object ID of the user that sent the request. |
conversation.isGroup | Boolean indicating whether conversation has more than two participants. |
conversation.tenantId | Microsoft Entra tenant ID of the conversation or meeting. |
conversation.id | The meeting chat ID. |
recipient.id | ID of the user that receives the request. |
recipient.name | Name of the user that receives the request. |
entities.locale | entity that contains metadata about locale. |
entities.country | entity that contains metadata about country. |
entities.type | entity that contains metadata about client. |
channelData.tenant.id | Microsoft Entra tenant ID. |
channelData.source | The source name from where event is fired or invoked. |
channelData.meeting.id | The default ID associated with the meeting. |
value.MeetingType | The type of meeting. |
value.Title | The subject of the meeting. |
value.Id | The default ID associated with the meeting. |
value.JoinUrl | The join URL of the meeting. |
value.StartTime | The meeting start time in UTC. |
value.EndTime | The meeting end time in UTC. |
locale | The locale of the message set by the client. |
Receive meeting participant events
Your bot can receive real-time meeting events such as participant join and leave events. A bot can receive the participant events only if subscribed to these events in Developer Portal.
Note
- Participant events are supported only for scheduled meetings.
- For a bot to receive participant events, ensure that you add the bot to the meeting before a participant joins or leaves the meeting.
To subscribe to participant events, follow these steps:
In Developer Portal open your bot app or import an existing app.
In the Meeting event subscriptions section, select the events:
- Participant join
- Participant leave
Select Save
Ensure that the
OnlineMeetingParticipant.Read.Chat
RSC permission is configured in your app manifest.If your app doesn't have the RSC permission, add it through the Configure > Permissions section of your app in Developer Portal. For more information, see RSC permissions.
The following examples show how to capture the participant join and leave events:
//Invoked on participant join a meeting
protected override async Task OnTeamsMeetingParticipantsJoinAsync(MeetingParticipantsEventDetails meeting, ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync("Member has joined the meeting.");
return;
}
Following are the examples of the participant join and leave event payloads:
The following is an example of the participant join event payload:
{
"type": "event",
"name": "application/vnd.microsoft.meetingParticipantJoin",
"timestamp": "2023-02-23T19:34:07.478Z",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer/",
"from": {
"id": "29:id_xyz"
},
"conversation": {
"isGroup": true,
"conversationType": "groupchat",
"id": "19:[email protected]"
},
"recipient": {
"id": "28:botid"
},
"value": {
"members": [
{
"user": {
"tenantId": "tenantid",
"objectId": "user_object_Id",
"id": "29:userId ",
"name": "Test User",
"aadObjectId": " user_object_Id "
},
"meeting": {
"inMeeting": true,
"role": "Organizer" //Attendee, Organizer, Presenter
},
}],
},
"channelData": {
"tenant": {
"id": "tenantId"
},
"meeting": {
"id": "encoded_meetingId"
}
}
}
Get incoming audio state
The getIncomingClientAudioState
API allows an app to get the incoming audio state setting for the meeting user. The API is available through the TeamsJS library.
Note
- The
getIncomingClientAudioState
API for mobile is available in Public Developer Preview. - The
toggleIncomingClientAudio
API is available in the new Teams client. - Resource specific consent is available for manifest version 1.12 and later versions, hence this API doesn't work for manifest version 1.11 and earlier versions.
Manifest
"authorization": {
"permissions": {
"resourceSpecific": [
{
"name": "OnlineMeetingParticipant.ToggleIncomingAudio.Chat",
"type": "Delegated"
}
]
}
}
Example
callback = (errcode, result) => {
if (errcode) {
// Handle error code
}
else {
// Handle success code
}
}
// The getIncomingClientAudioState API shows the current audio state.
microsoftTeams.meeting.getIncomingClientAudioState(this.callback)
Query parameter
The following table includes the query parameter:
Value | Type | Required | Description |
---|---|---|---|
callback | String | Yes | Callback contains two parameters error and result . The error can either contain an error type SdkError or null when the audio fetch is successful. The result can either contain true or false value when the audio fetch is successful or null when the audio fetch fails. The incoming audio is muted if the result is true and unmuted if the result is false. |
Response codes
The following table provides the response codes:
Response code | Description |
---|---|
500 | Internal error. |
501 | API isn't supported in the current context. |
1000 | App doesn't have proper permissions to allow share to stage. |
Toggle incoming audio
The toggleIncomingClientAudio
API allows an app to toggle the incoming audio state setting for the meeting user from mute to unmute or vice-versa. The API is available through the TeamsJS library.
Note
- The
toggleIncomingClientAudio
API for mobile is available in Public Developer Preview. - Resource specific consent is available for manifest version 1.12 and later versions, hence this API doesn't work for manifest version 1.11 and earlier versions.
Manifest
"authorization": {
"permissions": {
"resourceSpecific": [
{
"name": "OnlineMeetingParticipant.ToggleIncomingAudio.Chat",
"type": "Delegated"
}
]
}
}
Example
callback = (error, result) => {
if (error) {
// Handle error code
}
else {
// Handle success code
}
}
// The toggleIncomingClientAudio API allows an app to toggle the incoming audio state.
microsoftTeams.meeting.toggleIncomingClientAudio(this.callback)
Query parameter
The following table includes the query parameter:
Value | Type | Required | Description |
---|---|---|---|
callback | String | Yes | Callback contains two parameters error and result . The error can either contain an error type SdkError or null when the toggle is successful. The result can either contain true or false value, when the toggle is successful or null when the toggle fails. The incoming audio is muted if the result is true and unmuted if the result is false. |
Response code
The following table provides the response codes:
Response code | Description |
---|---|
500 | Internal error. |
501 | API isn't supported in the current context. |
1000 | App doesn't have proper permissions to allow share to stage. |
Code sample
Sample name | Description | .NET | Node.js | Manifest |
---|---|---|---|---|
Meetings extensibility | Teams meeting extensibility sample for passing tokens. | View | View | View |
In-meeting notification | Demonstrates how to implement in-meeting notification using bot. | View | View | View |
Meeting side panel | Teams meeting extensibility sample for interacting with the side panel in-meeting. | View | View | |
Details Tab in Meeting | This sample app shows Teams meeting extensibility feature where user can create a poll, and members can answer the poll in meeting. | View | View | View |
Meeting Events Sample | This sample shows real-time Teams meeting events using bot. | View | View | View |
Meeting Recruitment Sample | This sample app shows a meeting experience for recruitment scenario using Apps In Meetings. | View | View | View |
See also
Platform Docs