From 6317c324e7a64d6121a96303457c4f1ef8f7a5d1 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 6 Aug 2025 14:56:07 +0530 Subject: [PATCH 001/109] Updated the document --- .../build-and-test/shared-channels.md | 244 ++++++++++++++++-- 1 file changed, 224 insertions(+), 20 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index e5c9bb96c5f..2cdc6b920ee 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -8,9 +8,11 @@ ms.topic: conceptual ms.date: 04/09/2025 --- -# Microsoft Teams Connect shared channels +# Adapting Microsoft Teams App for Shared and Private Channels -Microsoft Teams Connect shared channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: +Microsoft Teams apps need to adapt to Shared and Private channels, which bring new collaboration patterns. This guide helps developers understand the changes required so their apps work smoothly across all channel types. + +Microsoft Teams Connect Shared and Private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a Shared channel with: * Members of another team within the same organization. * Individuals within the same organization. @@ -18,16 +20,92 @@ Microsoft Teams Connect shared channels allow members of a channel to collaborat > [!NOTE] > -> * Tab apps in shared channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. -> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. +> * Tab apps in Shared channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. +> * SharePoint and the SharePoint pages apps aren't supported for Shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. + +Teams Connect Shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. + +:::image type="content" source="~/assets/images/app-fundamentals/shared-channels-teams.png" alt-text="Diagram shows Team B from organization A and Team C from organization B collaborating in a Shared channel as Team A."::: + +## Understanding Shared and Private Channels in Microsoft Teams + +### Shared Channel + +Shared channels in Microsoft Teams let you collaborate with people who aren’t part of your team. Only those who are added as owners or members of the Shared channel can access it. Regular guest accounts (via Microsoft Entra) can’t be added to Shared channels. However, you can still invite people from outside your organization using Microsoft Entra B2B direct connect, which allows secure external collaboration without needing to add them as guests. More details [here](https://learn.microsoft.com/en-us/microsoftteams/shared-channels). + +### Private Channel + +Private channels in Microsoft Teams are special spaces for focused collaboration within a team. Only the people who are added as owners or members of the private channel can access it. You can include guests (users with Microsoft Entra guest accounts) in a private channel, but only if they are already part of the host team. + +### Feature Differences between Shared and Private Channels + +| Features | Standard Channel | Shared Channel | Private Channel | +|---------------------|------------------------|-----------------------------------------------------|--------------------------------------------------| +| People can be added to channel without adding to team | No | Yes | No | +|Channel membership can be limited to a subset of the team | No | Yes | Yes | +|Channel can be shared directly with other teams | No | Yes | No | +|Channel can be shared directly with its parent team | NA | Yes | No | +|Guests can participate in the channel |Yes | No | Yes | +|External participants (Direct Connect) can participate in channel |No | Yes | No | +|Each channel has a dedicated SharePoint site |No | Yes | Yes | + +Standard and private channels help team members collaborate within their own group. Shared channels, however, allow collaboration with people outside the team without needing to add them to the team. This opens up new ways of working but also requires apps to work differently in these shared spaces. + +## Reimagining App's Functionality for Shared and Private Channels + +As an app developer, it's important to rethink how your app works within Shared and Private channels in Microsoft Teams. These channels offer new ways for users to collaborate, so your app should be adapted to support their unique features. By making the right changes, you can improve both the app’s functionality and the user experience. + +## Why you should Adapt Apps to Shared and Private Channels + +As a developer, it's important to rethink how your app works in Microsoft Teams' Shared and Private channels. These channels offer new ways for users to collaborate—across teams and even across organizations—so your app needs to be flexible and aware of these environments. + +Why Adapting Your App Matters: + +1. Beyond Standard Channels: Without updates, your app won’t appear or function in Shared or Private channels. Some changes are mandatory for compatibility. +2. Wider Collaboration: Shared channels allow external users to join via Microsoft Entra B2B Direct Connect. Your app can support broader collaboration if properly configured. +3. Tailored Functionalities: You can highlight or build features that support cross-team workflows, like role-based permissions or scoped notifications. +4. Future-Proofing: These channels are the future of collaboration in Teams. Updating your app now ensures it remains relevant and competitive. + +## A Strategic Approach to Change + +Microsoft Teams is evolving with Shared and Private channels, and that means apps need to evolve too. To keep your app working smoothly across all channel types—standard, Shared, and Private—you need a clear strategy. + +### Mandatory Changes -Teams Connect shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. +If the app isn’t updated to support Shared and Private channels in Microsoft Teams, it might not work properly in those spaces. These changes are essential to avoid broken experiences for users. -:::image type="content" source="~/assets/images/app-fundamentals/shared-channels-teams.png" alt-text="Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A."::: +Note: Assess your app first and if it doesn’t depend on any of the following requirement, you can Mark your app is supported in Shared and Private channels in the app manifest and do functional changes later. -## Enable your app for shared channels +| Requirement | Description | Examples | +|------------------------|-----------------------------------------------------|--------------------------------------------------| +| Getting members of channel in which app will function | All members of team are also part of standard channels. But in Shared or Private channels it is flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content. | In a project management app that assigns tasks to members in a group, when working inside a Shared channel, you would need to get all members of the channel instead of members of team to correctly address the target users. | +|Accessing and storing data in Shared & Private channels | All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app will break and can leak data across channels. | For an app like a document management system that typically stores documents in team’s SharePoint site when working in standard channels, it will make changes to save and retrieve documents from the SharePoint sites dedicatedly linked to Shared or Private channels and not access team’s SharePoint site when working inside these channels. | +|Limit content access based on channels | As Shared and Private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you do not cross-post or cross-access data across channels and think carefully on your app scenarios | A summarization app can summarize non-confidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels. | +|Make your app available for Teams users in Shared and Private channels | After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app will not be discoverable in these channels anymore. **This is a Must-Do step for all apps.** -SupportedChannelTypes is an optional property that enables your app in non-standard channels. If your app supports the team scope and the property is defined, Teams enables your app in each channel type accordingly. Private and shared channels are supported. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). +### Optional Enhancements to Improve User Experience + +These updates are not required, but they can make your app work better in Shared and Private channels: + +| Requirement | Description | Examples | +|------------------------|-----------------------------------------------------|--------------------------------------------------| +| Privacy & Access Controls for app features | Implement conditional privacy & access controls within your app modules to cater to mix of internal and external users, protecting sensitive information as warranted for your app use-case. | For app which is used to conduct polls/surveys, while internal members might have the ability to create and analyse polls, external members in Shared channels or guests in private channels can be limited to have a 'respond-only' level of interaction and not allowed to create polls or view results of past polls.| +|Collaboration | Enhance features that facilitate smooth collaboration among diverse set of membership, like Shared task lists that provide clear visibility & editing permissions based on whether user is from host team, other team, or external to organization or is an in-tenant guest. | Whiteboarding apps could introduce a feature that allows external users in Shared channels or guests in private channels to add to the canvas, but these users cannot erase or edit internal members' contributions to the whiteboard. | +|Notification / Nudges | Refine your app's notification systems to avoid overloading users with irrelevant updates, possibly segmenting alerts by user group or channel type. | Helpdesk app used in a Shared channel, internal IT staff might receive immediate alerts for high-priority tickets or infrastructure issues, whereas external vendors might only receive notifications for tickets assigned to them or for maintenance schedules affecting their services. | + +## Technical Changes for App Compatibility with Shared and Private Channels + +With an enhanced understanding of of how users interact in Shared and Private channels, you can now focus on the technical steps to update your app. Microsoft Teams offers APIs specifically designed to work with these channels. + +### Identify Channels + +When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This helps the app adjust its functionality accordingly: + +| Tabs | Bots | +|--------------------------------------|----------------------------------------| +|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType == “Private”, | Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for Shared channel activities [(Bot activity handlers - Teams Microsoft Learn)](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/bot-concepts?tabs=csharp%2Cdotnet), to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private Channel turnContext.activity.channelData.channel.type == “private” | + +SupportedChannelTypes is an optional property that enables your app in non-standard channels. If your app supports the team scope and the property is defined, Teams enables your app in each channel type accordingly. Private and Shared channels are supported. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). ```JSON "supportedChannelTypes": [ @@ -41,25 +119,59 @@ SupportedChannelTypes is an optional property that enables your app in non-stand > * If your app supports the team scope, it functions in standard channels, regardless of what values are defined in this property. > * Your app might need to account for the unique properties of each of these channel types in order to function properly. -## Get context for shared channels +### Get Context for Shared Channels -When the content UX is loaded in a shared channel, use the data received from `getContext` call for shared channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. +When the content UX is loaded in a Shared or private channel, use the data received from `getContext` call for Shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the Shared channel. For more information to enable your tab, see: -* [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) +* [Get context for your tab for Private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) -## Apps and permissions in shared channels +### Managing Channel Members and Permissions in Microsoft Teams Apps + +To ensure your app functions correctly in Shared and Private Channels, you must use channel-specific APIs to gather accurate member information. This is important because: + +Team membership APIs is not equal to Shared or Private Channel membership +Shared and Private Channels have their own membership models, which are not the same as the parent team’s membership. + +Each channel has its own SharePoint site and permissions +Apps must respect these boundaries to avoid data leakage or access errors. + +### Get Host Team Group ID & Channel ID + +| Tabs | Bots | +|--------------------------------------|----------------------------------------| +|You can use below mentioned parameters received in getContext call to get host team ID and channel ID required for any Graph calls
1. JSv1 : hostTeamGroupID and channelId
2. JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
Get host team group Id from: turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
Get channel Id from: turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. + +Note: Do not store these parameters, as these values can change when host team of a Shared channel is modified by the channel owner. Recommended to always fetch these dynamically when needed. + +Then, call respective APIs listed below based on your app requirements: + +### Get All Members of a Private or Shared Channel + +If you are using Graph + +Pass the teamID and channelID fetched above in GET teams/{team-id}/channels/{channel-id}/allMembers to get all members of a Shared or a private channel. + +If you are using Bots SDK + +Pass the channel ID you received above in [getConversationMembers](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/team-chat-member-api-changes) API to get all members of a Shared or private channel. -You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. +Note: Next set of APIs are only required if you need to create any specific permissions or app experience based on type of member of a Shared channel, else you can skip these + +## Apps and permissions in Shared Channels + +You can collaborate with external members outside of your organization using Shared channels. App permissions in Shared channels follow the host team's app roster and host tenant's app policy. > [!NOTE] -> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. +> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a Shared channel. + +### Get Shared Channel Membership -## Get shared channel membership +You can get direct Shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: -You can get direct shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: +Note: This returns both internal and external users added to the Shared channel 1. Get direct members with [GET channel members API](/graph/api/channel-list-members?view=graph-rest-beta&tabs=http&preserve-view=true) API. @@ -78,8 +190,21 @@ You can get direct shared channel membership by using the `hostTeamGroupID` from ```http GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members ``` +## Retrieve Members of a Shared Channel in Microsoft Teams + +In Microsoft Teams, when a channel is shared with another team, its members are inherited from that team. These users are not directly added to the shared channel—they become members because the channel was shared with their team. + +Get each shared team with GET sharedWithTeams API. +GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams -## Classify members in the shared channel as in-tenant or out-tenant +Use GET members of each shared team (Team X) with GET sharedWithTeams API. +GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members + +With this information, structure your app to interpret member details and apply appropriate permissions as per your app use-case. + +For instance, Once your app identifies the channel type (standard, private, or shared) and retrieves member details using Microsoft Graph or Bot APIs, you can ensure that features like editing and task creation are selectively enabled based on user roles (Owners vs members vs External participants) determined through the preceding API responses. + +## Classify Members in the Shared channel as In-tenant or Out-tenant You can classify members as in-tenant or out-tenant by comparing `tenantID` of the member or team with `hostTeamTenantID` as follows: @@ -93,7 +218,43 @@ You can classify members as in-tenant or out-tenant by comparing `tenantID` of t -## Microsoft Entra native identity +## Handling External Users (B2B Direct connect) in Shared Channels + +When building Microsoft Teams app, especially for Shared channels, it is important to understand external users (people from outside your organization) who are part of Shared channel through B2B Direct Connect. + +For this, perform the following steps: + +Step 1: Identify External Users +To do this, get tenant ID of the channel in which your app is operating inside. + +| Tabs | Bots | +|--------------------------------------|----------------------------------------| +|You can use below mentioned parameters received in [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call to get host team ID and channel ID required for any Graph calls
•JSv1 : hostTeamGroupID and channelId
•JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
•Get host team group Id from turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
•Get channel Id from turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. + +Then, identify external users from direct members list you received for Shared channel. + +Get members of a Shared or a Private channel. +GET /teams/{host-team-group-id}/channels/{channel-id}/members + +Compare tenantID of each member with the hostTenantID property from above to classify member as out-of-tenant if TenantIds don’t match. + +## Authenticate External Users to Access your App Content in SharePoint + +Note: This step is only required when requesting the SharePoint token, i.e your app stores content in SharePoint service of the tenant in which channel is hosted. + + | Tabs | Bots | +|--------------------------------------|----------------------------------------| +|Save host tenant ID of Shared channel where tab is configured. You can get host tenant ID from channel.ownerTenantId for JSv2 or hostTenantId for JSv1 received under getContext call. | For any event payload or action payload received for a bot, use Get hostTenant ID, from turnContext.activity.conversation.tenantId| + +Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the Shared channel. + +## Identify Guest Users (B2B Guests) in Private Channels + +You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](https://learn.microsoft.com/en-us/graph/api/resources/conversationmember?view=graph-rest-1.0) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/en-us/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. + +For guests, “roles” = “guest” + +## Microsoft Entra Native Identity Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group IDs: @@ -102,7 +263,49 @@ Apps must function cross-tenants in installation and usage. The following table |Regular | Team Microsoft Entra group ID | Team Microsoft Entra group ID | |Shared | Empty | Host Team Microsoft Entra group ID | -## Apps in federated group chats with external users +## Access SharePoint Data in Shared and Private Channels + +If you're building an app using [SharePoint](https://learn.microsoft.com/en-us/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each Private channel has its own SPO site that is only accessible to members of that specific Shared or Private channel. + +Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or Private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/en-us/graph/api/channel-get-filesfolder?view=graph-rest-1.0&tabs=http). + +## Declare your App Works in Shared and Private Channels + +After making all the preceding changes, you need to declare your app’s manifest to declare that your app works in Shared and Private channels. + +This declaration will make your app visible to users in Shared and Private channels. Else, your app will not be discoverable to users in those channels. This is a mandatory update. + +supportsChannelFeatures is an optional property that enables your app in non-standard channels along with standard channels. + +Put supportsChannelFeatures as “level2” For more information, see . + +JSONCopy + +"supportsChannelFeatures": [ + + "Tier1"] + +Note: If your app supports team scope, it functions in standard channels, regardless of what values are defined in this property. + +Note: + +- When you declare support for "Tier1" in your app manifest. + - You are assuming the channel's roster matches the parent team. + - To get the full list of users with access—including direct and transitive members—use the API:GET /teams/{team-id}/channels/{channel-id}/allMembers + - This is the only API that returns everyone who can access the channel. Check the official documentation for more details. + +- Do not assume the type of users (e.g., guest, external, internal) in a channel’s roster. + - a. When using the GET /teams/{team-id}/channels/{channel-id}/allMembers API: + - Check the "roles" property to identify if the user is a guest. + - Check the "tenantId" property to determine if the user is:
*From the same tenant (intra-tenant), or
*From a different tenant (cross-tenant). + - This API returns both direct and transitive members—ensuring a complete view of channel access. + +- Do not assume that a channel’s storage location is the same as its parent team’s SharePoint site. + - Instead, always use the Microsoft Graph API endpoint: +GET /teams/{team-id}/channels/{channel-id}/filesFolder + - This API call returns the current and correct SharePoint document library location for the specified channel—especially important for Shared and Private channels, which have their own dedicated SharePoint sites. + +## Apps in Federated Group Chats with External Users > [!NOTE] > @@ -122,7 +325,7 @@ If you're developing an app for use in federated group chats with external users ## Code sample | Sample name | Description | Node.js | -|-------------|-------------|------|----| +|-------------|-------------|------| | Teams Conversation Bot | This sample app displays the names of the members in a federated group chat with external users. |[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-feed-members/nodejs/)| ## See also @@ -134,3 +337,4 @@ If you're developing an app for use in federated group chats with external users * [Retention policy for Teams locations](/microsoft-365/compliance/create-retention-policies) * [Use guest access and external access to collaborate with people outside your organization](/microsoftteams/communicate-with-users-from-other-organizations) * [Manage external meetings and chat with people and organizations using Microsoft identities](/microsoftteams/trusted-organizations-external-meetings-chat?tabs=organization-settings) + From 7815409181f388be9e7ee6feb89587319cea73ae Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 6 Aug 2025 18:53:57 +0530 Subject: [PATCH 002/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 2cdc6b920ee..de1deb9457c 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -10,8 +10,6 @@ ms.date: 04/09/2025 # Adapting Microsoft Teams App for Shared and Private Channels -Microsoft Teams apps need to adapt to Shared and Private channels, which bring new collaboration patterns. This guide helps developers understand the changes required so their apps work smoothly across all channel types. - Microsoft Teams Connect Shared and Private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a Shared channel with: * Members of another team within the same organization. From b24de9c1a6e8002300d738dbaa132c0f205ccf42 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 7 Aug 2025 11:27:03 +0530 Subject: [PATCH 003/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index de1deb9457c..c4b0dc33fb2 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -10,11 +10,12 @@ ms.date: 04/09/2025 # Adapting Microsoft Teams App for Shared and Private Channels -Microsoft Teams Connect Shared and Private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a Shared channel with: +Microsoft Teams apps need to adapt to shared and private channels, which bring new collaboration patterns. This guide helps developers in understanding the changes required so that their apps work smoothly across all channel types. + +Microsoft Teams Connects shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: * Members of another team within the same organization. -* Individuals within the same organization. -* Individuals and other teams of other organizations. +* Members of teams of other organizations. > [!NOTE] > @@ -29,11 +30,11 @@ Teams Connect Shared channels facilitate secure collaboration seamlessly. Allow ### Shared Channel -Shared channels in Microsoft Teams let you collaborate with people who aren’t part of your team. Only those who are added as owners or members of the Shared channel can access it. Regular guest accounts (via Microsoft Entra) can’t be added to Shared channels. However, you can still invite people from outside your organization using Microsoft Entra B2B direct connect, which allows secure external collaboration without needing to add them as guests. More details [here](https://learn.microsoft.com/en-us/microsoftteams/shared-channels). +Shared channels in Microsoft Teams let you collaborate with people who aren’t part of your team. Only users added as owners or members can access the shared channel. You can’t add regular guest accounts (via Microsoft Entra) to shared channels. However, you can still invite people from outside your organization through Microsoft Entra B2B direct connect, which enables secure external collaboration with no need to add them as guests. More details [here](https://learn.microsoft.com/en-us/microsoftteams/shared-channels). ### Private Channel -Private channels in Microsoft Teams are special spaces for focused collaboration within a team. Only the people who are added as owners or members of the private channel can access it. You can include guests (users with Microsoft Entra guest accounts) in a private channel, but only if they are already part of the host team. +Private channels in Microsoft Teams are special spaces for focused collaboration within a team. The system allows only people added as owners or members of the private channel to access it. You can include guests (users with Microsoft Entra guest accounts) in a private channel, but only if they are already part of the host team. ### Feature Differences between Shared and Private Channels @@ -47,53 +48,51 @@ Private channels in Microsoft Teams are special spaces for focused collaboration |External participants (Direct Connect) can participate in channel |No | Yes | No | |Each channel has a dedicated SharePoint site |No | Yes | Yes | -Standard and private channels help team members collaborate within their own group. Shared channels, however, allow collaboration with people outside the team without needing to add them to the team. This opens up new ways of working but also requires apps to work differently in these shared spaces. - ## Reimagining App's Functionality for Shared and Private Channels -As an app developer, it's important to rethink how your app works within Shared and Private channels in Microsoft Teams. These channels offer new ways for users to collaborate, so your app should be adapted to support their unique features. By making the right changes, you can improve both the app’s functionality and the user experience. +As an app developer, it’s important to rethink how your app works within shared and private channels in Microsoft Teams. Since these channels provide new way for users to collaborate, your app must adapt to support their unique features. ## Why you should Adapt Apps to Shared and Private Channels -As a developer, it's important to rethink how your app works in Microsoft Teams' Shared and Private channels. These channels offer new ways for users to collaborate—across teams and even across organizations—so your app needs to be flexible and aware of these environments. +As a developer, it's important to rethink how your app works in Microsoft Teams' shared and private channels. These channels offer new ways for users to collaborate—across teams and even across organizations—so your app needs to be flexible and aware of these environments. Why Adapting Your App Matters: -1. Beyond Standard Channels: Without updates, your app won’t appear or function in Shared or Private channels. Some changes are mandatory for compatibility. +1. Beyond Standard Channels: Without updates, your app does not appear or function in shared or private channels. Some changes are mandatory for compatibility. 2. Wider Collaboration: Shared channels allow external users to join via Microsoft Entra B2B Direct Connect. Your app can support broader collaboration if properly configured. 3. Tailored Functionalities: You can highlight or build features that support cross-team workflows, like role-based permissions or scoped notifications. 4. Future-Proofing: These channels are the future of collaboration in Teams. Updating your app now ensures it remains relevant and competitive. ## A Strategic Approach to Change -Microsoft Teams is evolving with Shared and Private channels, and that means apps need to evolve too. To keep your app working smoothly across all channel types—standard, Shared, and Private—you need a clear strategy. +Microsoft Teams is developing with shared and private channels, and that means apps need to develop too. To keep your app working smoothly across all channel types—standard, shared, and private—you need a logical strategy. ### Mandatory Changes -If the app isn’t updated to support Shared and Private channels in Microsoft Teams, it might not work properly in those spaces. These changes are essential to avoid broken experiences for users. +If you don’t update the app to support shared and private channels in Microsoft Teams, it might not work properly in those spaces.   -Note: Assess your app first and if it doesn’t depend on any of the following requirement, you can Mark your app is supported in Shared and Private channels in the app manifest and do functional changes later. +Note: First assess your app, and if it does not depend on any of the following requirements, you can mark that shared and private channels support your app in the app manifest and do functional changes later. -| Requirement | Description | Examples | +|Requirement|Description|Examples| |------------------------|-----------------------------------------------------|--------------------------------------------------| -| Getting members of channel in which app will function | All members of team are also part of standard channels. But in Shared or Private channels it is flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content. | In a project management app that assigns tasks to members in a group, when working inside a Shared channel, you would need to get all members of the channel instead of members of team to correctly address the target users. | -|Accessing and storing data in Shared & Private channels | All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app will break and can leak data across channels. | For an app like a document management system that typically stores documents in team’s SharePoint site when working in standard channels, it will make changes to save and retrieve documents from the SharePoint sites dedicatedly linked to Shared or Private channels and not access team’s SharePoint site when working inside these channels. | -|Limit content access based on channels | As Shared and Private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you do not cross-post or cross-access data across channels and think carefully on your app scenarios | A summarization app can summarize non-confidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels. | -|Make your app available for Teams users in Shared and Private channels | After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app will not be discoverable in these channels anymore. **This is a Must-Do step for all apps.** +| Getting members of channel in which app will function|All members of team are also part of standard channels. But in Shared or Private channels it is flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content.| In a project management app that assigns tasks to members in a group, when working inside a Shared channel, you would need to get all members of the channel instead of members of team to correctly address the target users.| +|Accessing and storing data in Shared & Private channels|All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app will break and can leak data across channels.|For an app like a document management system that typically stores documents in team’s SharePoint site when working in standard channels, it will make changes to save and retrieve documents from the SharePoint sites dedicatedly linked to Shared or Private channels and not access team’s SharePoint site when working inside these channels.| +|Limit content access based on channels|As Shared and Private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you do not cross-post or cross-access data across channels and think carefully on your app scenarios.|A summarization app can summarize non-confidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels.| +|Make your app available for Teams users in Shared and Private channels|After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app will not be discoverable in these channels anymore. **This is a Must-Do step for all apps.** ### Optional Enhancements to Improve User Experience -These updates are not required, but they can make your app work better in Shared and Private channels: +These updates are not required, but they can make your app work better in shared and private channels: -| Requirement | Description | Examples | +|Requirement|Description|Examples| |------------------------|-----------------------------------------------------|--------------------------------------------------| -| Privacy & Access Controls for app features | Implement conditional privacy & access controls within your app modules to cater to mix of internal and external users, protecting sensitive information as warranted for your app use-case. | For app which is used to conduct polls/surveys, while internal members might have the ability to create and analyse polls, external members in Shared channels or guests in private channels can be limited to have a 'respond-only' level of interaction and not allowed to create polls or view results of past polls.| -|Collaboration | Enhance features that facilitate smooth collaboration among diverse set of membership, like Shared task lists that provide clear visibility & editing permissions based on whether user is from host team, other team, or external to organization or is an in-tenant guest. | Whiteboarding apps could introduce a feature that allows external users in Shared channels or guests in private channels to add to the canvas, but these users cannot erase or edit internal members' contributions to the whiteboard. | -|Notification / Nudges | Refine your app's notification systems to avoid overloading users with irrelevant updates, possibly segmenting alerts by user group or channel type. | Helpdesk app used in a Shared channel, internal IT staff might receive immediate alerts for high-priority tickets or infrastructure issues, whereas external vendors might only receive notifications for tickets assigned to them or for maintenance schedules affecting their services. | +|Privacy & Access Controls for app features| Implement conditional privacy & access controls within your app modules to cater to mix of internal and external users, protecting sensitive information as warranted for your app use-case.| For app which is used to conduct polls/surveys, while internal members might have the ability to create and analyse polls, external members in Shared channels or guests in private channels can be limited to have a 'respond-only' level of interaction and not allowed to create polls or view results of past polls.| +|Collaboration| Enhance features that facilitate smooth collaboration among diverse set of membership, like Shared task lists that provide clear visibility & editing permissions based on whether user is from host team, other team, or external to organization or is an in-tenant guest.| Whiteboarding apps could introduce a feature that allows external users in Shared channels or guests in private channels to add to the canvas, but these users cannot erase or edit internal members' contributions to the whiteboard.| +|Notification / Nudges| Refine your app's notification systems to avoid overloading users with irrelevant updates, possibly segmenting alerts by user group or channel type.| Helpdesk app used in a Shared channel, internal IT staff might receive immediate alerts for high-priority tickets or infrastructure issues, whereas external vendors might only receive notifications for tickets assigned to them or for maintenance schedules affecting their services.| ## Technical Changes for App Compatibility with Shared and Private Channels -With an enhanced understanding of of how users interact in Shared and Private channels, you can now focus on the technical steps to update your app. Microsoft Teams offers APIs specifically designed to work with these channels. +With an enhanced understanding of how users interact in shared and private channels, you can now focus on the technical steps to update your app. Microsoft Teams offers APIs specifically designed to work with these channels. ### Identify Channels From 367483153ff90e71c4bd0cfc2eba85ea5b4753e0 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 7 Aug 2025 13:42:39 +0530 Subject: [PATCH 004/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index c4b0dc33fb2..30c497a882f 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -30,7 +30,7 @@ Teams Connect Shared channels facilitate secure collaboration seamlessly. Allow ### Shared Channel -Shared channels in Microsoft Teams let you collaborate with people who aren’t part of your team. Only users added as owners or members can access the shared channel. You can’t add regular guest accounts (via Microsoft Entra) to shared channels. However, you can still invite people from outside your organization through Microsoft Entra B2B direct connect, which enables secure external collaboration with no need to add them as guests. More details [here](https://learn.microsoft.com/en-us/microsoftteams/shared-channels). +Shared channels in Microsoft Teams let you collaborate with people who aren’t part of your team. Only users added as owners or members can access the shared channel. You can’t add regular guest accounts (via Microsoft Entra) to shared channels. However, you can still invite people from outside your organization through Microsoft Entra B2B direct connect, which enables secure external collaboration with no need to add them as guests. ### Private Channel @@ -96,13 +96,13 @@ With an enhanced understanding of how users interact in shared and private chann ### Identify Channels -When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This helps the app adjust its functionality accordingly: +When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This helps the app adjust its functionality accordingly. -| Tabs | Bots | +| Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType == “Private”, | Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for Shared channel activities [(Bot activity handlers - Teams Microsoft Learn)](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/bot-concepts?tabs=csharp%2Cdotnet), to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private Channel turnContext.activity.channelData.channel.type == “private” | +|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType == “Private”,|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for Shared channel activities [(Bot activity handlers - Teams Microsoft Learn)](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/bot-concepts?tabs=csharp%2Cdotnet), to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private Channel turnContext.activity.channelData.channel.type == “private”| -SupportedChannelTypes is an optional property that enables your app in non-standard channels. If your app supports the team scope and the property is defined, Teams enables your app in each channel type accordingly. Private and Shared channels are supported. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). +SupportedChannelTypes is an optional property that enables your app in non-standard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). ```JSON "supportedChannelTypes": [ @@ -113,27 +113,25 @@ SupportedChannelTypes is an optional property that enables your app in non-stand > [!NOTE] > -> * If your app supports the team scope, it functions in standard channels, regardless of what values are defined in this property. +> * If your app supports the team scope, it functions in standard channels, regardless of what this property defines. > * Your app might need to account for the unique properties of each of these channel types in order to function properly. ### Get Context for Shared Channels -When the content UX is loaded in a Shared or private channel, use the data received from `getContext` call for Shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the Shared channel. +When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. For more information to enable your tab, see: -* [Get context for your tab for Private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) +* [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) ### Managing Channel Members and Permissions in Microsoft Teams Apps -To ensure your app functions correctly in Shared and Private Channels, you must use channel-specific APIs to gather accurate member information. This is important because: +To ensure your app functions correctly in shared and private channels, you must use channel-specific APIs to gather accurate member information. This is important because: -Team membership APIs is not equal to Shared or Private Channel membership -Shared and Private Channels have their own membership models, which are not the same as the parent team’s membership. +TTeam membership APIs are not equal to shared or private Channel membershipShared and private channels have their own membership models, which are not the same as the parent team’s membership. -Each channel has its own SharePoint site and permissions -Apps must respect these boundaries to avoid data leakage or access errors. +Each channel has its own SharePointsite and permissionsApps must respect these boundaries to avoid data leakage or access errors. ### Get Host Team Group ID & Channel ID @@ -141,9 +139,9 @@ Apps must respect these boundaries to avoid data leakage or access errors. |--------------------------------------|----------------------------------------| |You can use below mentioned parameters received in getContext call to get host team ID and channel ID required for any Graph calls
1. JSv1 : hostTeamGroupID and channelId
2. JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
Get host team group Id from: turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
Get channel Id from: turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. -Note: Do not store these parameters, as these values can change when host team of a Shared channel is modified by the channel owner. Recommended to always fetch these dynamically when needed. +Note: Do not store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these dynamically when needed. -Then, call respective APIs listed below based on your app requirements: +Then, call APIs listed below based on your app requirements: ### Get All Members of a Private or Shared Channel @@ -155,7 +153,7 @@ If you are using Bots SDK Pass the channel ID you received above in [getConversationMembers](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/team-chat-member-api-changes) API to get all members of a Shared or private channel. -Note: Next set of APIs are only required if you need to create any specific permissions or app experience based on type of member of a Shared channel, else you can skip these +Note: Use the following APIs only if your app needs to create specific permissions or experiences based on the member type in a shared channel. Otherwise, you can skip them. ## Apps and permissions in Shared Channels From 4360c019d2589f9c1c99cf878f8a699053281768 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 7 Aug 2025 15:36:04 +0530 Subject: [PATCH 005/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 72 ++++++++++--------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 30c497a882f..6aab783890a 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -1,5 +1,5 @@ --- -title: Teams Connect Shared Channels +title: Teams Connects Shared Channels author: surbhigupta description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. ms.author: surbhigupta @@ -12,7 +12,7 @@ ms.date: 04/09/2025 Microsoft Teams apps need to adapt to shared and private channels, which bring new collaboration patterns. This guide helps developers in understanding the changes required so that their apps work smoothly across all channel types. -Microsoft Teams Connects shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: +Microsoft Teams Connect shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: * Members of another team within the same organization. * Members of teams of other organizations. @@ -22,7 +22,7 @@ Microsoft Teams Connects shared and private channels allow members of a channel > * Tab apps in Shared channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. > * SharePoint and the SharePoint pages apps aren't supported for Shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. -Teams Connect Shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. +Teams Connects Shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. :::image type="content" source="~/assets/images/app-fundamentals/shared-channels-teams.png" alt-text="Diagram shows Team B from organization A and Team C from organization B collaborating in a Shared channel as Team A."::: @@ -34,7 +34,7 @@ Shared channels in Microsoft Teams let you collaborate with people who aren’t ### Private Channel -Private channels in Microsoft Teams are special spaces for focused collaboration within a team. The system allows only people added as owners or members of the private channel to access it. You can include guests (users with Microsoft Entra guest accounts) in a private channel, but only if they are already part of the host team. +Private channels in Microsoft Teams are special spaces for focused collaboration within a team. The system allows only people added as owners or members of the private channel to access it. You can include guests (users with Microsoft Entra guest accounts) in a private channel, but only if they're already part of the host team. ### Feature Differences between Shared and Private Channels @@ -58,7 +58,7 @@ As a developer, it's important to rethink how your app works in Microsoft Teams' Why Adapting Your App Matters: -1. Beyond Standard Channels: Without updates, your app does not appear or function in shared or private channels. Some changes are mandatory for compatibility. +1. Beyond Standard Channels: Without updates, your app doesn't appear or function in shared or private channels. Some changes are mandatory for compatibility. 2. Wider Collaboration: Shared channels allow external users to join via Microsoft Entra B2B Direct Connect. Your app can support broader collaboration if properly configured. 3. Tailored Functionalities: You can highlight or build features that support cross-team workflows, like role-based permissions or scoped notifications. 4. Future-Proofing: These channels are the future of collaboration in Teams. Updating your app now ensures it remains relevant and competitive. @@ -71,36 +71,40 @@ Microsoft Teams is developing with shared and private channels, and that means a If you don’t update the app to support shared and private channels in Microsoft Teams, it might not work properly in those spaces.   -Note: First assess your app, and if it does not depend on any of the following requirements, you can mark that shared and private channels support your app in the app manifest and do functional changes later. +Note- Assess whether your app relies on specific requirements. If it doesn't, enable support for shared and private channels in the app manifest. You can apply functional changes later. |Requirement|Description|Examples| |------------------------|-----------------------------------------------------|--------------------------------------------------| -| Getting members of channel in which app will function|All members of team are also part of standard channels. But in Shared or Private channels it is flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content.| In a project management app that assigns tasks to members in a group, when working inside a Shared channel, you would need to get all members of the channel instead of members of team to correctly address the target users.| -|Accessing and storing data in Shared & Private channels|All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app will break and can leak data across channels.|For an app like a document management system that typically stores documents in team’s SharePoint site when working in standard channels, it will make changes to save and retrieve documents from the SharePoint sites dedicatedly linked to Shared or Private channels and not access team’s SharePoint site when working inside these channels.| -|Limit content access based on channels|As Shared and Private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you do not cross-post or cross-access data across channels and think carefully on your app scenarios.|A summarization app can summarize non-confidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels.| -|Make your app available for Teams users in Shared and Private channels|After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app will not be discoverable in these channels anymore. **This is a Must-Do step for all apps.** +| Getting members of channel in which app functions|All members of team are also part of standard channels. But in Shared or private channels it's flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content.| In a project management app, assigning tasks in a Shared channel means targeting channel members—not the full team.| +|Accessing and storing data in Shared & private channels|All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app breaks and can leak data across channels.|A document management app typically stores files on the team’s SharePoint site when working in standard channels. Shared and private channels have their own dedicated SharePoint sites, which are separate from the team’s site. The app saves and retrieves files from the SharePoint site that is linked to the specific channel, rather than using the team’s SharePoint site when operating within Shared or private channels.| +|Limit content access based on channels|As Shared and private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you don't cross-post or cross-access data across channels and think carefully on your app scenarios.|A summarization app can summarize non-confidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels.| +|Make your app available for Teams users in Shared and private channels|After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app isn't discoverable in these channels anymore. **This is a Must-Do step for all apps.** ### Optional Enhancements to Improve User Experience -These updates are not required, but they can make your app work better in shared and private channels: +These updates are'nt required, but they can make your app work better in shared and private channels: |Requirement|Description|Examples| |------------------------|-----------------------------------------------------|--------------------------------------------------| -|Privacy & Access Controls for app features| Implement conditional privacy & access controls within your app modules to cater to mix of internal and external users, protecting sensitive information as warranted for your app use-case.| For app which is used to conduct polls/surveys, while internal members might have the ability to create and analyse polls, external members in Shared channels or guests in private channels can be limited to have a 'respond-only' level of interaction and not allowed to create polls or view results of past polls.| -|Collaboration| Enhance features that facilitate smooth collaboration among diverse set of membership, like Shared task lists that provide clear visibility & editing permissions based on whether user is from host team, other team, or external to organization or is an in-tenant guest.| Whiteboarding apps could introduce a feature that allows external users in Shared channels or guests in private channels to add to the canvas, but these users cannot erase or edit internal members' contributions to the whiteboard.| +|Privacy & Access Controls for app features| Implement conditional privacy & access controls within your app modules to cater to mix of internal and external users, protecting sensitive information as warranted for your app use-case.|In a poll or survey app, internal members create polls and view results. External members in Shared channels and guests in Private channels only respond to polls. They can't create polls or see past results.| +|Collaboration| Make it easier for people to work together in Shared channels. Add task lists that everyone can see. If they are from the host team, they can add and change tasks. If they are from another team, they may have fewer rights. Guests inside the company and people from outside can see tasks, but can't change them..| Whiteboarding apps introduce a feature that lets external users in shared channels or guests in private channels add to the canvas. These users don't erase or edit contributions made by internal members.| |Notification / Nudges| Refine your app's notification systems to avoid overloading users with irrelevant updates, possibly segmenting alerts by user group or channel type.| Helpdesk app used in a Shared channel, internal IT staff might receive immediate alerts for high-priority tickets or infrastructure issues, whereas external vendors might only receive notifications for tickets assigned to them or for maintenance schedules affecting their services.| ## Technical Changes for App Compatibility with Shared and Private Channels -With an enhanced understanding of how users interact in shared and private channels, you can now focus on the technical steps to update your app. Microsoft Teams offers APIs specifically designed to work with these channels. +With an enhanced understanding of how users interact in shared and private channels, you can now focus on the technical steps to update your app. Microsoft Teams offers APIs to work with these channels. ### Identify Channels -When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This helps the app adjust its functionality accordingly. +When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This check helps the app adjust its functionality accordingly. | Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType == “Private”,|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for Shared channel activities [(Bot activity handlers - Teams Microsoft Learn)](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/bot-concepts?tabs=csharp%2Cdotnet), to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private Channel turnContext.activity.channelData.channel.type == “private”| +|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType =="Private",|To know where your bot was used in Microsoft Teams, you can check the channel.type property from the bot's activity data. check is found at turnContext.activity.channelData.channel.type. +If the value is "shared", it means the bot was used in a Shared channel. +If the value is "private", it means the bot was used in a Private channel. +This check helps your bot understand the context of the message and respond accordingly. +You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/bot-concepts?tabs=csharp%2Cdotnet)| SupportedChannelTypes is an optional property that enables your app in non-standard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). @@ -127,27 +131,27 @@ For more information to enable your tab, see: ### Managing Channel Members and Permissions in Microsoft Teams Apps -To ensure your app functions correctly in shared and private channels, you must use channel-specific APIs to gather accurate member information. This is important because: +To ensure your app functions correctly in shared and private channels, you must use channel-specific APIs to gather accurate member information. Usage of channel-specific APIS is important because: -TTeam membership APIs are not equal to shared or private Channel membershipShared and private channels have their own membership models, which are not the same as the parent team’s membership. +Team membership APIs aren't equal to shared or private Channel membershipShared and private channels have their own membership models, which aren't the same as the parent team’s membership. -Each channel has its own SharePointsite and permissionsApps must respect these boundaries to avoid data leakage or access errors. +Each channel has its own SharePoint site with its own permissions. Apps must follow these rules to prevent data leaks or access problems. ### Get Host Team Group ID & Channel ID | Tabs | Bots | |--------------------------------------|----------------------------------------| -|You can use below mentioned parameters received in getContext call to get host team ID and channel ID required for any Graph calls
1. JSv1 : hostTeamGroupID and channelId
2. JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
Get host team group Id from: turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
Get channel Id from: turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. +|You can use below mentioned parameters received in getContext call to get host team ID and channel ID required for any Graph calls
1. JSv1: hostTeamGroupID and channelId
2. JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
Get host team group ID from: turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
Get channel ID from: turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. -Note: Do not store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these dynamically when needed. +Note: Don't store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these dynamically when needed. Then, call APIs listed below based on your app requirements: ### Get All Members of a Private or Shared Channel -If you are using Graph +If you're using Graph -Pass the teamID and channelID fetched above in GET teams/{team-id}/channels/{channel-id}/allMembers to get all members of a Shared or a private channel. +Pass the teamID and channelID fetched above in GET teams/{team-ID}/channels/{channel-ID}/allMembers to get all members of a Shared or a private channel. If you are using Bots SDK @@ -164,9 +168,9 @@ You can collaborate with external members outside of your organization using Sha ### Get Shared Channel Membership -You can get direct Shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: +You can get direct shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: -Note: This returns both internal and external users added to the Shared channel +Note: This returns both internal and external users added to the Shared channel. 1. Get direct members with [GET channel members API](/graph/api/channel-list-members?view=graph-rest-beta&tabs=http&preserve-view=true) API. @@ -187,7 +191,7 @@ Note: This returns both internal and external users added to the Shared channel ``` ## Retrieve Members of a Shared Channel in Microsoft Teams -In Microsoft Teams, when a channel is shared with another team, its members are inherited from that team. These users are not directly added to the shared channel—they become members because the channel was shared with their team. +In Microsoft Teams, when you share a channel with another team, the channel includes that team’s members. The system doesn’t add users directly to the shared channel; instead, it grants access through their team’s connection to the channel. Get each shared team with GET sharedWithTeams API. GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams @@ -215,7 +219,7 @@ You can classify members as in-tenant or out-tenant by comparing `tenantID` of t ## Handling External Users (B2B Direct connect) in Shared Channels -When building Microsoft Teams app, especially for Shared channels, it is important to understand external users (people from outside your organization) who are part of Shared channel through B2B Direct Connect. +Each Teams channel links to its own SharePoint site with separate permissions. When building apps, make sure to check these limits so you don’t run into access issues or cause data leaks. For this, perform the following steps: @@ -224,7 +228,7 @@ To do this, get tenant ID of the channel in which your app is operating inside. | Tabs | Bots | |--------------------------------------|----------------------------------------| -|You can use below mentioned parameters received in [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call to get host team ID and channel ID required for any Graph calls
•JSv1 : hostTeamGroupID and channelId
•JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
•Get host team group Id from turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
•Get channel Id from turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. +|You can use below mentioned parameters received in [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call to get host team ID and channel ID required for any Graph calls
•JSv1: hostTeamGroupID and channelId
•JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
•Get host team group ID from turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
•Get channel ID from turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. Then, identify external users from direct members list you received for Shared channel. @@ -235,7 +239,7 @@ Compare tenantID of each member with the hostTenantID property from above to cla ## Authenticate External Users to Access your App Content in SharePoint -Note: This step is only required when requesting the SharePoint token, i.e your app stores content in SharePoint service of the tenant in which channel is hosted. +Note: This step is only required when requesting the SharePoint token, that is your app stores content in SharePoint service of the tenant in which channel is hosted. | Tabs | Bots | |--------------------------------------|----------------------------------------| @@ -268,7 +272,7 @@ Use the Graph API to access the document library of the SharePoint Online (SPO) After making all the preceding changes, you need to declare your app’s manifest to declare that your app works in Shared and Private channels. -This declaration will make your app visible to users in Shared and Private channels. Else, your app will not be discoverable to users in those channels. This is a mandatory update. +This declaration will make your app visible to users in Shared and Private channels. Else, your app won't be discoverable to users in those channels. This is a mandatory update. supportsChannelFeatures is an optional property that enables your app in non-standard channels along with standard channels. @@ -285,12 +289,12 @@ Note: If your app supports team scope, it functions in standard channels, regard Note: - When you declare support for "Tier1" in your app manifest. - - You are assuming the channel's roster matches the parent team. - - To get the full list of users with access—including direct and transitive members—use the API:GET /teams/{team-id}/channels/{channel-id}/allMembers + - You're assuming the channel's roster matches the parent team. + - To get the full list of users with access—including direct and transitive members—use the API: GET/teams/{team-id}/channels/{channel-id}/allMembers - This is the only API that returns everyone who can access the channel. Check the official documentation for more details. -- Do not assume the type of users (e.g., guest, external, internal) in a channel’s roster. - - a. When using the GET /teams/{team-id}/channels/{channel-id}/allMembers API: +- Don't assume the type of users (e.g., guest, external, internal) in a channel’s roster. + - a. When using the GET/teams/{team-id}/channels/{channel-id}/allMembers API: - Check the "roles" property to identify if the user is a guest. - Check the "tenantId" property to determine if the user is:
*From the same tenant (intra-tenant), or
*From a different tenant (cross-tenant). - This API returns both direct and transitive members—ensuring a complete view of channel access. From fad75456ebac22f2fe38f7b855773f5f4712d298 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 7 Aug 2025 16:11:16 +0530 Subject: [PATCH 006/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 6aab783890a..3c2667752e6 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -77,17 +77,17 @@ Note- Assess whether your app relies on specific requirements. If it doesn't, en |------------------------|-----------------------------------------------------|--------------------------------------------------| | Getting members of channel in which app functions|All members of team are also part of standard channels. But in Shared or private channels it's flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content.| In a project management app, assigning tasks in a Shared channel means targeting channel members—not the full team.| |Accessing and storing data in Shared & private channels|All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app breaks and can leak data across channels.|A document management app typically stores files on the team’s SharePoint site when working in standard channels. Shared and private channels have their own dedicated SharePoint sites, which are separate from the team’s site. The app saves and retrieves files from the SharePoint site that is linked to the specific channel, rather than using the team’s SharePoint site when operating within Shared or private channels.| -|Limit content access based on channels|As Shared and private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you don't cross-post or cross-access data across channels and think carefully on your app scenarios.|A summarization app can summarize non-confidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels.| -|Make your app available for Teams users in Shared and private channels|After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app isn't discoverable in these channels anymore. **This is a Must-Do step for all apps.** +|Limit content access based on channels|As Shared and private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you don't cross-post or cross-access data across channels and think carefully on your app scenarios.|A summarization app can summarize nonconfidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels.| +|Make your app available for Teams users in Shared and private channels|After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app isn't discoverable in these channels anymore. **This is a Must-Do step for all apps.** ### Optional Enhancements to Improve User Experience -These updates are'nt required, but they can make your app work better in shared and private channels: +These updates aren't required, but they can make your app work better in shared and private channels: |Requirement|Description|Examples| |------------------------|-----------------------------------------------------|--------------------------------------------------| |Privacy & Access Controls for app features| Implement conditional privacy & access controls within your app modules to cater to mix of internal and external users, protecting sensitive information as warranted for your app use-case.|In a poll or survey app, internal members create polls and view results. External members in Shared channels and guests in Private channels only respond to polls. They can't create polls or see past results.| -|Collaboration| Make it easier for people to work together in Shared channels. Add task lists that everyone can see. If they are from the host team, they can add and change tasks. If they are from another team, they may have fewer rights. Guests inside the company and people from outside can see tasks, but can't change them..| Whiteboarding apps introduce a feature that lets external users in shared channels or guests in private channels add to the canvas. These users don't erase or edit contributions made by internal members.| +|Collaboration| Make it easier for people to work together in Shared channels. Add task lists that everyone can see. If they are from the host team, they can add and change tasks. If they are from another team, they may have fewer rights. Guests inside the company and people from outside can see tasks, but can't change them.| Whiteboarding apps introduce a feature that lets external users in shared channels or guests in private channels add to the canvas. These users don't erase or edit contributions made by internal members.| |Notification / Nudges| Refine your app's notification systems to avoid overloading users with irrelevant updates, possibly segmenting alerts by user group or channel type.| Helpdesk app used in a Shared channel, internal IT staff might receive immediate alerts for high-priority tickets or infrastructure issues, whereas external vendors might only receive notifications for tickets assigned to them or for maintenance schedules affecting their services.| ## Technical Changes for App Compatibility with Shared and Private Channels @@ -100,13 +100,13 @@ When your app runs inside Microsoft Teams, it needs to know what kind of channel | Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType =="Private",|To know where your bot was used in Microsoft Teams, you can check the channel.type property from the bot's activity data. check is found at turnContext.activity.channelData.channel.type. -If the value is "shared", it means the bot was used in a Shared channel. -If the value is "private", it means the bot was used in a Private channel. +|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType =="Private,"|To know where your bot was used in Microsoft Teams, you can check the channel.type property from the bot's activity data. check is found at turnContext.activity.channelData.channel.type. +If the value is "shared," it means the bot was used in a Shared channel. +If the value is "private," it means the bot was used in a Private channel. This check helps your bot understand the context of the message and respond accordingly. You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/bot-concepts?tabs=csharp%2Cdotnet)| -SupportedChannelTypes is an optional property that enables your app in non-standard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). +SupportedChannelTypes is an optional property that enables your app in nonstandard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). ```JSON "supportedChannelTypes": [ @@ -118,7 +118,7 @@ SupportedChannelTypes is an optional property that enables your app in non-stand > [!NOTE] > > * If your app supports the team scope, it functions in standard channels, regardless of what this property defines. -> * Your app might need to account for the unique properties of each of these channel types in order to function properly. +> * To work well in all channel types, your app should handle the special rules and settings of each one. ### Get Context for Shared Channels @@ -274,7 +274,7 @@ After making all the preceding changes, you need to declare your app’s manifes This declaration will make your app visible to users in Shared and Private channels. Else, your app won't be discoverable to users in those channels. This is a mandatory update. -supportsChannelFeatures is an optional property that enables your app in non-standard channels along with standard channels. +supportsChannelFeatures is an optional property that enables your app in nonstandard channels along with standard channels. Put supportsChannelFeatures as “level2” For more information, see . From 1a107093594249d6866074bbf45862a63eccfaab Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 7 Aug 2025 18:17:54 +0530 Subject: [PATCH 007/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 3c2667752e6..3de83d0d112 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -76,7 +76,7 @@ Note- Assess whether your app relies on specific requirements. If it doesn't, en |Requirement|Description|Examples| |------------------------|-----------------------------------------------------|--------------------------------------------------| | Getting members of channel in which app functions|All members of team are also part of standard channels. But in Shared or private channels it's flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content.| In a project management app, assigning tasks in a Shared channel means targeting channel members—not the full team.| -|Accessing and storing data in Shared & private channels|All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app breaks and can leak data across channels.|A document management app typically stores files on the team’s SharePoint site when working in standard channels. Shared and private channels have their own dedicated SharePoint sites, which are separate from the team’s site. The app saves and retrieves files from the SharePoint site that is linked to the specific channel, rather than using the team’s SharePoint site when operating within Shared or private channels.| +|Accessing and storing data in Shared & private channels|All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app breaks and can leak data across channels.|A document management app typically stores files on the team’s SharePoint site when working in standard channels. Shared and private channels have their own dedicated SharePoint sites, which are separate from the team’s site. The app saves and retrieves files from the SharePoint site that is linked to the specific channel, rather than using the team’s SharePoint site when operating within Shared or private channels.| |Limit content access based on channels|As Shared and private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you don't cross-post or cross-access data across channels and think carefully on your app scenarios.|A summarization app can summarize nonconfidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels.| |Make your app available for Teams users in Shared and private channels|After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app isn't discoverable in these channels anymore. **This is a Must-Do step for all apps.** @@ -100,11 +100,11 @@ When your app runs inside Microsoft Teams, it needs to know what kind of channel | Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call
For Shared channel, channel.membershipType == “Shared”,
For private channel channel.membershipType =="Private,"|To know where your bot was used in Microsoft Teams, you can check the channel.type property from the bot's activity data. check is found at turnContext.activity.channelData.channel.type. +|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == “Shared,”
For private channel channel.membershipType =="Private,"|To know where your bot was used in Microsoft Teams, you can check the channel.type property from the bot's activity data. check is found at turnContext.activity.channelData.channel.type. If the value is "shared," it means the bot was used in a Shared channel. If the value is "private," it means the bot was used in a Private channel. This check helps your bot understand the context of the message and respond accordingly. -You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/bot-concepts?tabs=csharp%2Cdotnet)| +You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) SupportedChannelTypes is an optional property that enables your app in nonstandard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). @@ -226,22 +226,22 @@ For this, perform the following steps: Step 1: Identify External Users To do this, get tenant ID of the channel in which your app is operating inside. -| Tabs | Bots | +|Tabs|Bots| |--------------------------------------|----------------------------------------| |You can use below mentioned parameters received in [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call to get host team ID and channel ID required for any Graph calls
•JSv1: hostTeamGroupID and channelId
•JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
•Get host team group ID from turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
•Get channel ID from turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. Then, identify external users from direct members list you received for Shared channel. -Get members of a Shared or a Private channel. +Get members of a shared or a private channel. GET /teams/{host-team-group-id}/channels/{channel-id}/members Compare tenantID of each member with the hostTenantID property from above to classify member as out-of-tenant if TenantIds don’t match. ## Authenticate External Users to Access your App Content in SharePoint -Note: This step is only required when requesting the SharePoint token, that is your app stores content in SharePoint service of the tenant in which channel is hosted. +Note: This step is only required when requesting the SharePoint token that is your app stores content in SharePoint service of the tenant in which channel is hosted. - | Tabs | Bots | + |Tabs|Bots| |--------------------------------------|----------------------------------------| |Save host tenant ID of Shared channel where tab is configured. You can get host tenant ID from channel.ownerTenantId for JSv2 or hostTenantId for JSv1 received under getContext call. | For any event payload or action payload received for a bot, use Get hostTenant ID, from turnContext.activity.conversation.tenantId| @@ -264,15 +264,15 @@ Apps must function cross-tenants in installation and usage. The following table ## Access SharePoint Data in Shared and Private Channels -If you're building an app using [SharePoint](https://learn.microsoft.com/en-us/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each Private channel has its own SPO site that is only accessible to members of that specific Shared or Private channel. +If you're building an app using [SharePoint](https://learn.microsoft.com/en-us/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. -Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or Private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/en-us/graph/api/channel-get-filesfolder?view=graph-rest-1.0&tabs=http). +Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/en-us/graph/api/channel-get-filesfolder?view=graph-rest-1.0&tabs=http). ## Declare your App Works in Shared and Private Channels -After making all the preceding changes, you need to declare your app’s manifest to declare that your app works in Shared and Private channels. +After making all the preceding changes, you need to declare your app’s manifest to declare that your app works in Shared and private channels. -This declaration will make your app visible to users in Shared and Private channels. Else, your app won't be discoverable to users in those channels. This is a mandatory update. +This declaration will make your app visible to users in Shared and private channels. Else, your app won't be discoverable to users in those channels. This is a mandatory update. supportsChannelFeatures is an optional property that enables your app in nonstandard channels along with standard channels. @@ -302,7 +302,7 @@ Note: - Do not assume that a channel’s storage location is the same as its parent team’s SharePoint site. - Instead, always use the Microsoft Graph API endpoint: GET /teams/{team-id}/channels/{channel-id}/filesFolder - - This API call returns the current and correct SharePoint document library location for the specified channel—especially important for Shared and Private channels, which have their own dedicated SharePoint sites. + - This API call returns the current and correct SharePoint document library location for the specified channel—especially important for shared and private channels, which have their own dedicated SharePoint sites. ## Apps in Federated Group Chats with External Users @@ -323,9 +323,9 @@ If you're developing an app for use in federated group chats with external users ## Code sample -| Sample name | Description | Node.js | +|Sample name|Description|Node.js| |-------------|-------------|------| -| Teams Conversation Bot | This sample app displays the names of the members in a federated group chat with external users. |[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-feed-members/nodejs/)| +|Teams Conversation Bot|This sample app displays the names of the members in a federated group chat with external users.|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-feed-members/nodejs/)| ## See also @@ -336,4 +336,3 @@ If you're developing an app for use in federated group chats with external users * [Retention policy for Teams locations](/microsoft-365/compliance/create-retention-policies) * [Use guest access and external access to collaborate with people outside your organization](/microsoftteams/communicate-with-users-from-other-organizations) * [Manage external meetings and chat with people and organizations using Microsoft identities](/microsoftteams/trusted-organizations-external-meetings-chat?tabs=organization-settings) - From 380a5305bc11967e1fc86a8ca45347f6cd86261f Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 7 Aug 2025 23:18:11 +0530 Subject: [PATCH 008/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 3de83d0d112..e002a450738 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -98,13 +98,9 @@ With an enhanced understanding of how users interact in shared and private chann When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This check helps the app adjust its functionality accordingly. -| Tabs| Bots| +|Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == “Shared,”
For private channel channel.membershipType =="Private,"|To know where your bot was used in Microsoft Teams, you can check the channel.type property from the bot's activity data. check is found at turnContext.activity.channelData.channel.type. -If the value is "shared," it means the bot was used in a Shared channel. -If the value is "private," it means the bot was used in a Private channel. -This check helps your bot understand the context of the message and respond accordingly. -You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) +|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == “Shared,”
For private channel channel.membershipType =="Private,"|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for shared channel activities, to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private ChannelturnContext.activity.channelData.channel.type == “private” You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) SupportedChannelTypes is an optional property that enables your app in nonstandard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). @@ -155,7 +151,7 @@ Pass the teamID and channelID fetched above in GET teams/{team-ID}/channels/{cha If you are using Bots SDK -Pass the channel ID you received above in [getConversationMembers](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/team-chat-member-api-changes) API to get all members of a Shared or private channel. +Pass the channel ID you received above in [getConversationMembers](../../resources/team-chat-member-api-changes.md) API to get all members of a Shared or private channel. Note: Use the following APIs only if your app needs to create specific permissions or experiences based on the member type in a shared channel. Otherwise, you can skip them. @@ -228,7 +224,7 @@ To do this, get tenant ID of the channel in which your app is operating inside. |Tabs|Bots| |--------------------------------------|----------------------------------------| -|You can use below mentioned parameters received in [getContext](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context?tabs=Json-v2%2Cteamsjs-v2%2Cdefault) call to get host team ID and channel ID required for any Graph calls
•JSv1: hostTeamGroupID and channelId
•JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
•Get host team group ID from turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
•Get channel ID from turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. +|You can use below mentioned parameters received in [getContext](../../tabs/how-to/access-teams-context.md) call to get host team ID and channel ID required for any Graph calls
•JSv1: hostTeamGroupID and channelId
•JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
•Get host team group ID from turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
•Get channel ID from turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. Then, identify external users from direct members list you received for Shared channel. @@ -264,9 +260,9 @@ Apps must function cross-tenants in installation and usage. The following table ## Access SharePoint Data in Shared and Private Channels -If you're building an app using [SharePoint](https://learn.microsoft.com/en-us/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. +If you're building an app using [SharePoint](../../integrate-with-teams-introduction.md) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. -Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/en-us/graph/api/channel-get-filesfolder?view=graph-rest-1.0&tabs=http). +Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](../../channel-get-filesfolder.md). ## Declare your App Works in Shared and Private Channels @@ -278,11 +274,13 @@ supportsChannelFeatures is an optional property that enables your app in nonstan Put supportsChannelFeatures as “level2” For more information, see . -JSONCopy +Json +{ + "supportsChannelFeatures": [ + "Tier1" + ] +} -"supportsChannelFeatures": [ - - "Tier1"] Note: If your app supports team scope, it functions in standard channels, regardless of what values are defined in this property. From 28b01e4eb7de2393bc87f915e3bd01fecdbc2694 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 8 Aug 2025 10:30:40 +0530 Subject: [PATCH 009/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index e002a450738..55ea47c83d2 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -100,7 +100,7 @@ When your app runs inside Microsoft Teams, it needs to know what kind of channel |Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == “Shared,”
For private channel channel.membershipType =="Private,"|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for shared channel activities, to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private ChannelturnContext.activity.channelData.channel.type == “private” You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) +|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == “Shared,”
For private channel channel.membershipType =="Private,"|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for shared channel activities, to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private ChannelturnContext.activity.channelData.channel.type == “private” You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) SupportedChannelTypes is an optional property that enables your app in nonstandard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). @@ -245,7 +245,7 @@ Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to ## Identify Guest Users (B2B Guests) in Private Channels -You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](https://learn.microsoft.com/en-us/graph/api/resources/conversationmember?view=graph-rest-1.0) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/en-us/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. +You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](https://learn.microsoft.com/graph/api/resources/conversationmember?view=graph-rest-1.0) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. For guests, “roles” = “guest” @@ -260,7 +260,7 @@ Apps must function cross-tenants in installation and usage. The following table ## Access SharePoint Data in Shared and Private Channels -If you're building an app using [SharePoint](../../integrate-with-teams-introduction.md) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. +If you're building an app using [SharePoint](https://learn.microsoft.com/en-us/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](../../channel-get-filesfolder.md). From b4f28e14e4e1c05f0f530159b60977c0cb56c417 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 8 Aug 2025 11:33:02 +0530 Subject: [PATCH 010/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 55ea47c83d2..e9efe7a7350 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -12,7 +12,7 @@ ms.date: 04/09/2025 Microsoft Teams apps need to adapt to shared and private channels, which bring new collaboration patterns. This guide helps developers in understanding the changes required so that their apps work smoothly across all channel types. -Microsoft Teams Connect shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: +Microsoft Teams Connects shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: * Members of another team within the same organization. * Members of teams of other organizations. @@ -100,7 +100,7 @@ When your app runs inside Microsoft Teams, it needs to know what kind of channel |Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == “Shared,”
For private channel channel.membershipType =="Private,"|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for shared channel activities, to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private ChannelturnContext.activity.channelData.channel.type == “private” You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) +|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == "Shared,"
For private channel channel.membershipType =="Private,"|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for shared channel activities, to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private ChannelturnContext.activity.channelData.channel.type == “private” You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) SupportedChannelTypes is an optional property that enables your app in nonstandard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). @@ -292,7 +292,7 @@ Note: - This is the only API that returns everyone who can access the channel. Check the official documentation for more details. - Don't assume the type of users (e.g., guest, external, internal) in a channel’s roster. - - a. When using the GET/teams/{team-id}/channels/{channel-id}/allMembers API: + a. When using the GET/teams/{team-id}/channels/{channel-id}/allMembers API: - Check the "roles" property to identify if the user is a guest. - Check the "tenantId" property to determine if the user is:
*From the same tenant (intra-tenant), or
*From a different tenant (cross-tenant). - This API returns both direct and transitive members—ensuring a complete view of channel access. From c9c793a2e79e14d187632fe616047f4237a962f0 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Mon, 11 Aug 2025 10:47:47 +0530 Subject: [PATCH 011/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index e9efe7a7350..8497f6e00d2 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -245,7 +245,7 @@ Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to ## Identify Guest Users (B2B Guests) in Private Channels -You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](https://learn.microsoft.com/graph/api/resources/conversationmember?view=graph-rest-1.0) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](https://learn.microsoft.com/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. +You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember?view=graph-rest-1.0) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. For guests, “roles” = “guest” @@ -260,7 +260,7 @@ Apps must function cross-tenants in installation and usage. The following table ## Access SharePoint Data in Shared and Private Channels -If you're building an app using [SharePoint](https://learn.microsoft.com/en-us/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. +If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](../../channel-get-filesfolder.md). From 9a4345eb7d02911b1ca440626cd35dbd05e5329b Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Mon, 11 Aug 2025 10:56:31 +0530 Subject: [PATCH 012/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 8497f6e00d2..b63b3c8c1dd 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -245,7 +245,7 @@ Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to ## Identify Guest Users (B2B Guests) in Private Channels -You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember?view=graph-rest-1.0) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. +You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. For guests, “roles” = “guest” From 64b54e65f4fd59e9d1c26de636b741b3f23ce3bf Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Mon, 11 Aug 2025 11:32:47 +0530 Subject: [PATCH 013/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index b63b3c8c1dd..dc5d84b3873 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -245,7 +245,7 @@ Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to ## Identify Guest Users (B2B Guests) in Private Channels -You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members?view=graph-rest-1.0&tabs=http) response. +You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. For guests, “roles” = “guest” @@ -262,7 +262,7 @@ Apps must function cross-tenants in installation and usage. The following table If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. -Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](../../channel-get-filesfolder.md). +Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). ## Declare your App Works in Shared and Private Channels From e90a29661a1048a9ddfeb9af67c13882d7806d4c Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Mon, 11 Aug 2025 13:11:48 +0530 Subject: [PATCH 014/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index dc5d84b3873..61b53241b70 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -1,5 +1,5 @@ --- -title: Teams Connects Shared Channels +title: Teams Connect Shared Channels author: surbhigupta description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. ms.author: surbhigupta @@ -12,7 +12,7 @@ ms.date: 04/09/2025 Microsoft Teams apps need to adapt to shared and private channels, which bring new collaboration patterns. This guide helps developers in understanding the changes required so that their apps work smoothly across all channel types. -Microsoft Teams Connects shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: +Microsoft Teams Connect shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: * Members of another team within the same organization. * Members of teams of other organizations. @@ -129,7 +129,7 @@ For more information to enable your tab, see: To ensure your app functions correctly in shared and private channels, you must use channel-specific APIs to gather accurate member information. Usage of channel-specific APIS is important because: -Team membership APIs aren't equal to shared or private Channel membershipShared and private channels have their own membership models, which aren't the same as the parent team’s membership. +Team membership APIs aren't equal to shared or private Channel membership Shared and private channels have their own membership models, which aren't the same as the parent team’s membership. Each channel has its own SharePoint site with its own permissions. Apps must follow these rules to prevent data leaks or access problems. From f00102de794c5a71245b159be99f9dd5b5c03e0b Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 13:12:34 +0530 Subject: [PATCH 015/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 257 +++++++++++++----- 1 file changed, 190 insertions(+), 67 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 61b53241b70..1b46ded4ad7 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -8,14 +8,9 @@ ms.topic: conceptual ms.date: 04/09/2025 --- -# Adapting Microsoft Teams App for Shared and Private Channels +# Microsoft Teams connects for shared and private Channels -Microsoft Teams apps need to adapt to shared and private channels, which bring new collaboration patterns. This guide helps developers in understanding the changes required so that their apps work smoothly across all channel types. - -Microsoft Teams Connect shared and private channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: - -* Members of another team within the same organization. -* Members of teams of other organizations. +Microsoft Teams apps must support shared and private channels, which introduce new collaboration scenarios across teams and organizations. Shared channels in Microsoft Teams Connect can be created and shared with members of other teams within the same organization or with teams from external organizations. > [!NOTE] > @@ -24,19 +19,19 @@ Microsoft Teams Connect shared and private channels allow members of a channel t Teams Connects Shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. -:::image type="content" source="~/assets/images/app-fundamentals/shared-channels-teams.png" alt-text="Diagram shows Team B from organization A and Team C from organization B collaborating in a Shared channel as Team A."::: + ![Diagram shows Team B from organization A and Team C from organization B collaborating in a Shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) -## Understanding Shared and Private Channels in Microsoft Teams +## Understanding shared and private channels in Microsoft Teams -### Shared Channel +### Shared channel Shared channels in Microsoft Teams let you collaborate with people who aren’t part of your team. Only users added as owners or members can access the shared channel. You can’t add regular guest accounts (via Microsoft Entra) to shared channels. However, you can still invite people from outside your organization through Microsoft Entra B2B direct connect, which enables secure external collaboration with no need to add them as guests. -### Private Channel +### Private channel Private channels in Microsoft Teams are special spaces for focused collaboration within a team. The system allows only people added as owners or members of the private channel to access it. You can include guests (users with Microsoft Entra guest accounts) in a private channel, but only if they're already part of the host team. -### Feature Differences between Shared and Private Channels +### Feature differences between shared and private channels | Features | Standard Channel | Shared Channel | Private Channel | |---------------------|------------------------|-----------------------------------------------------|--------------------------------------------------| @@ -48,53 +43,31 @@ Private channels in Microsoft Teams are special spaces for focused collaboration |External participants (Direct Connect) can participate in channel |No | Yes | No | |Each channel has a dedicated SharePoint site |No | Yes | Yes | -## Reimagining App's Functionality for Shared and Private Channels - -As an app developer, it’s important to rethink how your app works within shared and private channels in Microsoft Teams. Since these channels provide new way for users to collaborate, your app must adapt to support their unique features. - -## Why you should Adapt Apps to Shared and Private Channels - -As a developer, it's important to rethink how your app works in Microsoft Teams' shared and private channels. These channels offer new ways for users to collaborate—across teams and even across organizations—so your app needs to be flexible and aware of these environments. - -Why Adapting Your App Matters: - -1. Beyond Standard Channels: Without updates, your app doesn't appear or function in shared or private channels. Some changes are mandatory for compatibility. -2. Wider Collaboration: Shared channels allow external users to join via Microsoft Entra B2B Direct Connect. Your app can support broader collaboration if properly configured. -3. Tailored Functionalities: You can highlight or build features that support cross-team workflows, like role-based permissions or scoped notifications. -4. Future-Proofing: These channels are the future of collaboration in Teams. Updating your app now ensures it remains relevant and competitive. - -## A Strategic Approach to Change - -Microsoft Teams is developing with shared and private channels, and that means apps need to develop too. To keep your app working smoothly across all channel types—standard, shared, and private—you need a logical strategy. - -### Mandatory Changes +### Teams channel models – capabilities comparison -If you don’t update the app to support shared and private channels in Microsoft Teams, it might not work properly in those spaces.   +| **Category** | **Capability** | **Standard channel** | **Private channel** | **Shared channel** | +|--------------|----------------------------------------------------------------------------------|----------------------|---------------------|---------------------| +| **Membership** | Can add people to the channel without adding to the host team | No | No | Yes | +| | Channel membership can be limited to a subset of the host team | No | Yes | Yes | +| | Channel can be shared with other teams to inherit members from the team | No | No | Yes | +| | Channel can be shared directly with its parent team to inherit members | N/A | No | Yes | +| | Guests (B2B Guests) can participate in the channel | Yes | Yes | No | +| | External participants (B2B Direct Connect) can participate in the channel | No | No | Yes | +| | Channel is hosted under a host team | Yes | Yes | Yes | +| **Storage** | Each channel has a dedicated SharePoint site | No (inherits team site) | Yes | Yes | +| **App Model** | App must be installed in the host team | Yes | Yes | Yes | +| | App installed to host team automatically available in channel | Yes | No | No | +| | App must be added to each channel | No | Yes | Yes | -Note- Assess whether your app relies on specific requirements. If it doesn't, enable support for shared and private channels in the app manifest. You can apply functional changes later. +## A strategic approach to change -|Requirement|Description|Examples| -|------------------------|-----------------------------------------------------|--------------------------------------------------| -| Getting members of channel in which app functions|All members of team are also part of standard channels. But in Shared or private channels it's flexible depending on the channel owner's choice. So make sure you use channel specific members APIs rather than using team members APIs, else your app can work unexpectedly for members outside the channel and leak content.| In a project management app, assigning tasks in a Shared channel means targeting channel members—not the full team.| -|Accessing and storing data in Shared & private channels|All standard channels share the same SharePoint site. But each Shared and private channel has its own SharePoint site for storing files or app content. So, make sure you use APIs available to access channel’s sharepoint site vs Team’s sharepoint site, else your app breaks and can leak data across channels.|A document management app typically stores files on the team’s SharePoint site when working in standard channels. Shared and private channels have their own dedicated SharePoint sites, which are separate from the team’s site. The app saves and retrieves files from the SharePoint site that is linked to the specific channel, rather than using the team’s SharePoint site when operating within Shared or private channels.| -|Limit content access based on channels|As Shared and private channels can have sensitive or restricted content not to be Shared outside channel, so ensure you don't cross-post or cross-access data across channels and think carefully on your app scenarios.|A summarization app can summarize nonconfidential chats/messages from all channels inside a team and post in a standard channel or to a group of team members. This app makes changes to not access private or Shared channel messages for this scenario and only get messages from standard channels.| -|Make your app available for Teams users in Shared and private channels|After you make necessary changes to your app, you must mark in App manifest that your app now is also supported in Shared and private channels. Else, your app isn't discoverable in these channels anymore. **This is a Must-Do step for all apps.** +Microsoft Teams is developing with shared and private channels, and that means apps need to develop too. To keep your app working smoothly across all channel types: standard, shared, and private you need a logical strategy. -### Optional Enhancements to Improve User Experience - -These updates aren't required, but they can make your app work better in shared and private channels: - -|Requirement|Description|Examples| -|------------------------|-----------------------------------------------------|--------------------------------------------------| -|Privacy & Access Controls for app features| Implement conditional privacy & access controls within your app modules to cater to mix of internal and external users, protecting sensitive information as warranted for your app use-case.|In a poll or survey app, internal members create polls and view results. External members in Shared channels and guests in Private channels only respond to polls. They can't create polls or see past results.| -|Collaboration| Make it easier for people to work together in Shared channels. Add task lists that everyone can see. If they are from the host team, they can add and change tasks. If they are from another team, they may have fewer rights. Guests inside the company and people from outside can see tasks, but can't change them.| Whiteboarding apps introduce a feature that lets external users in shared channels or guests in private channels add to the canvas. These users don't erase or edit contributions made by internal members.| -|Notification / Nudges| Refine your app's notification systems to avoid overloading users with irrelevant updates, possibly segmenting alerts by user group or channel type.| Helpdesk app used in a Shared channel, internal IT staff might receive immediate alerts for high-priority tickets or infrastructure issues, whereas external vendors might only receive notifications for tickets assigned to them or for maintenance schedules affecting their services.| - -## Technical Changes for App Compatibility with Shared and Private Channels +## Technical changes for app compatibility with shared and private channels With an enhanced understanding of how users interact in shared and private channels, you can now focus on the technical steps to update your app. Microsoft Teams offers APIs to work with these channels. -### Identify Channels +### Identify channels When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This check helps the app adjust its functionality accordingly. @@ -116,7 +89,7 @@ SupportedChannelTypes is an optional property that enables your app in nonstanda > * If your app supports the team scope, it functions in standard channels, regardless of what this property defines. > * To work well in all channel types, your app should handle the special rules and settings of each one. -### Get Context for Shared Channels +### Get context for shared channels When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. @@ -125,7 +98,7 @@ For more information to enable your tab, see: * [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) -### Managing Channel Members and Permissions in Microsoft Teams Apps +### Managing channel members and permissions in Microsoft Teams apps To ensure your app functions correctly in shared and private channels, you must use channel-specific APIs to gather accurate member information. Usage of channel-specific APIS is important because: @@ -141,9 +114,13 @@ Each channel has its own SharePoint site with its own permissions. Apps must fol Note: Don't store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these dynamically when needed. +> [!NOTE] +> +> * Don't store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these dynamically when needed. + Then, call APIs listed below based on your app requirements: -### Get All Members of a Private or Shared Channel +### Get all members of a private or shared channel If you're using Graph @@ -155,14 +132,14 @@ Pass the channel ID you received above in [getConversationMembers](../../resourc Note: Use the following APIs only if your app needs to create specific permissions or experiences based on the member type in a shared channel. Otherwise, you can skip them. -## Apps and permissions in Shared Channels +## Apps and permissions in shared channels You can collaborate with external members outside of your organization using Shared channels. App permissions in Shared channels follow the host team's app roster and host tenant's app policy. > [!NOTE] > The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a Shared channel. -### Get Shared Channel Membership +### Get shared channel membership You can get direct shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: @@ -185,21 +162,28 @@ Note: This returns both internal and external users added to the Shared channel. ```http GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members ``` -## Retrieve Members of a Shared Channel in Microsoft Teams + +## Retrieve members of a shared channel in Microsoft Teams In Microsoft Teams, when you share a channel with another team, the channel includes that team’s members. The system doesn’t add users directly to the shared channel; instead, it grants access through their team’s connection to the channel. Get each shared team with GET sharedWithTeams API. + +```http GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams + ``` Use GET members of each shared team (Team X) with GET sharedWithTeams API. + +```http GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members + ``` With this information, structure your app to interpret member details and apply appropriate permissions as per your app use-case. For instance, Once your app identifies the channel type (standard, private, or shared) and retrieves member details using Microsoft Graph or Bot APIs, you can ensure that features like editing and task creation are selectively enabled based on user roles (Owners vs members vs External participants) determined through the preceding API responses. -## Classify Members in the Shared channel as In-tenant or Out-tenant +## Classify members in the shared channel as in-tenant or out-tenant You can classify members as in-tenant or out-tenant by comparing `tenantID` of the member or team with `hostTeamTenantID` as follows: @@ -213,7 +197,85 @@ You can classify members as in-tenant or out-tenant by comparing `tenantID` of t -## Handling External Users (B2B Direct connect) in Shared Channels +## Get app notifications for direct and indirect membership changes + +### In graph + +Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. To receive these notifications, you must: + +1. [Install the app](../deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. +1. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. + +To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). + +```http +`/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` +``` + +This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) + +### In Bot SDK + +When a new member is added to a shared channel, the OnMembersAddedAsync method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. + +Member added + +```http +public async Task OnMembersAddedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) +``` + +Similarly, when a member is removed from the channel, the OnMembersRemovedAsync method is called. This allows the bot to handle clean-up tasks or adjust access controls as needed. + +Member removed + +```http +public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) +``` + +These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. + +## Validate user access for membership updates + +### Graph + +When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the **doesUserHaveAccess** API to determine whether the user still has access to the shared channel. + +```http +GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') +``` + +See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http) to learn more about user accesses and relevant permissions. + +## Handle bulk membership changes + +If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. This feature reduces notification volume and improves performance. + +### Use sharedWithTeams subscription for bulk membership changes + +To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new SharedWithTeams subscription resource: + +```http +`/teams/{team-id}/channels/{channel-id}/sharedWithTeams` +``` + +The sharedWithTeams subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the /allMembers API after receiving a 'shared with' or 'unshared from' team notification. + +> [!NOTE] +> To support membership updates in shared channels, apps using resource-specific consent (RSC) must request extended permissions. +> These permissions let the app: +> +> * Access membership data (both direct and indirect members). +> * Receive and respond to membership change notifications. + +### Bot Framework + +Whenevere we share the shared channel with another team we will get a notification on this Bot SDK endpoint API “OnConversationUpdateActivityAsync. + +```http +GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') +``` + +## Handling external users (B2B Direct connect) in shared channels Each Teams channel links to its own SharePoint site with separate permissions. When building apps, make sure to check these limits so you don’t run into access issues or cause data leaks. @@ -233,7 +295,7 @@ GET /teams/{host-team-group-id}/channels/{channel-id}/members Compare tenantID of each member with the hostTenantID property from above to classify member as out-of-tenant if TenantIds don’t match. -## Authenticate External Users to Access your App Content in SharePoint +## Authenticate external users to access your app content in sharepoint Note: This step is only required when requesting the SharePoint token that is your app stores content in SharePoint service of the tenant in which channel is hosted. @@ -243,13 +305,13 @@ Note: This step is only required when requesting the SharePoint token that is yo Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the Shared channel. -## Identify Guest Users (B2B Guests) in Private Channels +## Identify guest users (B2B guests) in private channels You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. For guests, “roles” = “guest” -## Microsoft Entra Native Identity +## Microsoft entra native identity Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group IDs: @@ -258,13 +320,13 @@ Apps must function cross-tenants in installation and usage. The following table |Regular | Team Microsoft Entra group ID | Team Microsoft Entra group ID | |Shared | Empty | Host Team Microsoft Entra group ID | -## Access SharePoint Data in Shared and Private Channels +## Access sharepoint data in shared and private channels If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). -## Declare your App Works in Shared and Private Channels +## Declare your app works in shared and private channels After making all the preceding changes, you need to declare your app’s manifest to declare that your app works in Shared and private channels. @@ -281,7 +343,6 @@ Json ] } - Note: If your app supports team scope, it functions in standard channels, regardless of what values are defined in this property. Note: @@ -302,7 +363,7 @@ Note: GET /teams/{team-id}/channels/{channel-id}/filesFolder - This API call returns the current and correct SharePoint document library location for the specified channel—especially important for shared and private channels, which have their own dedicated SharePoint sites. -## Apps in Federated Group Chats with External Users +## Apps in Federated group chats with external users > [!NOTE] > @@ -325,6 +386,68 @@ If you're developing an app for use in federated group chats with external users |-------------|-------------|------| |Teams Conversation Bot|This sample app displays the names of the members in a federated group chat with external users.|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-feed-members/nodejs/)| +## Frequently asked questions + +
+Why isn’t the app visible when trying to add it to a channel? +If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest may be missing required support, such as "supportsChannelFeatures": "tier1", which enables compatibility with channel features. Additionally, the installer may not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps cannot be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. + +
+  +
+
+Why am I getting a 403 error stating “app not enabled in this channel” when calling channel APIs? + +A 403 error stating “app not enabled in this channel” typically occurs when the app is installed at the team level but hasn’t been added to the specific channel. To resolve this, first confirm that the app has been explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel. + +
+  +
+
+Why does the channel roster appear incomplete, showing only owners or missing users? + +If the channel roster appears incomplete showing only owners or missing users, it may be due to using the team members API instead of the correct channel-specific API. To resolve this, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely hasn’t been added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. + +
+  +
+
+Why does file access fail for some users even though they are part of the channel? + +This can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. It may also be due to the type of link being blocked by your organization’s sharing policies, or because external users don’t have the right permissions. To fix this, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use “people with existing access” links or the /invite API to give access to specific users or groups. + +
+  +
+
+Why are external users experiencing authentication issues in tabs or task modules? + +Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this, check whether the user is external by comparing context.user.tenant.id with the host or owner tenant ID. If they are different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. + +
+  +
+
+How do I know my app was added to a channel? + +This issue may occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there is no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they have been added. If this event is not received, and a 403 error is returned during operations, the app should handle the error and prompt the user to add the bot to the channel. + +
+  +
+
+Why is my app failing to create message change notifications in shared or private channels? + +Message change notifications may fail in shared or private channels because subscriptions to /channels/{id}/messages are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To fis this, use on-demand message reads after the app has been successfully added to the channel. + +
+  +
+
+Why do file links still fail for external users even after the app has been added to the channel? + +This can happen if the type of link being used is not allowed by the tenant’s sharing policy, or if the user hasn’t been granted access to the specific item, despite being a member of the channel. Another common cause is that the app may have generated links pointing to the team drive instead of the channel’s dedicated drive. To resolve this, reissue the links using the “people with existing access” option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. + ## See also * [Build tabs for Teams](../../tabs/what-are-tabs.md) From 9fabc910d7302ddac213476e061265ba92ef9acc Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 13:23:10 +0530 Subject: [PATCH 016/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 1b46ded4ad7..baa3d0dc951 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -8,7 +8,7 @@ ms.topic: conceptual ms.date: 04/09/2025 --- -# Microsoft Teams connects for shared and private Channels +# Microsoft Teams connects for shared and private channels Microsoft Teams apps must support shared and private channels, which introduce new collaboration scenarios across teams and organizations. Shared channels in Microsoft Teams Connect can be created and shared with members of other teams within the same organization or with teams from external organizations. From 316d589850c176e9d25a4a06838e58325fb99047 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 14:36:45 +0530 Subject: [PATCH 017/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index baa3d0dc951..dc6c27d72fe 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -1,5 +1,5 @@ --- -title: Teams Connect Shared Channels +title: Teams Connects Shared Channels author: surbhigupta description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. ms.author: surbhigupta @@ -43,7 +43,7 @@ Private channels in Microsoft Teams are special spaces for focused collaboration |External participants (Direct Connect) can participate in channel |No | Yes | No | |Each channel has a dedicated SharePoint site |No | Yes | Yes | -### Teams channel models – capabilities comparison +### Teams channels – capabilities comparison | **Category** | **Capability** | **Standard channel** | **Private channel** | **Shared channel** | |--------------|----------------------------------------------------------------------------------|----------------------|---------------------|---------------------| @@ -73,7 +73,7 @@ When your app runs inside Microsoft Teams, it needs to know what kind of channel |Tabs| Bots| |--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == "Shared,"
For private channel channel.membershipType =="Private,"|Use turnContext.activity.channelData.channel.type type property from any of the bot activity handlers event generated for shared channel activities, to get context of where bot was invoked or bot activity originated from.
For Shared Channel turnContext.activity.channelData.channel.type == “shared”
For Private ChannelturnContext.activity.channelData.channel.type == “private” You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) +|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == Shared,
For private channel channel.membershipType == Private,|To determine where a bot activity originated, especially in shared channel scenarios, use the channel.type property found in turnContext.activity.channelData. This property is available in any bot activity handler and helps identify the channel type, allowing your app to respond appropriately based on the context.
For Shared Channel turnContext.activity.channelData.channel.type == shared
For Private ChannelturnContext.activity.channelData.channel.type == private You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) SupportedChannelTypes is an optional property that enables your app in nonstandard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). @@ -106,29 +106,27 @@ Team membership APIs aren't equal to shared or private Channel membership Shared Each channel has its own SharePoint site with its own permissions. Apps must follow these rules to prevent data leaks or access problems. -### Get Host Team Group ID & Channel ID +### Get host team group ID & channel ID | Tabs | Bots | |--------------------------------------|----------------------------------------| |You can use below mentioned parameters received in getContext call to get host team ID and channel ID required for any Graph calls
1. JSv1: hostTeamGroupID and channelId
2. JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
Get host team group ID from: turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
Get channel ID from: turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. -Note: Don't store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these dynamically when needed. - > [!NOTE] > -> * Don't store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these dynamically when needed. +> * Don't store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these parameters dynamically when needed. -Then, call APIs listed below based on your app requirements: +Then, call following APIs listed based on your app requirements: ### Get all members of a private or shared channel If you're using Graph -Pass the teamID and channelID fetched above in GET teams/{team-ID}/channels/{channel-ID}/allMembers to get all members of a Shared or a private channel. +Pass the teamID and channelID fetched in the preceding section in GET teams/{team-ID}/channels/{channel-ID}/allMembers to get all members of a Shared or a private channel. If you are using Bots SDK -Pass the channel ID you received above in [getConversationMembers](../../resources/team-chat-member-api-changes.md) API to get all members of a Shared or private channel. +Pass the channel ID you received in [getConversationMembers](../../resources/team-chat-member-api-changes.md) API to get all members of a Shared or private channel. Note: Use the following APIs only if your app needs to create specific permissions or experiences based on the member type in a shared channel. Otherwise, you can skip them. @@ -181,8 +179,6 @@ GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/me With this information, structure your app to interpret member details and apply appropriate permissions as per your app use-case. -For instance, Once your app identifies the channel type (standard, private, or shared) and retrieves member details using Microsoft Graph or Bot APIs, you can ensure that features like editing and task creation are selectively enabled based on user roles (Owners vs members vs External participants) determined through the preceding API responses. - ## Classify members in the shared channel as in-tenant or out-tenant You can classify members as in-tenant or out-tenant by comparing `tenantID` of the member or team with `hostTeamTenantID` as follows: @@ -224,7 +220,7 @@ Member added public async Task OnMembersAddedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` -Similarly, when a member is removed from the channel, the OnMembersRemovedAsync method is called. This allows the bot to handle clean-up tasks or adjust access controls as needed. +Similarly, when a member is removed from the channel, the OnMembersRemovedAsync method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. Member removed @@ -258,7 +254,7 @@ To reduce notification overload during membership updates, such as when a shared `/teams/{team-id}/channels/{channel-id}/sharedWithTeams` ``` -The sharedWithTeams subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the /allMembers API after receiving a 'shared with' or 'unshared from' team notification. +The sharedWithTeams subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the /allMembers API after receiving a "shared with" or "unshared from" team notification. > [!NOTE] > To support membership updates in shared channels, apps using resource-specific consent (RSC) must request extended permissions. @@ -269,7 +265,7 @@ The sharedWithTeams subscription sends a single notification when a channel is s ### Bot Framework -Whenevere we share the shared channel with another team we will get a notification on this Bot SDK endpoint API “OnConversationUpdateActivityAsync. +Whenever a shared channel is shared with another team, that team receives a notification through the Bot SDK endpoint API Bot SDK endpoint API "OnConversationUpdateActivityAsync." ```http GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') @@ -277,12 +273,12 @@ GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',t ## Handling external users (B2B Direct connect) in shared channels -Each Teams channel links to its own SharePoint site with separate permissions. When building apps, make sure to check these limits so you don’t run into access issues or cause data leaks. +Each Microsoft Teams channel is linked to its own SharePoint site, which has separate permission. When building apps, make sure to check these limits so you don’t run into access issues or cause data leaks. -For this, perform the following steps: +Perform the following steps, for this identification process: Step 1: Identify External Users -To do this, get tenant ID of the channel in which your app is operating inside. +Get tenant ID of the channel in which your app is operating inside. |Tabs|Bots| |--------------------------------------|----------------------------------------| @@ -293,11 +289,11 @@ Then, identify external users from direct members list you received for Shared c Get members of a shared or a private channel. GET /teams/{host-team-group-id}/channels/{channel-id}/members -Compare tenantID of each member with the hostTenantID property from above to classify member as out-of-tenant if TenantIds don’t match. +To classify member as out-of-tenant if TenantIds don’t match, compare tenantID of each member with the hostTenantID property. ## Authenticate external users to access your app content in sharepoint -Note: This step is only required when requesting the SharePoint token that is your app stores content in SharePoint service of the tenant in which channel is hosted. +You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. |Tabs|Bots| |--------------------------------------|----------------------------------------| @@ -311,9 +307,9 @@ You can identify if a member of private channel is guest user, invited to your t For guests, “roles” = “guest” -## Microsoft entra native identity +## Microsoft Entra native identity -Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group IDs: +Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group ids: |Channel type| groupId | hostTeamGroupId | |----------|---------|-----------------| @@ -330,9 +326,9 @@ Use the Graph API to access the document library of the SharePoint Online (SPO) After making all the preceding changes, you need to declare your app’s manifest to declare that your app works in Shared and private channels. -This declaration will make your app visible to users in Shared and private channels. Else, your app won't be discoverable to users in those channels. This is a mandatory update. +This declaration makes your app visible to users in Shared and private channels. Else, your app is not discoverable to users in those channels. This configuration update is a mandatory requirement. -supportsChannelFeatures is an optional property that enables your app in nonstandard channels along with standard channels. +supportsChannelFeatures are an optional property that enables your app in nonstandard channels along with standard channels. Put supportsChannelFeatures as “level2” For more information, see . @@ -350,9 +346,9 @@ Note: - When you declare support for "Tier1" in your app manifest. - You're assuming the channel's roster matches the parent team. - To get the full list of users with access—including direct and transitive members—use the API: GET/teams/{team-id}/channels/{channel-id}/allMembers - - This is the only API that returns everyone who can access the channel. Check the official documentation for more details. + - This API is the only API that returns everyone who can access the channel. Check the official documentation for more details. -- Don't assume the type of users (e.g., guest, external, internal) in a channel’s roster. +- Don't assume the type of users (for example, guest, external, internal) in a channel’s roster. a. When using the GET/teams/{team-id}/channels/{channel-id}/allMembers API: - Check the "roles" property to identify if the user is a guest. - Check the "tenantId" property to determine if the user is:
*From the same tenant (intra-tenant), or
*From a different tenant (cross-tenant). @@ -390,15 +386,15 @@ If you're developing an app for use in federated group chats with external users
Why isn’t the app visible when trying to add it to a channel? -If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest may be missing required support, such as "supportsChannelFeatures": "tier1", which enables compatibility with channel features. Additionally, the installer may not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps cannot be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as "supportsChannelFeatures": tier1, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps cannot be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
 
-Why am I getting a 403 error stating “app not enabled in this channel” when calling channel APIs? +Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -A 403 error stating “app not enabled in this channel” typically occurs when the app is installed at the team level but hasn’t been added to the specific channel. To resolve this, first confirm that the app has been explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel. +A 403 error stating "app not enabled in this channel" typically occurs when the app is installed at the team level but is not added to the specific channel. To fix this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel.
  @@ -406,7 +402,7 @@ A 403 error stating “app not enabled in this channel” typically occurs when
Why does the channel roster appear incomplete, showing only owners or missing users? -If the channel roster appears incomplete showing only owners or missing users, it may be due to using the team members API instead of the correct channel-specific API. To resolve this, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely hasn’t been added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely hasn’t been added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
  @@ -414,7 +410,7 @@ If the channel roster appears incomplete showing only owners or missing users, i
Why does file access fail for some users even though they are part of the channel? -This can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. It may also be due to the type of link being blocked by your organization’s sharing policies, or because external users don’t have the right permissions. To fix this, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use “people with existing access” links or the /invite API to give access to specific users or groups. +This can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. It might also be due to the type of link being blocked by your organization’s sharing policies, or because external users don’t have the right permissions. To fix this, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the /invite API to give access to specific users or groups.
  @@ -430,7 +426,7 @@ Authentication issues in tabs or task modules for external users often occur whe
How do I know my app was added to a channel? -This issue may occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there is no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they have been added. If this event is not received, and a 403 error is returned during operations, the app should handle the error and prompt the user to add the bot to the channel. +This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there is no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they have been added. If this event is not received, and a 403 error is returned during operations, the app should handle the error and prompt the user to add the bot to the channel.
  @@ -438,7 +434,7 @@ This issue may occur if the app is expecting a centralized list of installed app
Why is my app failing to create message change notifications in shared or private channels? -Message change notifications may fail in shared or private channels because subscriptions to /channels/{id}/messages are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To fis this, use on-demand message reads after the app has been successfully added to the channel. +Message change notifications might fail in shared or private channels because subscriptions to /channels/{id}/messages are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To fix this, use on-demand message reads after the app has been successfully added to the channel.
  @@ -446,7 +442,7 @@ Message change notifications may fail in shared or private channels because subs
Why do file links still fail for external users even after the app has been added to the channel? -This can happen if the type of link being used is not allowed by the tenant’s sharing policy, or if the user hasn’t been granted access to the specific item, despite being a member of the channel. Another common cause is that the app may have generated links pointing to the team drive instead of the channel’s dedicated drive. To resolve this, reissue the links using the “people with existing access” option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This can happen if the type of link being used is not allowed by the tenant’s sharing policy, or if the user hasn’t been granted access to the specific item, despite being a member of the channel. Another common cause is that the app might have generated links pointing to the team drive instead of the channel’s dedicated drive. To resolve this, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. ## See also From 30207270da8f78bc747f79aa3b14170688e35557 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 20:14:55 +0530 Subject: [PATCH 018/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 179 ++---------------- 1 file changed, 16 insertions(+), 163 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 8394bcf0772..bbbfed66fae 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -8,9 +8,19 @@ ms.topic: conceptual ms.date: 04/09/2025 --- -# Microsoft Teams connects for shared and private channels +# MMicrosoft Teams connect shared and private channels -Microsoft Teams apps must support shared and private channels, which introduce new collaboration scenarios across teams and organizations. Shared channels in Microsoft Teams Connect can be created and shared with members of other teams within the same organization or with teams from external organizations. +Microsoft Teams Connect shared channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: + +* Members of another team within the same organization. +* Individuals within the same organization. +* Individuals and other teams of other organizations. + +Microsoft Teams private channels allow a subset of team members to collaborate in a more focused and secure space, separate from the main team conversation. You can create and use a private channel with: + +* Selected members of the same team. +* Internal stakeholders who require restricted access to sensitive content. +* Team members working on confidential projects or specialized tasks > [!NOTE] > @@ -19,31 +29,9 @@ Microsoft Teams apps must support shared and private channels, which introduce n Teams Connects Shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. - ![Diagram shows Team B from organization A and Team C from organization B collaborating in a Shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) - -## Understanding shared and private channels in Microsoft Teams - -### Shared channel - -Shared channels in Microsoft Teams let you collaborate with people who aren’t part of your team. Only users added as owners or members can access the shared channel. You can’t add regular guest accounts (via Microsoft Entra) to shared channels. However, you can still invite people from outside your organization through Microsoft Entra B2B direct connect, which enables secure external collaboration with no need to add them as guests. - -### Private channel - -Private channels in Microsoft Teams are special spaces for focused collaboration within a team. The system allows only people added as owners or members of the private channel to access it. You can include guests (users with Microsoft Entra guest accounts) in a private channel, but only if they're already part of the host team. - -### Feature differences between shared and private channels +![Diagram shows Team B from organization A and Team C from organization B collaborating in a Shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) -| Features | Standard Channel | Shared Channel | Private Channel | -|---------------------|------------------------|-----------------------------------------------------|--------------------------------------------------| -| People can be added to channel without adding to team | No | Yes | No | -|Channel membership can be limited to a subset of the team | No | Yes | Yes | -|Channel can be shared directly with other teams | No | Yes | No | -|Channel can be shared directly with its parent team | NA | Yes | No | -|Guests can participate in the channel |Yes | No | Yes | -|External participants (Direct Connect) can participate in channel |No | Yes | No | -|Each channel has a dedicated SharePoint site |No | Yes | Yes | - -### Teams channels – capabilities comparison +## Teams channels – capabilities comparison | **Category** | **Capability** | **Standard channel** | **Private channel** | **Shared channel** | |--------------|----------------------------------------------------------------------------------|----------------------|---------------------|---------------------| @@ -59,37 +47,6 @@ Private channels in Microsoft Teams are special spaces for focused collaboration | | App installed to host team automatically available in channel | Yes | No | No | | | App must be added to each channel | No | Yes | Yes | -## A strategic approach to change - -Microsoft Teams is developing with shared and private channels, and that means apps need to develop too. To keep your app working smoothly across all channel types: standard, shared, and private you need a logical strategy. - -## Technical changes for app compatibility with shared and private channels - -With an enhanced understanding of how users interact in shared and private channels, you can now focus on the technical steps to update your app. Microsoft Teams offers APIs to work with these channels. - -### Identify channels - -When your app runs inside Microsoft Teams, it needs to know what kind of channel it’s operating in. This check helps the app adjust its functionality accordingly. - -|Tabs| Bots| -|--------------------------------------|----------------------------------------| -|When content UX is loaded in a Shared channel, use data received from [getContext](../../tabs/how-to/access-teams-context.md) call
For Shared channel, channel.membershipType == Shared,
For private channel channel.membershipType == Private,|To determine where a bot activity originated, especially in shared channel scenarios, use the channel.type property found in turnContext.activity.channelData. This property is available in any bot activity handler and helps identify the channel type, allowing your app to respond appropriately based on the context.
For Shared Channel turnContext.activity.channelData.channel.type == shared
For Private ChannelturnContext.activity.channelData.channel.type == private You can learn more from [(Bot activity handlers - Teams Microsoft Learn)](../../bots/bot-concepts.md) - -SupportedChannelTypes is an optional property that enables your app in nonstandard channels. If your app supports the team scope and you define the property, Teams enables your app in each channel type accordingly. The apps support private and shared channels. For more information, see [supportedChannelTypes](../../resources/schema/manifest-schema.md#supportedchanneltypes). - -```JSON - "supportedChannelTypes": [ - "sharedChannels", - "privateChannels" - ] -``` - -> [!NOTE] -> -> * If your app supports the team scope, it functions in standard channels, regardless of what values are defined in this property. -> * Your app might need to account for the unique properties of each of these channel types in order to function properly. -> * Only **tabs** are currently supported in **private** and **shared** channels in Microsoft Teams. - ### Get context for shared channels When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. @@ -107,30 +64,6 @@ Team membership APIs aren't equal to shared or private Channel membership Shared Each channel has its own SharePoint site with its own permissions. Apps must follow these rules to prevent data leaks or access problems. -### Get host team group ID & channel ID - -| Tabs | Bots | -|--------------------------------------|----------------------------------------| -|You can use below mentioned parameters received in getContext call to get host team ID and channel ID required for any Graph calls
1. JSv1: hostTeamGroupID and channelId
2. JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
Get host team group ID from: turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
Get channel ID from: turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. - -> [!NOTE] -> -> * Don't store these parameters, because the channel owner can change the host team of a shared channel, which updates the values. Recommended to always fetch these parameters dynamically when needed. - -Then, call following APIs listed based on your app requirements: - -### Get all members of a private or shared channel - -If you're using Graph - -Pass the teamID and channelID fetched in the preceding section in GET teams/{team-ID}/channels/{channel-ID}/allMembers to get all members of a Shared or a private channel. - -If you are using Bots SDK - -Pass the channel ID you received in [getConversationMembers](../../resources/team-chat-member-api-changes.md) API to get all members of a Shared or private channel. - -Note: Use the following APIs only if your app needs to create specific permissions or experiences based on the member type in a shared channel. Otherwise, you can skip them. - ## Apps and permissions in shared channels You can collaborate with external members outside of your organization using Shared channels. App permissions in Shared channels follow the host team's app roster and host tenant's app policy. @@ -162,24 +95,6 @@ Note: This returns both internal and external users added to the Shared channel. GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members ``` -## Retrieve members of a shared channel in Microsoft Teams - -In Microsoft Teams, when you share a channel with another team, the channel includes that team’s members. The system doesn’t add users directly to the shared channel; instead, it grants access through their team’s connection to the channel. - -Get each shared team with GET sharedWithTeams API. - -```http -GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams - ``` - -Use GET members of each shared team (Team X) with GET sharedWithTeams API. - -```http -GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members - ``` - -With this information, structure your app to interpret member details and apply appropriate permissions as per your app use-case. - ## Classify members in the shared channel as in-tenant or out-tenant You can classify members as in-tenant or out-tenant by comparing `tenantID` of the member or team with `hostTeamTenantID` as follows: @@ -233,8 +148,6 @@ These Bot SDK endpoints are essential for monitoring membership changes and main ## Validate user access for membership updates -### Graph - When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the **doesUserHaveAccess** API to determine whether the user still has access to the shared channel. ```http @@ -268,30 +181,6 @@ The sharedWithTeams subscription sends a single notification when a channel is s Whenever a shared channel is shared with another team, that team receives a notification through the Bot SDK endpoint API Bot SDK endpoint API "OnConversationUpdateActivityAsync." -```http -GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') -``` - -## Handling external users (B2B Direct connect) in shared channels - -Each Microsoft Teams channel is linked to its own SharePoint site, which has separate permission. When building apps, make sure to check these limits so you don’t run into access issues or cause data leaks. - -Perform the following steps, for this identification process: - -Step 1: Identify External Users -Get tenant ID of the channel in which your app is operating inside. - -|Tabs|Bots| -|--------------------------------------|----------------------------------------| -|You can use below mentioned parameters received in [getContext](../../tabs/how-to/access-teams-context.md) call to get host team ID and channel ID required for any Graph calls
•JSv1: hostTeamGroupID and channelId
•JSv2: channel.ownerGroupId and channel.id | For any event payload or action payload received for a bot,
•Get host team group ID from turnContext.Activity.TeamsGetTeamInfo().AadGroupId received in event payloads.
•Get channel ID from turnContext.Activity.TeamsGetChannelId() or turnContext.Activity.ChannelId received in event payloads. - -Then, identify external users from direct members list you received for Shared channel. - -Get members of a shared or a private channel. -GET /teams/{host-team-group-id}/channels/{channel-id}/members - -To classify member as out-of-tenant if TenantIds don’t match, compare tenantID of each member with the hostTenantID property. - ## Authenticate external users to access your app content in sharepoint You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. @@ -314,7 +203,7 @@ Apps must function cross-tenants in installation and usage. The following table |Channel type| groupId | hostTeamGroupId | |----------|---------|-----------------| -|Regular | Team Microsoft Entra group ID | Team Microsoft Entra group ID | +|Standard | Team Microsoft Entra group ID | Team Microsoft Entra group ID | |Shared | Empty | Host Team Microsoft Entra group ID | ## Access sharepoint data in shared and private channels @@ -323,43 +212,6 @@ If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). -## Declare your app works in shared and private channels - -After making all the preceding changes, you need to declare your app’s manifest to declare that your app works in Shared and private channels. - -This declaration makes your app visible to users in Shared and private channels. Else, your app is not discoverable to users in those channels. This configuration update is a mandatory requirement. - -supportsChannelFeatures are an optional property that enables your app in nonstandard channels along with standard channels. - -Put supportsChannelFeatures as “level2” For more information, see . - -Json -{ - "supportsChannelFeatures": [ - "Tier1" - ] -} - -Note: If your app supports team scope, it functions in standard channels, regardless of what values are defined in this property. - -Note: - -- When you declare support for "Tier1" in your app manifest. - - You're assuming the channel's roster matches the parent team. - - To get the full list of users with access—including direct and transitive members—use the API: GET/teams/{team-id}/channels/{channel-id}/allMembers - - This API is the only API that returns everyone who can access the channel. Check the official documentation for more details. - -- Don't assume the type of users (for example, guest, external, internal) in a channel’s roster. - a. When using the GET/teams/{team-id}/channels/{channel-id}/allMembers API: - - Check the "roles" property to identify if the user is a guest. - - Check the "tenantId" property to determine if the user is:
*From the same tenant (intra-tenant), or
*From a different tenant (cross-tenant). - - This API returns both direct and transitive members—ensuring a complete view of channel access. - -- Do not assume that a channel’s storage location is the same as its parent team’s SharePoint site. - - Instead, always use the Microsoft Graph API endpoint: -GET /teams/{team-id}/channels/{channel-id}/filesFolder - - This API call returns the current and correct SharePoint document library location for the specified channel—especially important for shared and private channels, which have their own dedicated SharePoint sites. - ## Apps in Federated group chats with external users > [!NOTE] @@ -387,6 +239,7 @@ If you're developing an app for use in federated group chats with external users
Why isn’t the app visible when trying to add it to a channel? + If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as "supportsChannelFeatures": tier1, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps cannot be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
From 82a157730340ed1521eddf336d59b4ad87ed3459 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 22:58:10 +0530 Subject: [PATCH 019/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index bbbfed66fae..bb875356c05 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -8,7 +8,7 @@ ms.topic: conceptual ms.date: 04/09/2025 --- -# MMicrosoft Teams connect shared and private channels +# Microsoft Teams connect shared and private channels Microsoft Teams Connect shared channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: @@ -16,11 +16,11 @@ Microsoft Teams Connect shared channels allow members of a channel to collaborat * Individuals within the same organization. * Individuals and other teams of other organizations. -Microsoft Teams private channels allow a subset of team members to collaborate in a more focused and secure space, separate from the main team conversation. You can create and use a private channel with: +Microsoft Teams private channels allow a subset of team members to collaborate in a more focused and secure space, separate from general team discussion. You can create and use a private channel with: * Selected members of the same team. * Internal stakeholders who require restricted access to sensitive content. -* Team members working on confidential projects or specialized tasks +* Team members working on confidential projects. > [!NOTE] > @@ -111,12 +111,12 @@ You can classify members as in-tenant or out-tenant by comparing `tenantID` of t ## Get app notifications for direct and indirect membership changes -### In graph +### [Graph](#tab/graph) Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. To receive these notifications, you must: 1. [Install the app](../deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. -1. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. +2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). @@ -126,19 +126,15 @@ To receive both direct and indirect member update notifications, you must includ This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) -### In Bot SDK +### [Bot SDK](#tab/bot sdk) -When a new member is added to a shared channel, the OnMembersAddedAsync method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. - -Member added +When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. ```http public async Task OnMembersAddedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` -Similarly, when a member is removed from the channel, the OnMembersRemovedAsync method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. - -Member removed +Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsync``` method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. ```http public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) @@ -248,7 +244,7 @@ If an app isn’t visible when trying to add it to a channel, there are a few li
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -A 403 error stating "app not enabled in this channel" typically occurs when the app is installed at the team level but is not added to the specific channel. To fix this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel. +A 403 error stating "app not enabled in this channel" typically occurs when the app is installed at the team level but is not added to the specific channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel.
  @@ -256,7 +252,7 @@ A 403 error stating "app not enabled in this channel" typically occurs when the
Why does the channel roster appear incomplete, showing only owners or missing users? -If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely hasn’t been added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely is not added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
  @@ -264,7 +260,7 @@ If the channel roster appears incomplete showing only owners or missing users, i
Why does file access fail for some users even though they are part of the channel? -This can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. It might also be due to the type of link being blocked by your organization’s sharing policies, or because external users don’t have the right permissions. To fix this, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the /invite API to give access to specific users or groups. +This failure can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the /invite API to give access to specific users or groups.
  @@ -272,7 +268,7 @@ This can happen if the app is using the team’s main SharePoint site instead of
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this, check whether the user is external by comparing context.user.tenant.id with the host or owner tenant ID. If they are different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. +Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing context.user.tenant.id with the host or owner tenant ID. If they are different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken.
  @@ -280,7 +276,7 @@ Authentication issues in tabs or task modules for external users often occur whe
How do I know my app was added to a channel? -This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there is no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they have been added. If this event is not received, and a 403 error is returned during operations, the app should handle the error and prompt the user to add the bot to the channel. +This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there is no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they are added. If the app doesn’t receive the event and gets a 403 error, it prompts the user to add the bot to the channel and handles the error.
  @@ -288,15 +284,15 @@ This issue might occur if the app is expecting a centralized list of installed a
Why is my app failing to create message change notifications in shared or private channels? -Message change notifications might fail in shared or private channels because subscriptions to /channels/{id}/messages are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To fix this, use on-demand message reads after the app has been successfully added to the channel. +Message change notifications might fail in shared or private channels because subscriptions to /channels/{id}/messages are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel.
 
-Why do file links still fail for external users even after the app has been added to the channel? +Why do file links still fail for external users even after the app is added to the channel? -This can happen if the type of link being used is not allowed by the tenant’s sharing policy, or if the user hasn’t been granted access to the specific item, despite being a member of the channel. Another common cause is that the app might have generated links pointing to the team drive instead of the channel’s dedicated drive. To resolve this, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This can happen if the type of link being used is not allowed by the tenant’s sharing policy, or if the user hasn’t been granted access to the specific item, despite being a member of the channel. Another common cause is that the app might have generated links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. ## See also From 41aed14cf43ad19e8f723d80e7d8ee5787cac1ce Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 23:13:00 +0530 Subject: [PATCH 020/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index bb875356c05..879a661625c 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -120,26 +120,27 @@ Apps installed in shared channels receive notifications when users are added to To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). -```http +```C# `/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` ``` This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) -### [Bot SDK](#tab/bot sdk) +### [Bot Framework](#tab/bot-framework) When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. -```http +```C# public async Task OnMembersAddedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsync``` method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. -```http +```C# public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` +--- These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. ## Validate user access for membership updates @@ -158,7 +159,7 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes -To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new SharedWithTeams subscription resource: +To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: ```http `/teams/{team-id}/channels/{channel-id}/sharedWithTeams` From a586fe7b8b37fc2fc03e83684929a92319128f2f Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 23:31:34 +0530 Subject: [PATCH 021/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 879a661625c..6eb8b320023 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -147,7 +147,7 @@ These Bot SDK endpoints are essential for monitoring membership changes and main When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the **doesUserHaveAccess** API to determine whether the user still has access to the shared channel. -```http +```C# GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') ``` @@ -159,9 +159,11 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes +### [Graph](#tab1/graph) + To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: -```http +```C# `/teams/{team-id}/channels/{channel-id}/sharedWithTeams` ``` @@ -174,9 +176,11 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### Bot Framework +### [Bot Framework](#tab1/bot-framework) -Whenever a shared channel is shared with another team, that team receives a notification through the Bot SDK endpoint API Bot SDK endpoint API "OnConversationUpdateActivityAsync." +When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. + +--- ## Authenticate external users to access your app content in sharepoint From d277b764b179a75aa9490cd323a114c8a2e20f7f Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 23:37:24 +0530 Subject: [PATCH 022/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 6eb8b320023..43a2f7ef28c 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -186,9 +186,15 @@ When a shared channel is added to another team, the Bot Framework may receive a You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. - |Tabs|Bots| -|--------------------------------------|----------------------------------------| -|Save host tenant ID of Shared channel where tab is configured. You can get host tenant ID from channel.ownerTenantId for JSv2 or hostTenantId for JSv1 received under getContext call. | For any event payload or action payload received for a bot, use Get hostTenant ID, from turnContext.activity.conversation.tenantId| +### [Tabs](#tab/tabs) + +Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ```channel.ownerTenantId``` for JSv2 or host tenant ID for JSv1 received under ```getContext``` call. + +### [Bots](#tab/bots) + +For any event payload or action payload received for a bot, use Get hostTenant ID, from ```turnContext.activity.conversation.tenantId```. + +--- Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the Shared channel. From ca45da5fa71b5241ea68805f73592772032e142f Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 9 Sep 2025 23:51:56 +0530 Subject: [PATCH 023/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 43a2f7ef28c..7a470954a82 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -140,8 +140,8 @@ Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsy public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` ---- These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. +--- ## Validate user access for membership updates @@ -159,7 +159,7 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes -### [Graph](#tab1/graph) +### [Graph](#tab/graph) To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: @@ -176,7 +176,7 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### [Bot Framework](#tab1/bot-framework) +### [Bot Framework](#tab/bot-framework) When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. From 89d812ccf19381c6f55ce5c8fdbefc729f99d804 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 00:00:56 +0530 Subject: [PATCH 024/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 7a470954a82..26e65717a60 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -138,9 +138,7 @@ Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsy ```C# public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) -``` - -These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. +```These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. --- ## Validate user access for membership updates @@ -159,7 +157,7 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes -### [Graph](#tab/graph) +### [Tab](#tab/tab) To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: @@ -176,7 +174,7 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### [Bot Framework](#tab/bot-framework) +### [Bot](#tab/bot) When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. From 250edd5916fc7581faf4980868fa92029df3511d Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 00:05:34 +0530 Subject: [PATCH 025/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 26e65717a60..a1a2d36c920 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -138,7 +138,10 @@ Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsy ```C# public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) -```These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. +``` + +These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. + --- ## Validate user access for membership updates @@ -157,7 +160,7 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes -### [Tab](#tab/tab) +### [Graph](#tab/graph) To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: @@ -174,7 +177,7 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### [Bot](#tab/bot) +### [Bot Framework](#tab/bot-framework) When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. From e77f97d2de5179c4058b1cd334d1ecc5f7233f11 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 00:09:50 +0530 Subject: [PATCH 026/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index a1a2d36c920..c61e6e9f9e3 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -141,7 +141,6 @@ public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnS ``` These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. - --- ## Validate user access for membership updates @@ -180,7 +179,6 @@ The sharedWithTeams subscription sends a single notification when a channel is s ### [Bot Framework](#tab/bot-framework) When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. - --- ## Authenticate external users to access your app content in sharepoint From e6e8f7549b67178d7fda73d8efa3842059c70649 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 00:15:27 +0530 Subject: [PATCH 027/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index c61e6e9f9e3..a55b3b42ae2 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -140,8 +140,8 @@ Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsy public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` -These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. --- +These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. ## Validate user access for membership updates @@ -159,7 +159,7 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes -### [Graph](#tab/graph) +### [Graph](#tab1/graph) To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: @@ -176,9 +176,10 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### [Bot Framework](#tab/bot-framework) +### [Bot Framework](#tab1/bot-framework) When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. + --- ## Authenticate external users to access your app content in sharepoint @@ -189,6 +190,7 @@ You need to complete this step when your app stores content in the SharePoint si Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ```channel.ownerTenantId``` for JSv2 or host tenant ID for JSv1 received under ```getContext``` call. + ### [Bots](#tab/bots) For any event payload or action payload received for a bot, use Get hostTenant ID, from ```turnContext.activity.conversation.tenantId```. From d406131092ff2d0f7857ced27d7cad434ea284e7 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 00:22:18 +0530 Subject: [PATCH 028/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index a55b3b42ae2..10d79584b37 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -145,7 +145,7 @@ These Bot SDK endpoints are essential for monitoring membership changes and main ## Validate user access for membership updates -When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the **doesUserHaveAccess** API to determine whether the user still has access to the shared channel. +When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the ```doesUserHaveAccess``` API to determine whether the user still has access to the shared channel. ```C# GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') @@ -190,7 +190,6 @@ You need to complete this step when your app stores content in the SharePoint si Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ```channel.ownerTenantId``` for JSv2 or host tenant ID for JSv1 received under ```getContext``` call. - ### [Bots](#tab/bots) For any event payload or action payload received for a bot, use Get hostTenant ID, from ```turnContext.activity.conversation.tenantId```. From a3c1d2972c46a556d212f1a4eecca3e52d07e443 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 00:24:14 +0530 Subject: [PATCH 029/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 10d79584b37..fa823e314c0 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -159,7 +159,7 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes -### [Graph](#tab1/graph) +### [Graph](#tab/graph) To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: From d45489f1e91dfd4e955fa4245f1252235cf12c65 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 07:49:43 +0530 Subject: [PATCH 030/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index fa823e314c0..5b5d632a250 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -120,7 +120,7 @@ Apps installed in shared channels receive notifications when users are added to To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). -```C# +```csharp `/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` ``` @@ -130,24 +130,25 @@ This subscription enables apps to monitor membership changes in shared channels When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. -```C# +```csharp public async Task OnMembersAddedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsync``` method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. -```C# +```csharp public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) ``` +These Bot Framework endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. + --- -These Bot SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. ## Validate user access for membership updates When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the ```doesUserHaveAccess``` API to determine whether the user still has access to the shared channel. -```C# +```csharp GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') ``` @@ -159,11 +160,11 @@ If there are bulk membership changes, Teams curbs individual membership update n ### Use sharedWithTeams subscription for bulk membership changes -### [Graph](#tab/graph) +### [Graph](#tab/graph-bulk) To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: -```C# +```csharp `/teams/{team-id}/channels/{channel-id}/sharedWithTeams` ``` @@ -176,7 +177,7 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### [Bot Framework](#tab1/bot-framework) +### [Bot Framework](#tab/bot-framework-bulk) When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. From 8425235487ef6537c6ce5f2e4700cd17b7b93f32 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 08:00:17 +0530 Subject: [PATCH 031/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 5b5d632a250..08039569001 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -177,7 +177,7 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### [Bot Framework](#tab/bot-framework-bulk) +### [Bot Framework](#tab/botframework-bulk) When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. From 7ecf5b26bddc4bd863597d50bbab026af17d73ee Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 08:08:57 +0530 Subject: [PATCH 032/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 08039569001..2aed8d1e50b 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -56,14 +56,6 @@ For more information to enable your tab, see: * [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) -### Managing channel members and permissions in Microsoft Teams apps - -To ensure your app functions correctly in shared and private channels, you must use channel-specific APIs to gather accurate member information. Usage of channel-specific APIS is important because: - -Team membership APIs aren't equal to shared or private Channel membership Shared and private channels have their own membership models, which aren't the same as the parent team’s membership. - -Each channel has its own SharePoint site with its own permissions. Apps must follow these rules to prevent data leaks or access problems. - ## Apps and permissions in shared channels You can collaborate with external members outside of your organization using Shared channels. App permissions in Shared channels follow the host team's app roster and host tenant's app policy. From 68356f3715177c2e11d57beaed27bb3edd869e47 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 08:36:14 +0530 Subject: [PATCH 033/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 2aed8d1e50b..28ae87adadd 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -10,7 +10,7 @@ ms.date: 04/09/2025 # Microsoft Teams connect shared and private channels -Microsoft Teams Connect shared channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: +Microsoft Teams connect shared channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: * Members of another team within the same organization. * Individuals within the same organization. @@ -24,12 +24,12 @@ Microsoft Teams private channels allow a subset of team members to collaborate i > [!NOTE] > -> * Tab apps in Shared channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. -> * SharePoint and the SharePoint pages apps aren't supported for Shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. +> * Tab apps in shared channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. +> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. -Teams Connects Shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. +Teams Connects shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. -![Diagram shows Team B from organization A and Team C from organization B collaborating in a Shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) +![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) ## Teams channels – capabilities comparison @@ -58,16 +58,16 @@ For more information to enable your tab, see: ## Apps and permissions in shared channels -You can collaborate with external members outside of your organization using Shared channels. App permissions in Shared channels follow the host team's app roster and host tenant's app policy. +You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. > [!NOTE] -> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a Shared channel. +> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. ### Get shared channel membership You can get direct shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: -Note: This returns both internal and external users added to the Shared channel. +Note: This returns both internal and external users added to the shared channel. 1. Get direct members with [GET channel members API](/graph/api/channel-list-members?view=graph-rest-beta&tabs=http&preserve-view=true) API. @@ -189,7 +189,7 @@ For any event payload or action payload received for a bot, use Get hostTenant I --- -Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the Shared channel. +Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the shared channel. ## Identify guest users (B2B guests) in private channels @@ -208,9 +208,9 @@ Apps must function cross-tenants in installation and usage. The following table ## Access sharepoint data in shared and private channels -If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the Shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific Shared or private channel. +If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. -Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a Shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). +Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). ## Apps in Federated group chats with external users From afa0caf709471382a1921d472765b24aac587822 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 08:49:26 +0530 Subject: [PATCH 034/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 28ae87adadd..2f119acf2e3 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -210,9 +210,9 @@ Apps must function cross-tenants in installation and usage. The following table If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. -Use the Graph API to access the document library of the SharePoint Online (SPO) site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). +Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). -## Apps in Federated group chats with external users +## Apps in federated group chats with external users > [!NOTE] > From bfaf4f4e370a1667e167f9d5effad5a92c4f11cd Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 09:43:32 +0530 Subject: [PATCH 035/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 2f119acf2e3..4ee14d6ddcc 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -35,17 +35,17 @@ Teams Connects shared channels facilitate secure collaboration seamlessly. Allow | **Category** | **Capability** | **Standard channel** | **Private channel** | **Shared channel** | |--------------|----------------------------------------------------------------------------------|----------------------|---------------------|---------------------| -| **Membership** | Can add people to the channel without adding to the host team | No | No | Yes | -| | Channel membership can be limited to a subset of the host team | No | Yes | Yes | -| | Channel can be shared with other teams to inherit members from the team | No | No | Yes | -| | Channel can be shared directly with its parent team to inherit members | N/A | No | Yes | -| | Guests (B2B Guests) can participate in the channel | Yes | Yes | No | -| | External participants (B2B Direct Connect) can participate in the channel | No | No | Yes | -| | Channel is hosted under a host team | Yes | Yes | Yes | -| **Storage** | Each channel has a dedicated SharePoint site | No (inherits team site) | Yes | Yes | -| **App Model** | App must be installed in the host team | Yes | Yes | Yes | -| | App installed to host team automatically available in channel | Yes | No | No | -| | App must be added to each channel | No | Yes | Yes | +| **Membership** | Can add people to the channel without adding to the host team | :x: | :x: | :white_check_mark: | +| | Channel membership can be limited to a subset of the host team | :x: | :white_check_mark: | :white_check_mark: | +| | Channel can be shared with other teams to inherit members from the team | :x: | :x: | :white_check_mark: | +| | Channel can be shared directly with its parent team to inherit members | N/A | :x: | :white_check_mark: | +| | Guests (B2B Guests) can participate in the channel | :white_check_mark: | :white_check_mark: | :x: | +| | External participants (B2B Direct Connect) can participate in the channel | :x: | :x: | :white_check_mark: | +| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **Storage** | Each channel has a dedicated SharePoint site | :x: (inherits team site) | :white_check_mark: | :white_check_mark: | +| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| | App installed to host team automatically available in channel | :white_check_mark: | :x: | :x: | +| | App must be added to each channel | :x: | :white_check_mark: | :white_check_mark: | ### Get context for shared channels From 86cfa1e1232b134eff6918a5ca795807ddffdadb Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 09:53:34 +0530 Subject: [PATCH 036/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 4ee14d6ddcc..d9481b68fc1 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -71,7 +71,7 @@ Note: This returns both internal and external users added to the shared channel. 1. Get direct members with [GET channel members API](/graph/api/channel-list-members?view=graph-rest-beta&tabs=http&preserve-view=true) API. - ```http + ```csharp GET /teams/{host-team-group-id}/channels/{channel-id}/members ``` @@ -83,7 +83,7 @@ Note: This returns both internal and external users added to the shared channel. 3. Use GET members of each shared team (Team X) with GET `sharedWithTeams` API. - ```http + ```csharp GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members ``` @@ -93,7 +93,7 @@ You can classify members as in-tenant or out-tenant by comparing `tenantID` of t 1. Get the member you wish to compare. - ```http + ```csharp GET /teams/{host-team-group-id}/channels/{channel-id}/members ``` From ca45ec711d0cd9a87ec7271647eba0a55acedbf5 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 10:00:12 +0530 Subject: [PATCH 037/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index d9481b68fc1..437c50c5613 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -77,7 +77,7 @@ Note: This returns both internal and external users added to the shared channel. 2. Get each shared team with GET `sharedWithTeams` API. - ```http + ```csharp GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams ``` From 8f6140d020cf59f9139cb83ee5d222ca2bcdc114 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 10:18:20 +0530 Subject: [PATCH 038/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 437c50c5613..a5fffbf4529 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -71,19 +71,19 @@ Note: This returns both internal and external users added to the shared channel. 1. Get direct members with [GET channel members API](/graph/api/channel-list-members?view=graph-rest-beta&tabs=http&preserve-view=true) API. - ```csharp + ```HTTP GET /teams/{host-team-group-id}/channels/{channel-id}/members ``` 2. Get each shared team with GET `sharedWithTeams` API. - ```csharp + ```HTTP GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams ``` 3. Use GET members of each shared team (Team X) with GET `sharedWithTeams` API. - ```csharp + ```HTTP GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members ``` @@ -93,7 +93,7 @@ You can classify members as in-tenant or out-tenant by comparing `tenantID` of t 1. Get the member you wish to compare. - ```csharp + ```HTTP GET /teams/{host-team-group-id}/channels/{channel-id}/members ``` @@ -112,7 +112,7 @@ Apps installed in shared channels receive notifications when users are added to To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). -```csharp +```HTTP `/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` ``` @@ -140,7 +140,7 @@ These Bot Framework endpoints are essential for monitoring membership changes an When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the ```doesUserHaveAccess``` API to determine whether the user still has access to the shared channel. -```csharp +```HTTP GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') ``` @@ -156,7 +156,7 @@ If there are bulk membership changes, Teams curbs individual membership update n To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: -```csharp +```HTTP `/teams/{team-id}/channels/{channel-id}/sharedWithTeams` ``` From cc71494e937c261a5807ce2d196b51c6e6a43fd7 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 10 Sep 2025 18:35:56 +0530 Subject: [PATCH 039/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index a5fffbf4529..0b73919498c 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -10,17 +10,27 @@ ms.date: 04/09/2025 # Microsoft Teams connect shared and private channels -Microsoft Teams connect shared channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: +Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels enable users to work across teams and organizations, allowing seamless communication with internal members or external partners. Private channels provide a secure space for select team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -* Members of another team within the same organization. -* Individuals within the same organization. -* Individuals and other teams of other organizations. +## Most apps easily support shared and private channels in Microsoft Teams -Microsoft Teams private channels allow a subset of team members to collaborate in a more focused and secure space, separate from general team discussion. You can create and use a private channel with: +For many apps, enabling support is simple. If your app doesn’t depend on any of the following: -* Selected members of the same team. -* Internal stakeholders who require restricted access to sensitive content. -* Team members working on confidential projects. +* Using channel or team membership to determine message delivery, task assignment, or permissions +* Accessing or managing files stored in Teams or SharePoint +* Combining or sharing data across multiple channels or teams +* Customizing the experience based on whether users are internal, guests, or external participants + +In that case, complete the following steps: + +1. Add ```"supportsChannelFeatures": "tier1"``` to your app manifest to enable support for shared and private channels. +2. Test your app in standard, private, and shared channels to verify expected behavior. + +If your app uses any of the preceding features: + +Continue reading for specific updates and best practices to help your app run smoothly across all channel types. + +For most apps, only a small update is needed. If your app involves more complex scenarios, this guide provides necessary updates to help you make the right changes without rebuilding theyour entire codebase. > [!NOTE] > From 0efdd6f4584c19bcbf37a6aa10f894e7f680eade Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 11 Sep 2025 10:42:08 +0530 Subject: [PATCH 040/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 0b73919498c..aec21e9e96c 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -10,18 +10,18 @@ ms.date: 04/09/2025 # Microsoft Teams connect shared and private channels -Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels enable users to work across teams and organizations, allowing seamless communication with internal members or external partners. Private channels provide a secure space for select team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. +Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -## Most apps easily support shared and private channels in Microsoft Teams - -For many apps, enabling support is simple. If your app doesn’t depend on any of the following: +## Enable apps support for shared and private channels +You can enable app support for shared and private channels based on whether your app is: + * Using channel or team membership to determine message delivery, task assignment, or permissions * Accessing or managing files stored in Teams or SharePoint * Combining or sharing data across multiple channels or teams -* Customizing the experience based on whether users are internal, guests, or external participants +* Customizing the experience based on whether users are internal, guests, or external participants -In that case, complete the following steps: +If it doesn't follow the preceding parameters, perform the following steps to enable app support in shared and private channels: 1. Add ```"supportsChannelFeatures": "tier1"``` to your app manifest to enable support for shared and private channels. 2. Test your app in standard, private, and shared channels to verify expected behavior. @@ -30,7 +30,7 @@ If your app uses any of the preceding features: Continue reading for specific updates and best practices to help your app run smoothly across all channel types. -For most apps, only a small update is needed. If your app involves more complex scenarios, this guide provides necessary updates to help you make the right changes without rebuilding theyour entire codebase. +For most apps, only a small update is needed. If your app involves more complex scenarios, this guide provides necessary updates to help you make the right changes without rebuilding your entire codebase. > [!NOTE] > @@ -73,6 +73,8 @@ You can collaborate with external members outside of your organization using sha > [!NOTE] > The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. +## Manage Shared Channel Membership + ### Get shared channel membership You can get direct shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: From a50fdd9308ebfe556f80506ae5be4e08061a157c Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 11 Sep 2025 17:40:00 +0530 Subject: [PATCH 041/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 173 +++++++++++++++--- 1 file changed, 151 insertions(+), 22 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index aec21e9e96c..35e47eea4a8 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -24,13 +24,15 @@ You can enable app support for shared and private channels based on whether your If it doesn't follow the preceding parameters, perform the following steps to enable app support in shared and private channels: 1. Add ```"supportsChannelFeatures": "tier1"``` to your app manifest to enable support for shared and private channels. -2. Test your app in standard, private, and shared channels to verify expected behavior. +2. To verify expected behavior, test your app in standard, private, and shared channels. If your app uses any of the preceding features: -Continue reading for specific updates and best practices to help your app run smoothly across all channel types. +For more information, see the following articles: -For most apps, only a small update is needed. If your app involves more complex scenarios, this guide provides necessary updates to help you make the right changes without rebuilding your entire codebase. +* [Manage Shared Channel Membership](#manage-shared-channel-membership) +* [Apps and permissions in shared channels](#apps-and-permissions-in-shared-channels) +* [Verify if your app is added to a channel](#verify-if-your-app-is-added-to-a-channel) > [!NOTE] > @@ -43,6 +45,8 @@ Teams Connects shared channels facilitate secure collaboration seamlessly. Allow ## Teams channels – capabilities comparison +Let's see how Teams channels type differ in their capabilities. + | **Category** | **Capability** | **Standard channel** | **Private channel** | **Shared channel** | |--------------|----------------------------------------------------------------------------------|----------------------|---------------------|---------------------| | **Membership** | Can add people to the channel without adding to the host team | :x: | :x: | :white_check_mark: | @@ -66,13 +70,6 @@ For more information to enable your tab, see: * [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) -## Apps and permissions in shared channels - -You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. - -> [!NOTE] -> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. - ## Manage Shared Channel Membership ### Get shared channel membership @@ -135,13 +132,53 @@ This subscription enables apps to monitor membership changes in shared channels When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. ```csharp -public async Task OnMembersAddedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) + protected override async Task OnTeamsMembersAddedAsync( + IList membersAdded, + TeamInfo teamInfo, + ITurnContext turnContext, + CancellationToken cancellationToken) + { + var extended = turnContext.Activity.GetChannelData(); + var source = extended?.MembershipSource + ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); + + if (source != null) + { + _logger.LogInformation("MemberAdded via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", + source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); + + await turnContext.SendActivityAsync( + MessageFactory.Text($"👤 Member added via **{source.SourceType}** ({source.MembershipType})."), + cancellationToken); + } + + await base.OnTeamsMembersAddedAsync(membersAdded, teamInfo, turnContext, cancellationToken); ``` Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsync``` method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. ```csharp -public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) + protected override async Task OnTeamsMembersRemovedAsync( + IList membersRemoved, + TeamInfo teamInfo, + ITurnContext turnContext, + CancellationToken cancellationToken) + { + var source = turnContext.Activity.GetChannelData()?.MembershipSource + ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); + + if (source != null) + { + _logger.LogInformation("MemberRemoved via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", + source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); + + await turnContext.SendActivityAsync( + MessageFactory.Text($"👋 Member removed (source **{source.SourceType}**, {source.MembershipType})."), + cancellationToken); + } + + await base.OnTeamsMembersRemovedAsync(membersRemoved, teamInfo, turnContext, cancellationToken); + } ``` These Bot Framework endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. @@ -183,11 +220,103 @@ The sharedWithTeams subscription sends a single notification when a channel is s ### [Bot Framework](#tab/botframework-bulk) -When a shared channel is added to another team, the Bot Framework may receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. +When a shared channel is added to another team, the Bot Framework might receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. + +```csharp + protected override async Task OnConversationUpdateActivityAsync( + ITurnContext turnContext, + CancellationToken cancellationToken) + { + // Always present on Teams activities + var tcd = turnContext.Activity.GetChannelData(); + var eventType = tcd?.EventType?.ToLowerInvariant(); + + // Read extended shared-channel shape (safe even if fields are absent) + var extended = turnContext.Activity.GetChannelData(); + + // Also keep a raw JObject for logging / future-proof access + var raw = turnContext.Activity.ChannelData as JObject + ?? (turnContext.Activity.ChannelData != null + ? JObject.FromObject(turnContext.Activity.ChannelData) + : new JObject()); + + // Helpful baseline log + _logger.LogInformation("ConversationUpdate eventType={EventType}, channelId={ChannelId}, teamId={TeamId}", + eventType, tcd?.Channel?.Id, tcd?.Team?.Id); + + switch (eventType) + { + case "channelshared": + { + var hostTeam = extended?.Team; // The channel's host team + var sharedWith = extended?.SharedWithTeams ?? new List(); + + _logger.LogInformation("ChannelShared: hostTeam={HostTeamId}, sharedWithCount={Count}", + hostTeam?.Id, sharedWith.Count); + + foreach (var team in sharedWith) + { + _logger.LogInformation("SharedWithTeam: id={Id}, name={Name}, aadGroupId={AadGroupId}, tenantId={TenantId}", + team.Id, team.Name, team.AadGroupId, team.TenantId); + } + + // Optional: surface a quick confirmation in-channel + await turnContext.SendActivityAsync( + MessageFactory.Text($"✅ Channel shared with {sharedWith.Count} team(s)."), + cancellationToken); + break; + } + + case "channelunshared": + { + var unsharedFrom = extended?.UnsharedFromTeams ?? new List(); + + _logger.LogInformation("ChannelUnshared: unsharedFromCount={Count}", unsharedFrom.Count); + + foreach (var team in unsharedFrom) + { + _logger.LogInformation("UnsharedFromTeam: id={Id}, name={Name}, aadGroupId={AadGroupId}, tenantId={TenantId}", + team.Id, team.Name, team.AadGroupId, team.TenantId); + } + + await turnContext.SendActivityAsync( + MessageFactory.Text($"❎ Channel unshared from {unsharedFrom.Count} team(s)."), + cancellationToken); + break; + } + + default: + // No-op; continue normal routing + break; + } + + await base.OnConversationUpdateActivityAsync(turnContext, cancellationToken); + } +``` --- -## Authenticate external users to access your app content in sharepoint +## Apps and permissions in shared channels + +You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. + +> [!NOTE] +> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. + +## Verify if your app is added to a channel + +For bots using the Bot Framework SDK, if your bot receives a channelMemberAdded event in a conversationUpdate activity for itself, it indicates that the app is added to the channel. +Begin your channel-specific logic at that point, for example, send a welcome message, fetch the roster, configure tabs, or schedule jobs as needed. Bot events start flowing only after the app is added to the channel + +There’s no direct API to check whether your app is added to a channel. + +> [!NOTE] +> +> * Use ```GET /teams/{team-id}/installedApps```, to list installed apps at the team level. +> * Channel level InstalledApps aren't listed. +> * Avoid using team-level installations to determine which apps are in a channel. + +## Authenticate external users to access app content in SharePoint You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. @@ -211,7 +340,7 @@ For guests, “roles” = “guest” ## Microsoft Entra native identity -Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group ids: +Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group IDs: |Channel type| groupId | hostTeamGroupId | |----------|---------|-----------------| @@ -252,7 +381,7 @@ If you're developing an app for use in federated group chats with external users
Why isn’t the app visible when trying to add it to a channel? -If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as "supportsChannelFeatures": tier1, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps cannot be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as "supportsChannelFeatures": tier1, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
  @@ -260,7 +389,7 @@ If an app isn’t visible when trying to add it to a channel, there are a few li
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -A 403 error stating "app not enabled in this channel" typically occurs when the app is installed at the team level but is not added to the specific channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel. +You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel.
  @@ -268,13 +397,13 @@ A 403 error stating "app not enabled in this channel" typically occurs when the
Why does the channel roster appear incomplete, showing only owners or missing users? -If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely is not added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
 
-Why does file access fail for some users even though they are part of the channel? +Why does file access fail for some users even though they're part of the channel? This failure can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the /invite API to give access to specific users or groups. @@ -284,7 +413,7 @@ This failure can happen if the app is using the team’s main SharePoint site in
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing context.user.tenant.id with the host or owner tenant ID. If they are different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. +Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing context.user.tenant.id with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken.
  @@ -292,7 +421,7 @@ Authentication issues in tabs or task modules for external users often occur whe
How do I know my app was added to a channel? -This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there is no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they are added. If the app doesn’t receive the event and gets a 403 error, it prompts the user to add the bot to the channel and handles the error. +This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there's no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error.
  @@ -308,7 +437,7 @@ Message change notifications might fail in shared or private channels because su
Why do file links still fail for external users even after the app is added to the channel? -This can happen if the type of link being used is not allowed by the tenant’s sharing policy, or if the user hasn’t been granted access to the specific item, despite being a member of the channel. Another common cause is that the app might have generated links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item—even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. ## See also From 10754860bd50a3a7cf6c72d7e21b9a900509835c Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 11 Sep 2025 18:25:53 +0530 Subject: [PATCH 042/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 35e47eea4a8..55ee0491a51 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -26,9 +26,7 @@ If it doesn't follow the preceding parameters, perform the following steps to en 1. Add ```"supportsChannelFeatures": "tier1"``` to your app manifest to enable support for shared and private channels. 2. To verify expected behavior, test your app in standard, private, and shared channels. -If your app uses any of the preceding features: - -For more information, see the following articles: +If your app uses any of the preceding features, see the following articles, for more information: * [Manage Shared Channel Membership](#manage-shared-channel-membership) * [Apps and permissions in shared channels](#apps-and-permissions-in-shared-channels) @@ -381,7 +379,7 @@ If you're developing an app for use in federated group chats with external users
Why isn’t the app visible when trying to add it to a channel? -If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as "supportsChannelFeatures": tier1, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as ```"supportsChannelFeatures": tier1```, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
  @@ -389,7 +387,7 @@ If an app isn’t visible when trying to add it to a channel, there are a few li
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ChannelMember.Read.Group for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel. +You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ```ChannelMember.Read.Group``` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel.
  @@ -397,7 +395,7 @@ You’ll see a 403 error saying "app not enabled in this channel" if the app is
Why does the channel roster appear incomplete, showing only owners or missing users? -If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the /channels/{id}/allMembers API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ```/channels/{id}/allMembers``` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
  @@ -413,7 +411,7 @@ This failure can happen if the app is using the team’s main SharePoint site in
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing context.user.tenant.id with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. +Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ```context.user.tenant.id``` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken.
  @@ -429,7 +427,7 @@ This issue might occur if the app is expecting a centralized list of installed a
Why is my app failing to create message change notifications in shared or private channels? -Message change notifications might fail in shared or private channels because subscriptions to /channels/{id}/messages are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. +Message change notifications might fail in shared or private channels because subscriptions to ```/channels/{id}/messages``` are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel.
  @@ -437,7 +435,7 @@ Message change notifications might fail in shared or private channels because su
Why do file links still fail for external users even after the app is added to the channel? -This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item—even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. ## See also From ac9761a74ca0b09e846d3eb45aabbc4033d6c3ad Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 11 Sep 2025 18:32:18 +0530 Subject: [PATCH 043/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 55ee0491a51..20fda6f55e9 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -12,7 +12,7 @@ ms.date: 04/09/2025 Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -## Enable apps support for shared and private channels +## Enable app support for shared and private channels You can enable app support for shared and private channels based on whether your app is: From 61b12534b9ff1adf22131059d2b01372d02ca487 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 11 Sep 2025 22:49:37 +0530 Subject: [PATCH 044/109] Update shared-channels.md --- .../concepts/build-and-test/shared-channels.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 20fda6f55e9..bfed1f260b7 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -29,7 +29,7 @@ If it doesn't follow the preceding parameters, perform the following steps to en If your app uses any of the preceding features, see the following articles, for more information: * [Manage Shared Channel Membership](#manage-shared-channel-membership) -* [Apps and permissions in shared channels](#apps-and-permissions-in-shared-channels) +* [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) * [Verify if your app is added to a channel](#verify-if-your-app-is-added-to-a-channel) > [!NOTE] @@ -294,7 +294,7 @@ When a shared channel is added to another team, the Bot Framework might receive --- -## Apps and permissions in shared channels +## Understand app permissions in shared channels You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. @@ -387,7 +387,7 @@ If an app isn’t visible when trying to add it to a channel, there are a few li
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ```ChannelMember.Read.Group``` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the channelMemberAdded event to confirm it has been successfully added to the channel. +You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ```ChannelMember.Read.Group``` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ```channelMemberAdded``` event to confirm it has been successfully added to the channel.
  @@ -403,7 +403,7 @@ If the channel roster appears incomplete showing only owners or missing users, i
Why does file access fail for some users even though they're part of the channel? -This failure can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the /invite API to give access to specific users or groups. +This failure can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the invite API to give access to specific users or groups.
  @@ -435,7 +435,7 @@ Message change notifications might fail in shared or private channels because su
Why do file links still fail for external users even after the app is added to the channel? -This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the /invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. ## See also From 556ffdbd57f81f550b8e401c6b21b2d9948973e4 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 12 Sep 2025 13:43:24 +0530 Subject: [PATCH 045/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index bfed1f260b7..91ac474838a 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -28,7 +28,7 @@ If it doesn't follow the preceding parameters, perform the following steps to en If your app uses any of the preceding features, see the following articles, for more information: -* [Manage Shared Channel Membership](#manage-shared-channel-membership) +* [Manage Shared and Private Channel Membership](#manage-shared-channel-membership) * [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) * [Verify if your app is added to a channel](#verify-if-your-app-is-added-to-a-channel) @@ -68,7 +68,7 @@ For more information to enable your tab, see: * [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) -## Manage Shared Channel Membership +## Manage Shared and Private Channel Membership ### Get shared channel membership From 30ad1822be1be315377c86fea5081f00b12c99ba Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 18 Sep 2025 12:48:06 +0530 Subject: [PATCH 046/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 218 ++++++++++++++---- 1 file changed, 170 insertions(+), 48 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 91ac474838a..ae6857afa09 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -1,5 +1,5 @@ --- -title: Teams Connects Shared Channels +title: Teams Connects Shared and Private Channels author: surbhigupta description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. ms.author: surbhigupta @@ -12,6 +12,53 @@ ms.date: 04/09/2025 Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. +## Understand Channel Models in Microsoft Teams + +When building or integrating apps with Microsoft Teams, understand how different channel types affect visibility, membership, and data storage. + +* **Standard channels:** Accessible to every team member by default. The standard channels support team-wide collaboration and are suitable for scenarios where bots, or tabs, need to be accessible to every team member. Files shared in standard channels are stored in the team’s SharePoint site. + +* **Private channels:** Visible only to a selected subset of team members. The private channels are suited for scenarios that require tighter control over membership and data, such as limiting bots, connectors, or stored files to only members of the private channel. Files shared in private channels are stored in a dedicated SharePoint site, separate from the team’s default site. + +* **Shared channels:** Designed for cross-team and cross-organization collaboration. They support scenarios where app components such as bots and tabs, need to interact with users who aren’t part of the host team, without requiring those users to join the team. Files are managed in the shared channel's SharePoint site. + +## Teams channels – capabilities comparison + +Let's see how Teams channels type differ in their capabilities. + +| **Model** | **Channel Capability** | **Standard Channel** | **Other Channels** | +|----------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------------------| +| **Membership** | Can add people to the channel without adding to the host team | :x: | Supported (Shared channels) | +| | Channel membership can be limited to a subset of the host team | :x: | Supported | +| | Channel can be shared with other teams to inherit members | :x: | Supported (Shared channels) | +| | Channel can be shared directly with its parent team | N/A | Supported (Shared channels) | +| | External users can participate in the channel | :white_check_mark: (B2B collab users) | :white_check_mark: (B2B Direct Connect in Shared channels, B2B collab users in Private channels) | +| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | +| **Storage** | Each channel has a dedicated SharePoint site | :x: (Inherits team site) | :white_check_mark: | +| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: | +| | App installed to host team automatically available in channel | :white_check_mark: | :x: | +| | App must be added to each channel | :x: | :white_check_mark: | + +## Understand channel differences that impact app functionality + +Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. + +* In private and shared channels, not everyone in the team has access. Only members who are specifically added to the channel can participate in these channels. If your bot targets "everyone," it may violate privacy or miss external members. Always use channel-specific membership APIs to determine the correct members. + +* Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Always validate user roles and tenant IDs before granting permissions or executing actions. + +* Private and shared channels have their own SharePoint sites. If your app targets the wrong site, it may encounter missing files or unauthorized access errors. Always resolve the correct site URL for each channel. + +* Aggregate or cross-post data across channels only when necessary. Keep data scoped to the channel unless clearly defined to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. + +![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) | + +> [!NOTE] +> +> Don't depend on channel type to determine behavior. Avoid making make any logic decisions based on the channel type in your code. Instead, check for the capabilities your app needs (for example, membership boundaries, storage location, external access) and always use APIs and patterns that work across all channel types. + +Use the following guidance to enable app support for shared and private channels. + ## Enable app support for shared and private channels You can enable app support for shared and private channels based on whether your app is: @@ -28,38 +75,16 @@ If it doesn't follow the preceding parameters, perform the following steps to en If your app uses any of the preceding features, see the following articles, for more information: -* [Manage Shared and Private Channel Membership](#manage-shared-channel-membership) +* [Manage channel membership](#manage-channel-membership) * [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) * [Verify if your app is added to a channel](#verify-if-your-app-is-added-to-a-channel) > [!NOTE] > -> * Tab apps in shared channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. -> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. - -Teams Connects shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. - -![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) - -## Teams channels – capabilities comparison +> * Tab and bot apps in shared and private channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. +> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. | -Let's see how Teams channels type differ in their capabilities. - -| **Category** | **Capability** | **Standard channel** | **Private channel** | **Shared channel** | -|--------------|----------------------------------------------------------------------------------|----------------------|---------------------|---------------------| -| **Membership** | Can add people to the channel without adding to the host team | :x: | :x: | :white_check_mark: | -| | Channel membership can be limited to a subset of the host team | :x: | :white_check_mark: | :white_check_mark: | -| | Channel can be shared with other teams to inherit members from the team | :x: | :x: | :white_check_mark: | -| | Channel can be shared directly with its parent team to inherit members | N/A | :x: | :white_check_mark: | -| | Guests (B2B Guests) can participate in the channel | :white_check_mark: | :white_check_mark: | :x: | -| | External participants (B2B Direct Connect) can participate in the channel | :x: | :x: | :white_check_mark: | -| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| **Storage** | Each channel has a dedicated SharePoint site | :x: (inherits team site) | :white_check_mark: | :white_check_mark: | -| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| | App installed to host team automatically available in channel | :white_check_mark: | :x: | :x: | -| | App must be added to each channel | :x: | :white_check_mark: | :white_check_mark: | - -### Get context for shared channels +### Get context for shared and private channels When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. @@ -68,45 +93,67 @@ For more information to enable your tab, see: * [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) -## Manage Shared and Private Channel Membership +## Manage channel membership -### Get shared channel membership +This section explains how to view and manage the membership of Microsoft Teams Channels. -You can get direct shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: +### Retrieve full channel membership -Note: This returns both internal and external users added to the shared channel. +To accurately retrieve the all members of any Microsoft Teams channel Standard, Private, or Shared use the ``allMembers`` API: -1. Get direct members with [GET channel members API](/graph/api/channel-list-members?view=graph-rest-beta&tabs=http&preserve-view=true) API. +```HTTP +GET /teams/{team-id}/channels/{channel-id}/allMembers`` +``` - ```HTTP - GET /teams/{host-team-group-id}/channels/{channel-id}/members - ``` +This API works across all channel types and returns the actual members of a channel, rather than the broader team members. For shared channels, it also includes indirect members, such as users from other teams who have been granted access. -2. Get each shared team with GET `sharedWithTeams` API. +### Understand shared channel membership - ```HTTP - GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams - ``` +Shared channels support three types of membership direct, indirect and external allowing flexible collaboration across teams. -3. Use GET members of each shared team (Team X) with GET `sharedWithTeams` API. +#### Direct members - ```HTTP - GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members - ``` +Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. -## Classify members in the shared channel as in-tenant or out-tenant +You can retrieve the list of direct members in a shared channel by using the ``hostTeamGroupID`` obtained from ``getContext`` and calling the appropriate API. This method returns all users who have been explicitly added to the shared channel, including both internal and external participants. -You can classify members as in-tenant or out-tenant by comparing `tenantID` of the member or team with `hostTeamTenantID` as follows: +To retrieve direct members of a shared channel: -1. Get the member you wish to compare. +1. Call the following API: ```HTTP GET /teams/{host-team-group-id}/channels/{channel-id}/members ``` -2. Use `getContext`, compare the `tenantID` of the member to the `hostTenantID` property. +#### Indirect members + +Indirect members are users who can access shared channel through their membership in a team that the channel is shared with. These users are not added directly to the channel but are eligible to participate because their team has been granted access. + +To retrieve indirect members of a shared channel: - +1. Call the following API to identify which teams the channel is shared with: + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams +``` + +2. Call the following API for each team returned: + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{shared-team-id}/allowedMembers +``` + +#### External members + +An external member are users who is not part of your organization but has been granted access to a shared channel through guest access or cross-tenant collaboration. + +To retrieve external members of a shared channel: + +1. Call the following API: + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/members +``` ## Get app notifications for direct and indirect membership changes @@ -374,6 +421,81 @@ If you're developing an app for use in federated group chats with external users |-------------|-------------|------| |Teams Conversation Bot|This sample app displays the names of the members in a federated group chat with external users.|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-feed-members/nodejs/)| +## Test your app across channel types + +Before publishing updates, validate your app behaves correctly in real situations behaves across all channel types. + +### Standard channel + +Confirm that the existing functionality remains intact after your changes. Ensure tabs, bots and messaging extensions continue to work as expected. + +### Private channel + +Try this setup: Create a private channel P in Team A with atleast two members (one owner, one member). + +Test steps: + +1. Add the app to Team A then add it to private channel P. +2. Verify that your tab loads correctly in the private channel. +3. Test bot responses for different user types: + * In-tenant member + * Guest user + * External user (if applicable) +4. If your app lists members or assigns tasks, confirm it only uses channel members and not the complete team. +5. Add a new member to the private channel and check: + * Whether your bot receives a membership change event + * Whether your membership API reflects the new member. + +### Shared channel (same tenant) + +Try this setup: Create shared channel X in Team A, then share it with Team B (requires owner permissions). + +Test steps: + +1. Add the app to Team A (host team), then to Channel X. +2. Validate that members from Team B. + * Can see the tab + * Receive bot responses +3. Unshare the channel from Team B and confirm: + * Your bot receives a ``channelUnshared`` event + * Membership updates are handled correctly + +### Shared channel (external tenant) + +Try this setup: Use two tenants or collaborate with a colleague from another organization via Teams Connect. + +Test steps: + +1. Have an external user send a message to your bot, does it respond? +2. Trigger a task module or tab interaction as the external user: + * Does authentication succeed? + * If using SSO, ensure ``getAuthToken`` handles the user's home tenant ID correctly. +3. Attempt a direct message from your bot to the external user: + * This will fail if the user is outside your tenant + * Confirm that in-channel communication still works. + +Testing across these scenarios will help you spot any issues with functionality, permissions, and user experience. + +## Best practices for supporting all channels + +Follow these best practices to ensure your app works reliably across all channel types: + +* Always retrieve the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. + +* Adjust app functionality and access controls based on user roles (owner, member, guest, external). Limit sensitive actions to owners or internal users, and offer limited features to guests or external participants. + +* Control data access and sharing based on channel membership and permissions. Never include private-channel data in broader reports or public channels unless explicitly authorized. + +* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when they access files. + +* Update help text and user guides to explain how your app behaves in different channel types, including any limitations for guests or external users. + +* Cache large member lists and use change notifications to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. + +* Test your app across different user roles and channel configurations including owners, members, guests, and external users to confirm it behaves correctly and enforces appropriate permissions. + +* Review Microsoft Teams documentation and changelogs to keep your app aligned with the latest updates to APIs, permissions, and channel configurations. + ## Frequently asked questions
From 24f64f48364d09fd0ed24a4bb31706eb30671e20 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 18 Sep 2025 12:50:28 +0530 Subject: [PATCH 047/109] Update shared-channels.md --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index ae6857afa09..e9e42888641 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -12,7 +12,7 @@ ms.date: 04/09/2025 Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -## Understand Channel Models in Microsoft Teams +## Understand channel models in Microsoft Teams When building or integrating apps with Microsoft Teams, understand how different channel types affect visibility, membership, and data storage. From 44e2ee99c2c3de742fee7f274fce82574433a781 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 18 Sep 2025 15:04:57 +0530 Subject: [PATCH 048/109] Updated --- .../build-and-test/shared-channels.md | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index e9e42888641..cfb86b21e49 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -383,38 +383,12 @@ You can identify if a member of private channel is guest user, invited to your t For guests, “roles” = “guest” -## Microsoft Entra native identity - -Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group IDs: - -|Channel type| groupId | hostTeamGroupId | -|----------|---------|-----------------| -|Standard | Team Microsoft Entra group ID | Team Microsoft Entra group ID | -|Shared | Empty | Host Team Microsoft Entra group ID | - ## Access sharepoint data in shared and private channels If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). -## Apps in federated group chats with external users - -> [!NOTE] -> -> * Apps in federated group chats with external users aren't available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](~/concepts/sovereign-cloud.md) environments. -> * Apps aren't supported in one-on-one chats, channels, or meetings with external users. - -Teams supports the use of apps in federated group chats with external users. These users can't add, update, or remove apps from the group chat. Only the host of the group chat can add, update, or remove apps. However, all members of the chat, including external users, can use apps under the following conditions: - -* The tenant admin of the group chat host's organization and the tenant admin of the external user's organization must allow the use of the app in federated group chats. For more information, see [Teams apps for external attendees or guests from outside an organization](/microsoftteams/apps-external-users). -* The app allows access to external users in federated group chats. - -If you're developing an app for use in federated group chats with external users, register your app as a multitenant app in Microsoft Entra ID. This action allows users across multiple organizations to access your app. - -> [!NOTE] -> If you want to test the [code sample](#code-sample) with an external user in a federated group chat, you must first add the external user as a guest to your tenant. For more information, see [Quickstart: Add a guest user and send an invitation](/entra/external-id/b2b-quickstart-add-guest-users-portal). After adding the user to the tenant, go to the federated group chat and add the guest to test the app. - ## Code sample |Sample name|Description|Node.js| From f797d1e7aac339729cdcf5a1af0ad04957d78e33 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 18 Sep 2025 19:06:33 +0530 Subject: [PATCH 049/109] Updated --- msteams-platform/TOC.yml | 3 + .../build-apps-for-shared-private-channels.md | 543 ++++++++++++++++++ 2 files changed, 546 insertions(+) create mode 100644 msteams-platform/build-apps-for-shared-private-channels.md diff --git a/msteams-platform/TOC.yml b/msteams-platform/TOC.yml index 12e83575edf..3fd7f926d66 100644 --- a/msteams-platform/TOC.yml +++ b/msteams-platform/TOC.yml @@ -688,6 +688,9 @@ - name: Integrate meetings and calls in external apps href: get-started/b2c-apps.md displayName: Teams meeting, Teams call, Teams meeting and call for external apps, external apps +- name: Apps for Shared and Private Channels + href: msteams-platform/build-apps-for-shared-private-channels.md + displayName: shared channels, private channels - name: Build webhooks and connectors items: - name: Overview diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md new file mode 100644 index 00000000000..1906081b715 --- /dev/null +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -0,0 +1,543 @@ +--- +title: Teams Connects Shared and Private Channels +author: surbhigupta +description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. +ms.author: surbhigupta +ms.localizationpriority: high +ms.topic: conceptual +ms.date: 04/09/2025 +--- + +# Microsoft Teams connect shared and private channels + +Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. + +## Understand channel models in Microsoft Teams + +When building or integrating apps with Microsoft Teams, understand how different channel types affect visibility, membership, and data storage. + +* **Standard channels:** Accessible to every team member by default. The standard channels support team-wide collaboration and are suitable for scenarios where bots, or tabs, need to be accessible to every team member. Files shared in standard channels are stored in the team’s SharePoint site. + +* **Private channels:** Visible only to a selected subset of team members. The private channels are suited for scenarios that require tighter control over membership and data, such as limiting bots, connectors, or stored files to only members of the private channel. Files shared in private channels are stored in a dedicated SharePoint site, separate from the team’s default site. + +* **Shared channels:** Designed for cross-team and cross-organization collaboration. They support scenarios where app components such as bots and tabs, need to interact with users who aren’t part of the host team, without requiring those users to join the team. Files are managed in the shared channel's SharePoint site. + +## Teams channels – capabilities comparison + +Let's see how Teams channels type differ in their capabilities. + +| **Model** | **Channel Capability** | **Standard Channel** | **Other Channels** | +|----------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------------------| +| **Membership** | Can add people to the channel without adding to the host team | :x: | Supported (Shared channels) | +| | Channel membership can be limited to a subset of the host team | :x: | Supported | +| | Channel can be shared with other teams to inherit members | :x: | Supported (Shared channels) | +| | Channel can be shared directly with its parent team | N/A | Supported (Shared channels) | +| | External users can participate in the channel | :white_check_mark: (B2B collab users) | :white_check_mark: (B2B Direct Connect in Shared channels, B2B collab users in Private channels) | +| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | +| **Storage** | Each channel has a dedicated SharePoint site | :x: (Inherits team site) | :white_check_mark: | +| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: | +| | App installed to host team automatically available in channel | :white_check_mark: | :x: | +| | App must be added to each channel | :x: | :white_check_mark: | + +## Understand channel differences that impact app functionality + +Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. + +* In private and shared channels, not everyone in the team has access. Only members who are specifically added to the channel can participate in these channels. If your bot targets "everyone," it may violate privacy or miss external members. Always use channel-specific membership APIs to determine the correct members. + +* Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Always validate user roles and tenant IDs before granting permissions or executing actions. + +* Private and shared channels have their own SharePoint sites. If your app targets the wrong site, it may encounter missing files or unauthorized access errors. Always resolve the correct site URL for each channel. + +* Aggregate or cross-post data across channels only when necessary. Keep data scoped to the channel unless clearly defined to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. + +![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) | + +> [!NOTE] +> +> Don't depend on channel type to determine behavior. Avoid making make any logic decisions based on the channel type in your code. Instead, check for the capabilities your app needs (for example, membership boundaries, storage location, external access) and always use APIs and patterns that work across all channel types. + +Use the following guidance to enable app support for shared and private channels. + +## Enable app support for shared and private channels + +You can enable app support for shared and private channels based on whether your app is: + +* Using channel or team membership to determine message delivery, task assignment, or permissions +* Accessing or managing files stored in Teams or SharePoint +* Combining or sharing data across multiple channels or teams +* Customizing the experience based on whether users are internal, guests, or external participants + +If it doesn't follow the preceding parameters, perform the following steps to enable app support in shared and private channels: + +1. Add ```"supportsChannelFeatures": "tier1"``` to your app manifest to enable support for shared and private channels. +2. To verify expected behavior, test your app in standard, private, and shared channels. + +If your app uses any of the preceding features, see the following articles, for more information: + +* [Manage channel membership](#manage-channel-membership) +* [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) +* [Verify if your app is added to a channel](#verify-if-your-app-is-added-to-a-channel) + +> [!NOTE] +> +> * Tab and bot apps in shared and private channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. +> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. | + +### Get context for shared and private channels + +When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. + +For more information to enable your tab, see: + +* [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) +* [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) + +## Manage channel membership + +This section explains how to view and manage the membership of Microsoft Teams Channels. + +### Retrieve full channel membership + +To accurately retrieve the all members of any Microsoft Teams channel Standard, Private, or Shared use the ``allMembers`` API: + +```HTTP +GET /teams/{team-id}/channels/{channel-id}/allMembers`` +``` + +This API works across all channel types and returns the actual members of a channel, rather than the broader team members. For shared channels, it also includes indirect members, such as users from other teams who have been granted access. + +### Understand shared channel membership + +Shared channels support three types of membership direct, indirect and external allowing flexible collaboration across teams. + +#### Direct members + +Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. + +You can retrieve the list of direct members in a shared channel by using the ``hostTeamGroupID`` obtained from ``getContext`` and calling the appropriate API. This method returns all users who have been explicitly added to the shared channel, including both internal and external participants. + +To retrieve direct members of a shared channel: + +1. Call the following API: + + ```HTTP + GET /teams/{host-team-group-id}/channels/{channel-id}/members + ``` + +#### Indirect members + +Indirect members are users who can access shared channel through their membership in a team that the channel is shared with. These users are not added directly to the channel but are eligible to participate because their team has been granted access. + +To retrieve indirect members of a shared channel: + +1. Call the following API to identify which teams the channel is shared with: + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams +``` + +2. Call the following API for each team returned: + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{shared-team-id}/allowedMembers +``` + +#### External members + +An external member are users who is not part of your organization but has been granted access to a shared channel through guest access or cross-tenant collaboration. + +To retrieve external members of a shared channel: + +1. Call the following API: + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/members +``` + +## Get app notifications for direct and indirect membership changes + +### [Graph](#tab/graph) + +Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. To receive these notifications, you must: + +1. [Install the app](../deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. +2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. + +To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). + +```HTTP +`/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` +``` + +This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) + +### [Bot Framework](#tab/bot-framework) + +When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. + +```csharp + protected override async Task OnTeamsMembersAddedAsync( + IList membersAdded, + TeamInfo teamInfo, + ITurnContext turnContext, + CancellationToken cancellationToken) + { + var extended = turnContext.Activity.GetChannelData(); + var source = extended?.MembershipSource + ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); + + if (source != null) + { + _logger.LogInformation("MemberAdded via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", + source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); + + await turnContext.SendActivityAsync( + MessageFactory.Text($"👤 Member added via **{source.SourceType}** ({source.MembershipType})."), + cancellationToken); + } + + await base.OnTeamsMembersAddedAsync(membersAdded, teamInfo, turnContext, cancellationToken); +``` + +Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsync``` method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. + +```csharp + protected override async Task OnTeamsMembersRemovedAsync( + IList membersRemoved, + TeamInfo teamInfo, + ITurnContext turnContext, + CancellationToken cancellationToken) + { + var source = turnContext.Activity.GetChannelData()?.MembershipSource + ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); + + if (source != null) + { + _logger.LogInformation("MemberRemoved via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", + source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); + + await turnContext.SendActivityAsync( + MessageFactory.Text($"👋 Member removed (source **{source.SourceType}**, {source.MembershipType})."), + cancellationToken); + } + + await base.OnTeamsMembersRemovedAsync(membersRemoved, teamInfo, turnContext, cancellationToken); + } +``` + +These Bot Framework endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. + +--- + +## Validate user access for membership updates + +When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the ```doesUserHaveAccess``` API to determine whether the user still has access to the shared channel. + +```HTTP +GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') +``` + +See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http) to learn more about user accesses and relevant permissions. + +## Handle bulk membership changes + +If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. This feature reduces notification volume and improves performance. + +### Use sharedWithTeams subscription for bulk membership changes + +### [Graph](#tab/graph-bulk) + +To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: + +```HTTP +`/teams/{team-id}/channels/{channel-id}/sharedWithTeams` +``` + +The sharedWithTeams subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the /allMembers API after receiving a "shared with" or "unshared from" team notification. + +> [!NOTE] +> To support membership updates in shared channels, apps using resource-specific consent (RSC) must request extended permissions. +> These permissions let the app: +> +> * Access membership data (both direct and indirect members). +> * Receive and respond to membership change notifications. + +### [Bot Framework](#tab/botframework-bulk) + +When a shared channel is added to another team, the Bot Framework might receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. + +```csharp + protected override async Task OnConversationUpdateActivityAsync( + ITurnContext turnContext, + CancellationToken cancellationToken) + { + // Always present on Teams activities + var tcd = turnContext.Activity.GetChannelData(); + var eventType = tcd?.EventType?.ToLowerInvariant(); + + // Read extended shared-channel shape (safe even if fields are absent) + var extended = turnContext.Activity.GetChannelData(); + + // Also keep a raw JObject for logging / future-proof access + var raw = turnContext.Activity.ChannelData as JObject + ?? (turnContext.Activity.ChannelData != null + ? JObject.FromObject(turnContext.Activity.ChannelData) + : new JObject()); + + // Helpful baseline log + _logger.LogInformation("ConversationUpdate eventType={EventType}, channelId={ChannelId}, teamId={TeamId}", + eventType, tcd?.Channel?.Id, tcd?.Team?.Id); + + switch (eventType) + { + case "channelshared": + { + var hostTeam = extended?.Team; // The channel's host team + var sharedWith = extended?.SharedWithTeams ?? new List(); + + _logger.LogInformation("ChannelShared: hostTeam={HostTeamId}, sharedWithCount={Count}", + hostTeam?.Id, sharedWith.Count); + + foreach (var team in sharedWith) + { + _logger.LogInformation("SharedWithTeam: id={Id}, name={Name}, aadGroupId={AadGroupId}, tenantId={TenantId}", + team.Id, team.Name, team.AadGroupId, team.TenantId); + } + + // Optional: surface a quick confirmation in-channel + await turnContext.SendActivityAsync( + MessageFactory.Text($"✅ Channel shared with {sharedWith.Count} team(s)."), + cancellationToken); + break; + } + + case "channelunshared": + { + var unsharedFrom = extended?.UnsharedFromTeams ?? new List(); + + _logger.LogInformation("ChannelUnshared: unsharedFromCount={Count}", unsharedFrom.Count); + + foreach (var team in unsharedFrom) + { + _logger.LogInformation("UnsharedFromTeam: id={Id}, name={Name}, aadGroupId={AadGroupId}, tenantId={TenantId}", + team.Id, team.Name, team.AadGroupId, team.TenantId); + } + + await turnContext.SendActivityAsync( + MessageFactory.Text($"❎ Channel unshared from {unsharedFrom.Count} team(s)."), + cancellationToken); + break; + } + + default: + // No-op; continue normal routing + break; + } + + await base.OnConversationUpdateActivityAsync(turnContext, cancellationToken); + } +``` + +--- + +## Understand app permissions in shared channels + +You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. + +> [!NOTE] +> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. + +## Verify if your app is added to a channel + +For bots using the Bot Framework SDK, if your bot receives a channelMemberAdded event in a conversationUpdate activity for itself, it indicates that the app is added to the channel. +Begin your channel-specific logic at that point, for example, send a welcome message, fetch the roster, configure tabs, or schedule jobs as needed. Bot events start flowing only after the app is added to the channel + +There’s no direct API to check whether your app is added to a channel. + +> [!NOTE] +> +> * Use ```GET /teams/{team-id}/installedApps```, to list installed apps at the team level. +> * Channel level InstalledApps aren't listed. +> * Avoid using team-level installations to determine which apps are in a channel. + +## Authenticate external users to access app content in SharePoint + +You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. + +### [Tabs](#tab/tabs) + +Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ```channel.ownerTenantId``` for JSv2 or host tenant ID for JSv1 received under ```getContext``` call. + +### [Bots](#tab/bots) + +For any event payload or action payload received for a bot, use Get hostTenant ID, from ```turnContext.activity.conversation.tenantId```. + +--- + +Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the shared channel. + +## Identify guest users (B2B guests) in private channels + +You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. + +For guests, “roles” = “guest” + +## Access sharepoint data in shared and private channels + +If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. + +Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). + +## Test your app across channel types + +Before publishing updates, validate your app behaves correctly in real situations behaves across all channel types. + +### Standard channel + +Confirm that the existing functionality remains intact after your changes. Ensure tabs, bots and messaging extensions continue to work as expected. + +### Private channel + +Try this setup: Create a private channel P in Team A with atleast two members (one owner, one member). + +Test steps: + +1. Add the app to Team A then add it to private channel P. +2. Verify that your tab loads correctly in the private channel. +3. Test bot responses for different user types: + * In-tenant member + * Guest user or external user +4. If your app lists members or assigns tasks, confirm it only uses channel members and not the complete team. +5. Add a new member to the private channel and check: + * Whether your app receives a membership change event + * Whether your membership API reflects the new member. + +### Shared channel (same tenant) + +Try this setup: Create shared channel X in Team A, then share it with Team B (requires owner permissions). + +Test steps: + +1. Add the app to Team A (host team), then to Channel X. +2. Validate that members from Team B. + * Can see the tab + * Receive bot responses +3. Unshare the channel from Team B and confirm: + * Your bot receives a ``channelUnshared`` event + * Membership updates are handled correctly + +### Shared channel (external tenant) + +Try this setup: Use two tenants or collaborate with a colleague from another organization via Teams Connect. + +Test steps: + +1. Have an external user send a message to your bot and confirm that is responds. + * The bot should receive the message, provided it is added to the appropriate scope (personal chat, group chat, or channel). +2. Have the external user trigger a task module or tab interaction and verify that the authentication succeeds. + * If using SSO, ensure ``getAuthToken`` handles the user's home tenant ID correctly. +3. Attempt to send a direct message from your bot to the external user: + * This will fail if the user is outside your tenant + * Confirm that in-channel communication still works. + +Testing across these scenarios will help you spot any issues with functionality, permissions, and user experience. + +## Best practices for supporting all channels + +Follow these best practices to ensure your app works reliably across all channel types: + +* Always retrieve the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. + +* Adjust app functionality and access controls based on user roles (owner, member, guest, external). Limit sensitive actions to owners or internal users, and offer limited features to guests or external participants. + +* Control data access and sharing based on channel membership and permissions. Never include private-channel data in broader reports or public channels unless explicitly authorized. + +* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when they access files. + +* Update help text and user guides to explain how your app behaves in different channel types, including any limitations for guests or external users. + +* Cache large member lists and use change notifications to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. + +* Test your app across different user roles and channel configurations including owners, members, guests, and external users to confirm it behaves correctly and enforces appropriate permissions. + +* Review Microsoft Teams documentation and changelogs to keep your app aligned with the latest updates to APIs, permissions, and channel configurations. + +## Code sample + +|Sample name|Description|Node.js| +|-------------|-------------|------| +||| + +## Frequently asked questions + +
+Why isn’t the app visible when trying to add it to a channel? + +If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as ```"supportsChannelFeatures": tier1```, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. + +
+  +
+
+Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? + +You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ```ChannelMember.Read.Group``` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ```channelMemberAdded``` event to confirm it has been successfully added to the channel. + +
+  +
+
+Why does the channel roster appear incomplete, showing only owners or missing users? + +If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ```/channels/{id}/allMembers``` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. + +
+  +
+
+Why does file access fail for some users even though they're part of the channel? + +This failure can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the invite API to give access to specific users or groups. + +
+  +
+
+Why are external users experiencing authentication issues in tabs or task modules? + +Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ```context.user.tenant.id``` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. + +
+  +
+
+How do I know my app was added to a channel? + +This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there's no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. + +
+  +
+
+Why is my app failing to create message change notifications in shared or private channels? + +Message change notifications might fail in shared or private channels because subscriptions to ```/channels/{id}/messages``` are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. + +
+  +
+
+Why do file links still fail for external users even after the app is added to the channel? + +This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. + +## See also + +* [Build tabs for Teams](../../tabs/what-are-tabs.md) +* [App manifest schema for Teams](../../resources/schema/manifest-schema.md) +* [Shared channels in Microsoft Teams](/microsoftteams/shared-channels) +* [Channel resource type](/graph/api/resources/channel) +* [Retention policy for Teams locations](/microsoft-365/compliance/create-retention-policies) +* [Use guest access and external access to collaborate with people outside your organization](/microsoftteams/communicate-with-users-from-other-organizations) +* [Manage external meetings and chat with people and organizations using Microsoft identities](/microsoftteams/trusted-organizations-external-meetings-chat?tabs=organization-settings) From 4cff965359df98c820ee15dbf14c2ebc8b74db3e Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 18 Sep 2025 21:10:50 +0530 Subject: [PATCH 050/109] Update TOC.yml --- msteams-platform/TOC.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/TOC.yml b/msteams-platform/TOC.yml index 3fd7f926d66..e902ad6748b 100644 --- a/msteams-platform/TOC.yml +++ b/msteams-platform/TOC.yml @@ -689,7 +689,7 @@ href: get-started/b2c-apps.md displayName: Teams meeting, Teams call, Teams meeting and call for external apps, external apps - name: Apps for Shared and Private Channels - href: msteams-platform/build-apps-for-shared-private-channels.md + href: build-apps-for-shared-private-channels.md displayName: shared channels, private channels - name: Build webhooks and connectors items: From bc3a3e3f32220f87f6b72944831d8718c1eabf0d Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 19 Sep 2025 12:48:10 +0530 Subject: [PATCH 051/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 1906081b715..41c1996135d 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -51,7 +51,7 @@ Understanding the difference between Microsoft Teams channel types is essential. * Aggregate or cross-post data across channels only when necessary. Keep data scoped to the channel unless clearly defined to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. -![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) | +![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](./assets/images/app-fundamentals/shared-channels-teams.png) | > [!NOTE] > @@ -399,9 +399,9 @@ Confirm that the existing functionality remains intact after your changes. Ensur ### Private channel -Try this setup: Create a private channel P in Team A with atleast two members (one owner, one member). +Create a private channel P in Team A with atleast two members (one owner, one member). -Test steps: +Perform the following steps to validate: 1. Add the app to Team A then add it to private channel P. 2. Verify that your tab loads correctly in the private channel. @@ -413,11 +413,11 @@ Test steps: * Whether your app receives a membership change event * Whether your membership API reflects the new member. -### Shared channel (same tenant) +### [Shared channel (same tenant)](#tab/sharedchannel) -Try this setup: Create shared channel X in Team A, then share it with Team B (requires owner permissions). +Create shared channel X in Team A, then share it with Team B (requires owner permissions). -Test steps: +Perform the following steps to validate: 1. Add the app to Team A (host team), then to Channel X. 2. Validate that members from Team B. @@ -427,11 +427,11 @@ Test steps: * Your bot receives a ``channelUnshared`` event * Membership updates are handled correctly -### Shared channel (external tenant) +### [Shared channel (external tenant)](#tab/sharedchannel-externaltenant) -Try this setup: Use two tenants or collaborate with a colleague from another organization via Teams Connect. +Use two tenants or collaborate with a colleague from another organization via Teams Connect. -Test steps: +Perform the following steps to validate: 1. Have an external user send a message to your bot and confirm that is responds. * The bot should receive the message, provided it is added to the appropriate scope (personal chat, group chat, or channel). @@ -440,6 +440,8 @@ Test steps: 3. Attempt to send a direct message from your bot to the external user: * This will fail if the user is outside your tenant * Confirm that in-channel communication still works. + +--- Testing across these scenarios will help you spot any issues with functionality, permissions, and user experience. From 26337240163757ef0267c9aebfcaf342f25879df Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 19 Sep 2025 13:00:31 +0530 Subject: [PATCH 052/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 41c1996135d..7f21aba6eac 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -70,7 +70,7 @@ You can enable app support for shared and private channels based on whether your If it doesn't follow the preceding parameters, perform the following steps to enable app support in shared and private channels: -1. Add ```"supportsChannelFeatures": "tier1"``` to your app manifest to enable support for shared and private channels. +1. Add ``"supportsChannelFeatures": "tier1"`` to your app manifest to enable support for shared and private channels. 2. To verify expected behavior, test your app in standard, private, and shared channels. If your app uses any of the preceding features, see the following articles, for more information: From 392d43d2f500e3c8ec861dc35db9b8e641c6fdf3 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 19 Sep 2025 13:11:37 +0530 Subject: [PATCH 053/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 7f21aba6eac..060ffff1ae9 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -24,7 +24,7 @@ When building or integrating apps with Microsoft Teams, understand how different ## Teams channels – capabilities comparison -Let's see how Teams channels type differ in their capabilities. +Following is a detailed table outlining the capabilities of different Teams channel types. | **Model** | **Channel Capability** | **Standard Channel** | **Other Channels** | |----------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------------------| @@ -172,7 +172,7 @@ To receive both direct and indirect member update notifications, you must includ This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) -### [Bot Framework](#tab/bot-framework) +### [Microsoft 365 Agents SDK](#tab/microsoft365agentssdk1) When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. @@ -226,7 +226,7 @@ Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsy } ``` -These Bot Framework endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. +These Microsoft 365 Agents SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. --- @@ -263,9 +263,9 @@ The sharedWithTeams subscription sends a single notification when a channel is s > * Access membership data (both direct and indirect members). > * Receive and respond to membership change notifications. -### [Bot Framework](#tab/botframework-bulk) +### [Microsoft 365 Agents SDK](#tab/microsoft365agentssdk-bulk) -When a shared channel is added to another team, the Bot Framework might receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. +When a shared channel is added to another team, the Microsoft 365 Agents SDK might receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. ```csharp protected override async Task OnConversationUpdateActivityAsync( @@ -350,14 +350,14 @@ You can collaborate with external members outside of your organization using sha ## Verify if your app is added to a channel -For bots using the Bot Framework SDK, if your bot receives a channelMemberAdded event in a conversationUpdate activity for itself, it indicates that the app is added to the channel. +For bots using the Microsoft 365 Agents SDK, if your bot receives a channelMemberAdded event in a conversationUpdate activity for itself, it indicates that the app is added to the channel. Begin your channel-specific logic at that point, for example, send a welcome message, fetch the roster, configure tabs, or schedule jobs as needed. Bot events start flowing only after the app is added to the channel There’s no direct API to check whether your app is added to a channel. > [!NOTE] > -> * Use ```GET /teams/{team-id}/installedApps```, to list installed apps at the team level. +> * Use ``GET /teams/{team-id}/installedApps``, to list installed apps at the team level. > * Channel level InstalledApps aren't listed. > * Avoid using team-level installations to determine which apps are in a channel. @@ -367,11 +367,11 @@ You need to complete this step when your app stores content in the SharePoint si ### [Tabs](#tab/tabs) -Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ```channel.ownerTenantId``` for JSv2 or host tenant ID for JSv1 received under ```getContext``` call. +Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ``channel.ownerTenantId`` for JSv2 or host tenant ID for JSv1 received under ``getContext`` call. ### [Bots](#tab/bots) -For any event payload or action payload received for a bot, use Get hostTenant ID, from ```turnContext.activity.conversation.tenantId```. +For any event payload or action payload received for a bot, use Get hostTenant ID, from ``turnContext.activity.conversation.tenantId``. --- @@ -413,6 +413,8 @@ Perform the following steps to validate: * Whether your app receives a membership change event * Whether your membership API reflects the new member. +### Shared Channel + ### [Shared channel (same tenant)](#tab/sharedchannel) Create shared channel X in Team A, then share it with Team B (requires owner permissions). @@ -476,7 +478,7 @@ Follow these best practices to ensure your app works reliably across all channel
Why isn’t the app visible when trying to add it to a channel? -If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as ```"supportsChannelFeatures": tier1```, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as ``"supportsChannelFeatures": tier1``, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
  @@ -484,7 +486,7 @@ If an app isn’t visible when trying to add it to a channel, there are a few li
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ```ChannelMember.Read.Group``` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ```channelMemberAdded``` event to confirm it has been successfully added to the channel. +You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it has been successfully added to the channel.
  @@ -492,7 +494,7 @@ You’ll see a 403 error saying "app not enabled in this channel" if the app is
Why does the channel roster appear incomplete, showing only owners or missing users? -If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ```/channels/{id}/allMembers``` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
  @@ -508,7 +510,7 @@ This failure can happen if the app is using the team’s main SharePoint site in
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ```context.user.tenant.id``` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. +Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken.
  @@ -524,7 +526,7 @@ This issue might occur if the app is expecting a centralized list of installed a
Why is my app failing to create message change notifications in shared or private channels? -Message change notifications might fail in shared or private channels because subscriptions to ```/channels/{id}/messages``` are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. +Message change notifications might fail in shared or private channels because subscriptions to ``/channels/{id}/messages`` are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel.
  From c5e399f633ee04e7e6d06271b347e961925827d0 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 19 Sep 2025 13:19:44 +0530 Subject: [PATCH 054/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 060ffff1ae9..82cbc2e421c 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -413,7 +413,7 @@ Perform the following steps to validate: * Whether your app receives a membership change event * Whether your membership API reflects the new member. -### Shared Channel +### Shared channel ### [Shared channel (same tenant)](#tab/sharedchannel) From 84c143b952be42e81b25548c8ba2e1fb4be06099 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 24 Sep 2025 14:08:29 +0530 Subject: [PATCH 055/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 82cbc2e421c..d67bb63fb41 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -55,7 +55,7 @@ Understanding the difference between Microsoft Teams channel types is essential. > [!NOTE] > -> Don't depend on channel type to determine behavior. Avoid making make any logic decisions based on the channel type in your code. Instead, check for the capabilities your app needs (for example, membership boundaries, storage location, external access) and always use APIs and patterns that work across all channel types. +> Don't depend on channel type to determine behavior. Avoid making any changes to your code based on channel type. Instead, check for the capabilities your app needs (for example, membership boundaries, storage location, external access) and always use APIs and patterns that work across all channel types. Use the following guidance to enable app support for shared and private channels. @@ -385,10 +385,69 @@ For guests, “roles” = “guest” ## Access sharepoint data in shared and private channels -If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. +If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). +### Resolve storage correctly for channel files + +To access a channel’s SharePoint files root, use the following API: + +`GET /teams/{teamId}/channels/{channelId}/filesFolder` + +This returns a DriveItem object for that channel's files root. + +Use the following properties for all subsequent file operations: + +* `parentReference.driveId`: The SharePoint drive ID for the channel’s site. +* `itemId`: The folder ID for the channel’s root. + +Following is the expected drive behavior of the channels: + +* Standard channels use the team site’s driveId. +* Other channels use a separate driveId for their individual sites. + +> [!NOTE] +> +> Always store and reuse the `driveId` and `itemId` returned by the API. +> Avoid hardcoding library names or URLs based on assumptions about the team site, as the team site location can change. +> Use the preceding API for all channel types. + +### Handle external or guest users’ access to files + +#### [External users](#tab/external users) + +External users remain in their home tenant while accessing the host channel’s SharePoint site. To enable access: + +* Configure cross-tenant access on both sides. +* Ensure your app is multi-tenant and has received consent in the host tenant. + +#### [Guest users](#tab/guest users) + +The channel’s SharePoint site automatically grants access to all channel members, including tenant guests. + +Consider the following steps: + +* Avoid using Organization-wide sharing links they typically exclude external users. +* Use specific-people sharing, or rely on membership-based permissions. +* Check tenant or site policies, as they may block anonymous or organization-wide links. + +To grant access to specific users/groups , use the following API: + +`POST /drives/{driveId}/items/{itemId}/invite` + +--- + +### Authenticate external users in tabs or task modules + +When your tab or task module needs to access SharePoint resources in the channel’s home tenant, perform the following steps: + +1. Detect external users +Use getContext() to retrieve channel context. Compare `user.tenant.id` with `channel.ownerTenantId or channel.hostTenantId`. If they differ, the user is external. + +2. Request token from home tenant +Call getAuthToken() with the external user's tenant ID (`user.tenant.id` or `tid`) to ensure the token is issued from their home tenant. + ## Test your app across channel types Before publishing updates, validate your app behaves correctly in real situations behaves across all channel types. From 2ef45b68e735775b7132c836bbaae33fb74ae786 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 24 Sep 2025 14:33:19 +0530 Subject: [PATCH 056/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index d67bb63fb41..6d2410ba282 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -379,10 +379,18 @@ Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to ## Identify guest users (B2B guests) in private channels -You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. +You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. For guests, “roles” = “guest” +To accurately retrieve the all guest users in Private channel use the following``allMembers`` API: + +```HTTP +GET /teams/{team-id}/channels/{channel-id}/allMembers`` +``` + +This API works across standard and other channels and and is recommended for reliably indentifying guest members. + ## Access sharepoint data in shared and private channels If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. @@ -393,7 +401,9 @@ Use the Graph API to access the document library of the SPO site linked to a sha To access a channel’s SharePoint files root, use the following API: -`GET /teams/{teamId}/channels/{channelId}/filesFolder` +```HTTP +GET /teams/{teamId}/channels/{channelId}/filesFolder +``` This returns a DriveItem object for that channel's files root. @@ -434,7 +444,9 @@ Consider the following steps: To grant access to specific users/groups , use the following API: -`POST /drives/{driveId}/items/{itemId}/invite` +```HTTP +POST /drives/{driveId}/items/{itemId}/invite` +``` --- From 0e5bffdcb0db7001f54ce35e964a789c9d9c412e Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 24 Sep 2025 15:10:06 +0530 Subject: [PATCH 057/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 6d2410ba282..656e65c0e48 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -399,7 +399,7 @@ Use the Graph API to access the document library of the SPO site linked to a sha ### Resolve storage correctly for channel files -To access a channel’s SharePoint files root, use the following API: +To access a channel’s sharepoint files root, use the following API: ```HTTP GET /teams/{teamId}/channels/{channelId}/filesFolder @@ -409,7 +409,7 @@ This returns a DriveItem object for that channel's files root. Use the following properties for all subsequent file operations: -* `parentReference.driveId`: The SharePoint drive ID for the channel’s site. +* `parentReference.driveId`: The sharepoint drive ID for the channel’s site. * `itemId`: The folder ID for the channel’s root. Following is the expected drive behavior of the channels: @@ -427,14 +427,14 @@ Following is the expected drive behavior of the channels: #### [External users](#tab/external users) -External users remain in their home tenant while accessing the host channel’s SharePoint site. To enable access: +External users remain in their home tenant while accessing the host channel’s sharepoint site. To enable access: * Configure cross-tenant access on both sides. * Ensure your app is multi-tenant and has received consent in the host tenant. #### [Guest users](#tab/guest users) -The channel’s SharePoint site automatically grants access to all channel members, including tenant guests. +The channel’s sharepoint site automatically grants access to all channel members, including tenant guests. Consider the following steps: @@ -452,7 +452,7 @@ POST /drives/{driveId}/items/{itemId}/invite` ### Authenticate external users in tabs or task modules -When your tab or task module needs to access SharePoint resources in the channel’s home tenant, perform the following steps: +When your tab or task module needs to access sharepoint resources in the channel’s home tenant, perform the following steps: 1. Detect external users Use getContext() to retrieve channel context. Compare `user.tenant.id` with `channel.ownerTenantId or channel.hostTenantId`. If they differ, the user is external. From 14abe9946029dc880fd11d63f89388f370bb747a Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 24 Sep 2025 15:56:43 +0530 Subject: [PATCH 058/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 656e65c0e48..e05eb4bd225 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -423,7 +423,7 @@ Following is the expected drive behavior of the channels: > Avoid hardcoding library names or URLs based on assumptions about the team site, as the team site location can change. > Use the preceding API for all channel types. -### Handle external or guest users’ access to files +### Manage file access for external or guest users #### [External users](#tab/external users) From b3111836bc5b740efd1841bb9626419ff96acd19 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Thu, 25 Sep 2025 12:58:43 +0530 Subject: [PATCH 059/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index e05eb4bd225..4da2de5f0c0 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -26,18 +26,18 @@ When building or integrating apps with Microsoft Teams, understand how different Following is a detailed table outlining the capabilities of different Teams channel types. -| **Model** | **Channel Capability** | **Standard Channel** | **Other Channels** | -|----------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------------------| -| **Membership** | Can add people to the channel without adding to the host team | :x: | Supported (Shared channels) | -| | Channel membership can be limited to a subset of the host team | :x: | Supported | -| | Channel can be shared with other teams to inherit members | :x: | Supported (Shared channels) | -| | Channel can be shared directly with its parent team | N/A | Supported (Shared channels) | -| | External users can participate in the channel | :white_check_mark: (B2B collab users) | :white_check_mark: (B2B Direct Connect in Shared channels, B2B collab users in Private channels) | -| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | -| **Storage** | Each channel has a dedicated SharePoint site | :x: (Inherits team site) | :white_check_mark: | -| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: | -| | App installed to host team automatically available in channel | :white_check_mark: | :x: | -| | App must be added to each channel | :x: | :white_check_mark: | +| **Model** | **Channel Capability** | **Standard Channel** | **Shared Channels**| **Private channels** | +|----------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------------------|-----------------------| +| **Membership** | Can add people to the channel without adding to the host team | :x: | :white_check_mark: |:x: +| | Channel membership can be limited to a subset of the host team | :x: | :white_check_mark: | :white_check_mark: | +| | Channel can be shared with other teams to inherit members | :x: | :white_check_mark:| :x: | +| | Channel can be shared directly with its parent team | N/A | :white_check_mark: | :x: | +| | External users can participate in the channel | :white_check_mark: (B2B collab users) | :white_check_mark: (B2B Direct Connect in Shared channels) |:white_check_mark: (B2B Direct Connect in Shared channels, B2B collab users in Private channels)| +| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **Storage** | Each channel has a dedicated SharePoint site | :x: (Inherits team site) | :white_check_mark: |:white_check_mark: | +| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: |:white_check_mark: +| | App installed to host team automatically available in channel | :white_check_mark: | :x: | :x: +| | App must be added to each channel | :x: |:white_check_mark:| :white_check_mark: | ## Understand channel differences that impact app functionality From 2ba252fc93e892455cc8e22658a9d73f1ae66aba Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Tue, 30 Sep 2025 22:51:17 +0530 Subject: [PATCH 060/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 417 ++++++++++-------- 1 file changed, 226 insertions(+), 191 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 4da2de5f0c0..803aaec3cce 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -10,70 +10,72 @@ ms.date: 04/09/2025 # Microsoft Teams connect shared and private channels -Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. +Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. You can experience multiple benefits, depending on your channel: -## Understand channel models in Microsoft Teams +* Shared channels: Allow seamless communication with internal or external partners, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing -When building or integrating apps with Microsoft Teams, understand how different channel types affect visibility, membership, and data storage. +* Private channels: Provide secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -* **Standard channels:** Accessible to every team member by default. The standard channels support team-wide collaboration and are suitable for scenarios where bots, or tabs, need to be accessible to every team member. Files shared in standard channels are stored in the team’s SharePoint site. +## Understand channels for app integration -* **Private channels:** Visible only to a selected subset of team members. The private channels are suited for scenarios that require tighter control over membership and data, such as limiting bots, connectors, or stored files to only members of the private channel. Files shared in private channels are stored in a dedicated SharePoint site, separate from the team’s default site. +When building or integrating apps with Microsoft Teams, understanding channel types is crucial, as they determine app visibility, user access, and data storage behavior as shown: -* **Shared channels:** Designed for cross-team and cross-organization collaboration. They support scenarios where app components such as bots and tabs, need to interact with users who aren’t part of the host team, without requiring those users to join the team. Files are managed in the shared channel's SharePoint site. +| Channels | Access | Collaboration | File storage location | +|----------|----------------------------------|--------------------------------------------------------------------------------|-------------------------------------| +| Standard | All team members by default | Ideal for team-wide collaboration where bots or tabs should be available to everyone | Team’s SharePoint site | +| Private | Only to selected team members | Suitable for scenarios requiring restricted access to bots, connectors, or files | Private channel’s SharePoint site | +| Shared | Cross-team and cross-organization | Enables interaction with users outside the host team without requiring them to join the team | Shared channel’s SharePoint site | -## Teams channels – capabilities comparison +## Capabilities across channels -Following is a detailed table outlining the capabilities of different Teams channel types. +Here’s an outline of the different channels and their capabilities, across various parameters: -| **Model** | **Channel Capability** | **Standard Channel** | **Shared Channels**| **Private channels** | -|----------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------------------|-----------------------| -| **Membership** | Can add people to the channel without adding to the host team | :x: | :white_check_mark: |:x: -| | Channel membership can be limited to a subset of the host team | :x: | :white_check_mark: | :white_check_mark: | -| | Channel can be shared with other teams to inherit members | :x: | :white_check_mark:| :x: | -| | Channel can be shared directly with its parent team | N/A | :white_check_mark: | :x: | -| | External users can participate in the channel | :white_check_mark: (B2B collab users) | :white_check_mark: (B2B Direct Connect in Shared channels) |:white_check_mark: (B2B Direct Connect in Shared channels, B2B collab users in Private channels)| -| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| **Storage** | Each channel has a dedicated SharePoint site | :x: (Inherits team site) | :white_check_mark: |:white_check_mark: | -| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: |:white_check_mark: -| | App installed to host team automatically available in channel | :white_check_mark: | :x: | :x: -| | App must be added to each channel | :x: |:white_check_mark:| :white_check_mark: | +| Model | Channel Capabilities | Standard Channel | Shared Channels | Private Channels | +|-------------|----------------------------------------------------------------------------------------|-----------------------------------|----------------------------------|----------------------------------| +| Membership | Can add people to the channel without adding to the host team | No | Yes | No | +| | Channel membership can be limited to a subset of the host team | No | Yes | Yes | +| | Channel can be shared with other teams to inherit members from the team | No | Yes | No | +| | Channel can be shared directly with its parent team to inherit members from parent team | N/A | Yes | No | +| | External users can participate in the channel | Yes (B2B collab users) | Yes (B2B Direct connect) | Yes (B2B collab users) | +| | Channel is hosted under a host team | Yes | Yes | | +| Storage | Each channel has a dedicated SharePoint site | No (Inherits team site) | Yes | Yes | +| App Model | App must be installed in the host team | Yes | Yes | Yes | +| | App installed to host team automatically available in channel | Yes | No | No | +| | App must be added to each channel | No | Yes | Yes | -## Understand channel differences that impact app functionality +## Understand how different channels impact app functionality Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. -* In private and shared channels, not everyone in the team has access. Only members who are specifically added to the channel can participate in these channels. If your bot targets "everyone," it may violate privacy or miss external members. Always use channel-specific membership APIs to determine the correct members. +* **Access limits in private and shared channels:** Only members who are specifically added to the channel can participate in these channels. If your bot targets ‘everyone’, it may violate privacy or miss external members. Use channel-specific membership APIs to determine the correct members. -* Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Always validate user roles and tenant IDs before granting permissions or executing actions. +* **Different user types:** Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant IDs before granting permissions. -* Private and shared channels have their own SharePoint sites. If your app targets the wrong site, it may encounter missing files or unauthorized access errors. Always resolve the correct site URL for each channel. +* **SharePoint sites:** Private and shared channels have their own SharePoint sites. Always use the correct site URL for each channel to avoid missing files or unauthorized access errors. -* Aggregate or cross-post data across channels only when necessary. Keep data scoped to the channel unless clearly defined to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. +* **Data aggregation:** Aggregate or cross-post data across channels only when necessary. Keep data scoped to the channel unless clearly defined to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. ![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](./assets/images/app-fundamentals/shared-channels-teams.png) | -> [!NOTE] +> [!IMPORTANT] > -> Don't depend on channel type to determine behavior. Avoid making any changes to your code based on channel type. Instead, check for the capabilities your app needs (for example, membership boundaries, storage location, external access) and always use APIs and patterns that work across all channel types. - -Use the following guidance to enable app support for shared and private channels. +> Check your app’s capability (membership boundaries, storage location, external access) and don’t make any code changes, based on channel type. -## Enable app support for shared and private channels +## Enable your app for shared and private channels -You can enable app support for shared and private channels based on whether your app is: +Enabling app support in shared and private channels depends on whether your app: -* Using channel or team membership to determine message delivery, task assignment, or permissions -* Accessing or managing files stored in Teams or SharePoint -* Combining or sharing data across multiple channels or teams -* Customizing the experience based on whether users are internal, guests, or external participants +* Uses channel or team membership to determine message delivery, task assignment, or permissions +* Accesses or manages files stored in Teams or SharePoint +* Combines or shares data across multiple channels or teams +* Customizes experience based on whether users (internal, guests, or external participants) -If it doesn't follow the preceding parameters, perform the following steps to enable app support in shared and private channels: +In case your app, doesn’t support any of the listed parameters, then perform the following steps to enable app support in shared and private channels: 1. Add ``"supportsChannelFeatures": "tier1"`` to your app manifest to enable support for shared and private channels. 2. To verify expected behavior, test your app in standard, private, and shared channels. -If your app uses any of the preceding features, see the following articles, for more information: +See the following articles, for more information: * [Manage channel membership](#manage-channel-membership) * [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) @@ -86,6 +88,8 @@ If your app uses any of the preceding features, see the following articles, for ### Get context for shared and private channels +Microsoft Teams now supports enhanced bot and tab capabilities in shared and private channels. + When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. For more information to enable your tab, see: @@ -95,65 +99,74 @@ For more information to enable your tab, see: ## Manage channel membership -This section explains how to view and manage the membership of Microsoft Teams Channels. - -### Retrieve full channel membership - -To accurately retrieve the all members of any Microsoft Teams channel Standard, Private, or Shared use the ``allMembers`` API: +Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. Get the list of all members in a channel. ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers`` ``` -This API works across all channel types and returns the actual members of a channel, rather than the broader team members. For shared channels, it also includes indirect members, such as users from other teams who have been granted access. - -### Understand shared channel membership +### Identify members -Shared channels support three types of membership direct, indirect and external allowing flexible collaboration across teams. +* Direct members: Users who are added directly to the channel, including users from other tenants (cross-tenants). +* Indirect members: Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. +* External members: Guest users, who are not part of your organization but have been granted access to a shared channel through guest access or cross-tenant collaboration. -#### Direct members +Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel, as shown in the following table. -Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. +| Member Type | Annotation Present? | Description | +|-----------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Direct Member | Yes | The user is added directly to the shared channel. | +| Indirect Member | Yes | The user accesses the shared channel through another team. The `@microsoft.graph.originalSourceMembershipUrl` property includes a URL that points to the source team and indicates indirect membership. | -You can retrieve the list of direct members in a shared channel by using the ``hostTeamGroupID`` obtained from ``getContext`` and calling the appropriate API. This method returns all users who have been explicitly added to the shared channel, including both internal and external participants. +> [!Note] +> You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `List allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists; either directly or indirectly. -To retrieve direct members of a shared channel: +## Manage indirect membership across channels -1. Call the following API: +You can manage indirect membership in channels using the following Microsoft Graph APIs: - ```HTTP - GET /teams/{host-team-group-id}/channels/{channel-id}/members - ``` +* Use `allMembers` API to retrieve all users who are members of a specific channel. -#### Indirect members +```HTTP +GET /teams/{team-id}/channels/{channel-id}/allMembers +``` -Indirect members are users who can access shared channel through their membership in a team that the channel is shared with. These users are not added directly to the channel but are eligible to participate because their team has been granted access. +* Use `doesUserHaveAccess API` to determine whether the user is removed from the channel and can view all user accesses and relevant permissions. -To retrieve indirect members of a shared channel: +```HTTP +GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') +``` -1. Call the following API to identify which teams the channel is shared with: +* Use sharedWithTeams API to list all teams a channel is shared with. ```HTTP -GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams +GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams ``` -2. Call the following API for each team returned: +* Use the allowedMembers API to retrieve users from a shared team who can access a shared channel. ```HTTP -GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{shared-team-id}/allowedMembers +GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/allowedMembers ``` +>[!Note] +>`allowedMembers` API returns only newly associated users and doesn't apply to unshared events. + -#### External members -An external member are users who is not part of your organization but has been granted access to a shared channel through guest access or cross-tenant collaboration. -To retrieve external members of a shared channel: +#### Direct members + +Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. + +You can retrieve the list of direct members in a shared channel by using the ``hostTeamGroupID`` obtained from ``getContext`` and calling the appropriate API. This method returns all users who have been explicitly added to the shared channel, including both internal and external participants. + +To retrieve direct members of a shared channel: 1. Call the following API: -```HTTP -GET /teams/{host-team-group-id}/channels/{channel-id}/members -``` + ```HTTP + GET /teams/{host-team-group-id}/channels/{channel-id}/members + ``` ## Get app notifications for direct and indirect membership changes @@ -167,125 +180,102 @@ Apps installed in shared channels receive notifications when users are added to To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). ```HTTP -`/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` +/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` ``` This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) -### [Microsoft 365 Agents SDK](#tab/microsoft365agentssdk1) +### [Bots](#tab/bots) -When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. +Microsoft Teams now supports bot notifications for both direct and indirect members. This enhancement expands its Bot Framework SDK to support notifications for indirect members in shared channels. This update improves visibility into membership changes across teams, enabling bots to more effectively track user access in collaborative environments. It builds on the existing capability for bots to subscribe to `conversationUpdate` events in channels. -```csharp - protected override async Task OnTeamsMembersAddedAsync( - IList membersAdded, - TeamInfo teamInfo, - ITurnContext turnContext, - CancellationToken cancellationToken) - { - var extended = turnContext.Activity.GetChannelData(); - var source = extended?.MembershipSource - ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); +### Manage member added and removed events - if (source != null) - { - _logger.LogInformation("MemberAdded via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", - source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); +A member added event is sent to your bot in the following scenarios: - await turnContext.SendActivityAsync( - MessageFactory.Text($"👤 Member added via **{source.SourceType}** ({source.MembershipType})."), - cancellationToken); - } +1. When the bot, itself, is installed and added to a conversation +2. When a user is added to a conversation where the bot is installed - await base.OnTeamsMembersAddedAsync(membersAdded, teamInfo, turnContext, cancellationToken); -``` +A member removed event is sent to your bot in the following scenarios: -Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsync``` method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. +1. When the bot, itself, is uninstalled and removed from a conversation. +2. When a user is removed from a conversation where the bot is installed. -```csharp - protected override async Task OnTeamsMembersRemovedAsync( - IList membersRemoved, - TeamInfo teamInfo, - ITurnContext turnContext, - CancellationToken cancellationToken) - { - var source = turnContext.Activity.GetChannelData()?.MembershipSource - ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); +For more information, see [Conversation events - Teams | Microsoft Learn]() +The following Bot Framework SDK examples apply to both direct and indirect member add and remove events. To receive transitive member events, ensure your bot is set up with all the prerequisites. - if (source != null) - { - _logger.LogInformation("MemberRemoved via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", - source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); +When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. - await turnContext.SendActivityAsync( - MessageFactory.Text($"👋 Member removed (source **{source.SourceType}**, {source.MembershipType})."), - cancellationToken); - } +Member added event - await base.OnTeamsMembersRemovedAsync(membersRemoved, teamInfo, turnContext, cancellationToken); +```csharp +public async Task OnMembersAddedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) +{ + var membersAdded = turnContext.Activity.MembersAdded; + + List addedMembers = new List(); + foreach (var member in membersAdded) + { + if (member.Id != turnContext.Activity.Recipient.Id) + { + addedMembers.Add($"Member {member.Name} (ID {member.Id}) added."); } + } + + await ActivityUtils.SendAdaptiveCard( + "Member Added", + addedMembers, + new List { "membersAdded", membersAdded }, + turnContext, + cancellationToken).ConfigureAwait(false); ``` -These Microsoft 365 Agents SDK endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. - ---- - -## Validate user access for membership updates - -When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the ```doesUserHaveAccess``` API to determine whether the user still has access to the shared channel. - -```HTTP -GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') -``` - -See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http) to learn more about user accesses and relevant permissions. +Member removed event -## Handle bulk membership changes - -If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. This feature reduces notification volume and improves performance. - -### Use sharedWithTeams subscription for bulk membership changes - -### [Graph](#tab/graph-bulk) - -To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: - -```HTTP -`/teams/{team-id}/channels/{channel-id}/sharedWithTeams` +```csharp +public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnState, CancellationToken cancellationToken) +{ + var membersRemoved = turnContext.Activity.MembersRemoved; + + List removedMembers = new List(); + foreach (var member in membersRemoved) + { + if (member.Id != turnContext.Activity.Recipient.Id) + { + removedMembers.Add($"Member {member.Name} (ID {member.Id}) removed."); + } + } + + await ActivityUtils.SendAdaptiveCard( + "Member Removed", + removedMembers, + new List { "membersRemoved", membersRemoved }, + turnContext, + cancellationToken).ConfigureAwait(false); +} ``` -The sharedWithTeams subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the /allMembers API after receiving a "shared with" or "unshared from" team notification. - -> [!NOTE] -> To support membership updates in shared channels, apps using resource-specific consent (RSC) must request extended permissions. -> These permissions let the app: -> -> * Access membership data (both direct and indirect members). -> * Receive and respond to membership change notifications. +--- -### [Microsoft 365 Agents SDK](#tab/microsoft365agentssdk-bulk) +### Shared and unshared with team events -When a shared channel is added to another team, the Microsoft 365 Agents SDK might receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. +When a shared channel is added to another team, the Bot Framework might receive a conversationUpdate activity through the OnConversationUpdateActivityAsync method, but only if the bot is installed in the team or channel. ```csharp protected override async Task OnConversationUpdateActivityAsync( ITurnContext turnContext, CancellationToken cancellationToken) { - // Always present on Teams activities var tcd = turnContext.Activity.GetChannelData(); var eventType = tcd?.EventType?.ToLowerInvariant(); - // Read extended shared-channel shape (safe even if fields are absent) var extended = turnContext.Activity.GetChannelData(); - // Also keep a raw JObject for logging / future-proof access var raw = turnContext.Activity.ChannelData as JObject ?? (turnContext.Activity.ChannelData != null ? JObject.FromObject(turnContext.Activity.ChannelData) : new JObject()); - // Helpful baseline log _logger.LogInformation("ConversationUpdate eventType={EventType}, channelId={ChannelId}, teamId={TeamId}", eventType, tcd?.Channel?.Id, tcd?.Team?.Id); @@ -293,7 +283,7 @@ When a shared channel is added to another team, the Microsoft 365 Agents SDK mig { case "channelshared": { - var hostTeam = extended?.Team; // The channel's host team + var hostTeam = extended?.Team; var sharedWith = extended?.SharedWithTeams ?? new List(); _logger.LogInformation("ChannelShared: hostTeam={HostTeamId}, sharedWithCount={Count}", @@ -305,9 +295,8 @@ When a shared channel is added to another team, the Microsoft 365 Agents SDK mig team.Id, team.Name, team.AadGroupId, team.TenantId); } - // Optional: surface a quick confirmation in-channel await turnContext.SendActivityAsync( - MessageFactory.Text($"✅ Channel shared with {sharedWith.Count} team(s)."), + MessageFactory.Text($" Channel shared with {sharedWith.Count} team(s)."), cancellationToken); break; } @@ -325,13 +314,12 @@ When a shared channel is added to another team, the Microsoft 365 Agents SDK mig } await turnContext.SendActivityAsync( - MessageFactory.Text($"❎ Channel unshared from {unsharedFrom.Count} team(s)."), + MessageFactory.Text($" Channel unshared from {unsharedFrom.Count} team(s)."), cancellationToken); break; } default: - // No-op; continue normal routing break; } @@ -339,7 +327,49 @@ When a shared channel is added to another team, the Microsoft 365 Agents SDK mig } ``` ---- +## Validate user access for membership updates + +### Graph + +When an app receives a 'member removed' notification for an indirect membership update, it’s important to verify whether the user is removed from the shared channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app should confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http) API to learn more about user accesses and relevant permissions. + +```HTTP +GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') +``` + +When an app receives a 'member added' notification for an indirect membership update, see allMembers API to refresh the list of all members. + +```HTTP +GET /teams/{team-id}/channels/{channel-id}/allMembers +``` + +### Handle bulk membership changes + +If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. This feature reduces notification volume and improves performance. + +### Use `sharedWithTeams` subscription for bulk membership changes + +To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new `sharedWithTeams` subscription resource: + +```HTTP +/teams/{team-id}/channels/{channel-id}/sharedWithTeams +``` + +The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the allMembers API after receiving a 'shared with' or 'unshared from' team notification. + +## Classify channels as in-tenant or out-tenant + +You can classify members as in-tenant or out-tenant by comparing the ‘TenantId’ of the member or team with `ownerTenantId` as follows: + +1. Get the 'TenantId' of the member you wish to compare. + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/allMembers +``` + +2. Call `microsoftTeams.app.getContext()` in your tab from the Teams JavaScript client library (TeamsJS SDK). The getContext() call returns context of the shared channel, which contains the details such as displayName, membershipType, ownerGroupId , and ownerTenantId. + +3. Compare the TenantId of the member to the ownerTenantId property and determine if the member is an in-tenant or out-tenant. ## Understand app permissions in shared channels @@ -348,18 +378,22 @@ You can collaborate with external members outside of your organization using sha > [!NOTE] > The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. -## Verify if your app is added to a channel +## Verify app addition to a channel -For bots using the Microsoft 365 Agents SDK, if your bot receives a channelMemberAdded event in a conversationUpdate activity for itself, it indicates that the app is added to the channel. -Begin your channel-specific logic at that point, for example, send a welcome message, fetch the roster, configure tabs, or schedule jobs as needed. Bot events start flowing only after the app is added to the channel +There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. -There’s no direct API to check whether your app is added to a channel. +When your bot receives a `channelMemberAdded` event for itself in a `conversationUpdate`, your app is added to the channel. -> [!NOTE] -> -> * Use ``GET /teams/{team-id}/installedApps``, to list installed apps at the team level. -> * Channel level InstalledApps aren't listed. -> * Avoid using team-level installations to determine which apps are in a channel. +Use this event to trigger app-specific logic such as: + +* Sending a welcome message +* Fetching the channel roster +* Configuring tabs +* Starting scheduled jobs + +Bot events (like messages and mentions) will only begin after your app is added to the channel. + +There’s no direct API to check whether your app is added to a channel. ## Authenticate external users to access app content in SharePoint @@ -369,7 +403,7 @@ You need to complete this step when your app stores content in the SharePoint si Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ``channel.ownerTenantId`` for JSv2 or host tenant ID for JSv1 received under ``getContext`` call. -### [Bots](#tab/bots) +### [Bots](#tab/bots1) For any event payload or action payload received for a bot, use Get hostTenant ID, from ``turnContext.activity.conversation.tenantId``. @@ -391,7 +425,7 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers`` This API works across standard and other channels and and is recommended for reliably indentifying guest members. -## Access sharepoint data in shared and private channels +## Access SharePoint data in shared and private channels If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. @@ -442,10 +476,10 @@ Consider the following steps: * Use specific-people sharing, or rely on membership-based permissions. * Check tenant or site policies, as they may block anonymous or organization-wide links. -To grant access to specific users/groups , use the following API: +To grant access to specific users/groups, use the following API: ```HTTP -POST /drives/{driveId}/items/{itemId}/invite` +POST /drives/{driveId}/items/{itemId}/invite ``` --- @@ -506,7 +540,7 @@ Use two tenants or collaborate with a colleague from another organization via Te Perform the following steps to validate: -1. Have an external user send a message to your bot and confirm that is responds. +1. Have an external user send a message to your bot and confirm that it responds. * The bot should receive the message, provided it is added to the appropriate scope (personal chat, group chat, or channel). 2. Have the external user trigger a task module or tab interaction and verify that the authentication succeeds. * If using SSO, ensure ``getAuthToken`` handles the user's home tenant ID correctly. @@ -522,34 +556,28 @@ Testing across these scenarios will help you spot any issues with functionality, Follow these best practices to ensure your app works reliably across all channel types: -* Always retrieve the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. - -* Adjust app functionality and access controls based on user roles (owner, member, guest, external). Limit sensitive actions to owners or internal users, and offer limited features to guests or external participants. - -* Control data access and sharing based on channel membership and permissions. Never include private-channel data in broader reports or public channels unless explicitly authorized. - -* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when they access files. +### Dos +* Always get the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. +* Adjust app functionality and access controls based on user roles (owner, member, guest, external). +* Control data access and sharing based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). +* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users (B2B guests) in private channels](#identify-guest-users-b2b-guests-in-private-channels) * Update help text and user guides to explain how your app behaves in different channel types, including any limitations for guests or external users. - * Cache large member lists and use change notifications to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. +* Validate your app's behavior across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. +* Review Microsoft Teams documentation and changelogs to stay aligned with the latest updates to APIs, permissions, and channel configurations. -* Test your app across different user roles and channel configurations including owners, members, guests, and external users to confirm it behaves correctly and enforces appropriate permissions. - -* Review Microsoft Teams documentation and changelogs to keep your app aligned with the latest updates to APIs, permissions, and channel configurations. - -## Code sample +### Don'ts -|Sample name|Description|Node.js| -|-------------|-------------|------| -||| +* Restrict sensitive actions to owners or internal users and offer limited features to guests or external participants. +* Never include private-channel data in broader reports or public channels unless explicitly authorized. ## Frequently asked questions
Why isn’t the app visible when trying to add it to a channel? -If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as ``"supportsChannelFeatures": tier1``, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +The app may not appear if the manifest is missing required support, such as ``"supportsChannelFeatures": tier1``. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
  @@ -557,7 +585,7 @@ If an app isn’t visible when trying to add it to a channel, there are a few li
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it has been successfully added to the channel. +This error occurs if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it has been successfully added to the channel.
  @@ -565,7 +593,7 @@ You’ll see a 403 error saying "app not enabled in this channel" if the app is
Why does the channel roster appear incomplete, showing only owners or missing users? -If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +the channel roster appears incomplete due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
  @@ -573,7 +601,7 @@ If the channel roster appears incomplete showing only owners or missing users, i
Why does file access fail for some users even though they're part of the channel? -This failure can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the invite API to give access to specific users or groups. +This failure can happen if the app is using the team’s main SharePoint site instead of the channel's specific site. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups.
  @@ -581,7 +609,7 @@ This failure can happen if the app is using the team’s main SharePoint site in
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. +Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling `getAuthToken`.
  @@ -589,7 +617,7 @@ Authentication issues in tabs or task modules for external users often occur whe
How do I know my app was added to a channel? -This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there's no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. +This issue might occur if the app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, Bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error.
  @@ -597,7 +625,7 @@ This issue might occur if the app is expecting a centralized list of installed a
Why is my app failing to create message change notifications in shared or private channels? -Message change notifications might fail in shared or private channels because subscriptions to ``/channels/{id}/messages`` are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. +Message change notifications might fail in shared or private channels because subscriptions to `/channels/{id}/messages` are blocked when using resource-specific consent (RSC) in these types of channels. If your app receives a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel.
  @@ -607,6 +635,13 @@ Message change notifications might fail in shared or private channels because su This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +## Code sample + +| Sample Name | Description | .NET | Node.js | Python | +|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------|---------|--------| +| Teams Conversation Bot | This sample app displays the names of the members in a federated group chat with external users. | NA | View | NA | +| Membership Change Notification | The sample application demonstrates how to send notifications for shared channel events in Microsoft Teams. Scenarios include users being added, removed, or membership being updated and when channel is shared or unshared with a team. | View | View | View | + ## See also * [Build tabs for Teams](../../tabs/what-are-tabs.md) From ea8ac7a95c3a452351bb8eb87c908e052b20d934 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 00:11:27 +0530 Subject: [PATCH 061/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 803aaec3cce..1edc1baebdb 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -1,5 +1,5 @@ --- -title: Teams Connects Shared and Private Channels +title: Teams connect shared and private channels author: surbhigupta description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. ms.author: surbhigupta @@ -83,7 +83,7 @@ See the following articles, for more information: > [!NOTE] > -> * Tab and bot apps in shared and private channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. +> * Tab and bot apps in shared and private channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](concepts/cloud-overview.md), and [Teams operated by 21Vianet](concepts/sovereign-cloud.md) environments. > * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. | ### Get context for shared and private channels @@ -94,8 +94,8 @@ When loading the content UX in a shared or private channel, use the data receive For more information to enable your tab, see: -* [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) -* [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) +* [Get context for your tab for private channels](tabs/how-to/access-teams-context.md) +* [Get context in shared channels](tabs/how-to/access-teams-context.md) ## Manage channel membership @@ -107,9 +107,9 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers`` ### Identify members -* Direct members: Users who are added directly to the channel, including users from other tenants (cross-tenants). -* Indirect members: Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. -* External members: Guest users, who are not part of your organization but have been granted access to a shared channel through guest access or cross-tenant collaboration. +* **Direct members:** Users who are added directly to the channel, including users from other tenants (cross-tenants). +* **Indirect members:** Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. +* **External members:** Guest users, who are not part of your organization but have been granted access to a shared channel through guest access or cross-tenant collaboration. Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel, as shown in the following table. @@ -118,7 +118,7 @@ Additionally, you can identify whether a member of a shared channel is direct or | Direct Member | Yes | The user is added directly to the shared channel. | | Indirect Member | Yes | The user accesses the shared channel through another team. The `@microsoft.graph.originalSourceMembershipUrl` property includes a URL that points to the source team and indicates indirect membership. | -> [!Note] +> [!NOTE] > You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `List allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists; either directly or indirectly. ## Manage indirect membership across channels @@ -148,12 +148,9 @@ GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams ```HTTP GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/allowedMembers ``` ->[!Note] +>[!NOTE] >`allowedMembers` API returns only newly associated users and doesn't apply to unshared events. - - - #### Direct members Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. @@ -174,10 +171,10 @@ To retrieve direct members of a shared channel: Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. To receive these notifications, you must: -1. [Install the app](../deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. +1. [Install the app](concepts/deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. 2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. -To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). +To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership.md). ```HTTP /teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` @@ -459,14 +456,14 @@ Following is the expected drive behavior of the channels: ### Manage file access for external or guest users -#### [External users](#tab/external users) +#### [External users](#tab/external-users) External users remain in their home tenant while accessing the host channel’s sharepoint site. To enable access: * Configure cross-tenant access on both sides. * Ensure your app is multi-tenant and has received consent in the host tenant. -#### [Guest users](#tab/guest users) +#### [Guest users](#tab/guest-users) The channel’s sharepoint site automatically grants access to all channel members, including tenant guests. From 844130d6490ec6a4bb65b1822840bde2f30155a2 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 00:13:04 +0530 Subject: [PATCH 062/109] Revert "Update TOC.yml" This reverts commit 4cff965359df98c820ee15dbf14c2ebc8b74db3e. --- msteams-platform/TOC.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/TOC.yml b/msteams-platform/TOC.yml index c554381241d..b2c6c08db24 100644 --- a/msteams-platform/TOC.yml +++ b/msteams-platform/TOC.yml @@ -673,7 +673,7 @@ href: get-started/b2c-apps.md displayName: Teams meeting, Teams call, Teams meeting and call for external apps, external apps - name: Apps for Shared and Private Channels - href: build-apps-for-shared-private-channels.md + href: msteams-platform/build-apps-for-shared-private-channels.md displayName: shared channels, private channels - name: Build webhooks and connectors items: From b2c2e1acb3d1357e0aab2f3c969d7d991afb576a Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 00:13:15 +0530 Subject: [PATCH 063/109] Revert "Update shared-channels.md" This reverts commit 24f64f48364d09fd0ed24a4bb31706eb30671e20. --- msteams-platform/concepts/build-and-test/shared-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index cfb86b21e49..d80f351ed34 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -12,7 +12,7 @@ ms.date: 04/09/2025 Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -## Understand channel models in Microsoft Teams +## Understand Channel Models in Microsoft Teams When building or integrating apps with Microsoft Teams, understand how different channel types affect visibility, membership, and data storage. From 54d89d66cdb2cdb6143dee59a359cab5bee6613f Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 00:54:52 +0530 Subject: [PATCH 064/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 1edc1baebdb..640b4f4365f 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -61,6 +61,8 @@ Understanding the difference between Microsoft Teams channel types is essential. > > Check your app’s capability (membership boundaries, storage location, external access) and don’t make any code changes, based on channel type. +[Back to Top](#microsoft-teams-connect-shared-and-private-channels) + ## Enable your app for shared and private channels Enabling app support in shared and private channels depends on whether your app: @@ -148,10 +150,11 @@ GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams ```HTTP GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/allowedMembers ``` + >[!NOTE] >`allowedMembers` API returns only newly associated users and doesn't apply to unshared events. -#### Direct members +### Direct members Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. @@ -165,6 +168,8 @@ To retrieve direct members of a shared channel: GET /teams/{host-team-group-id}/channels/{channel-id}/members ``` +[Back to Top](#microsoft-teams-connect-shared-and-private-channels) + ## Get app notifications for direct and indirect membership changes ### [Graph](#tab/graph) @@ -354,6 +359,8 @@ To reduce notification overload during membership updates, such as when a shared The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the allMembers API after receiving a 'shared with' or 'unshared from' team notification. +[Back to Top](#microsoft-teams-connect-shared-and-private-channels) + ## Classify channels as in-tenant or out-tenant You can classify members as in-tenant or out-tenant by comparing the ‘TenantId’ of the member or team with `ownerTenantId` as follows: @@ -428,6 +435,8 @@ If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). +[Back to Top](#microsoft-teams-connect-shared-and-private-channels) + ### Resolve storage correctly for channel files To access a channel’s sharepoint files root, use the following API: @@ -491,6 +500,8 @@ Use getContext() to retrieve channel context. Compare `user.tenant.id` with `cha 2. Request token from home tenant Call getAuthToken() with the external user's tenant ID (`user.tenant.id` or `tid`) to ensure the token is issued from their home tenant. +[Back to Top](#microsoft-teams-connect-shared-and-private-channels) + ## Test your app across channel types Before publishing updates, validate your app behaves correctly in real situations behaves across all channel types. @@ -555,26 +566,26 @@ Follow these best practices to ensure your app works reliably across all channel ### Dos -* Always get the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. -* Adjust app functionality and access controls based on user roles (owner, member, guest, external). -* Control data access and sharing based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). -* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users (B2B guests) in private channels](#identify-guest-users-b2b-guests-in-private-channels) -* Update help text and user guides to explain how your app behaves in different channel types, including any limitations for guests or external users. -* Cache large member lists and use change notifications to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. -* Validate your app's behavior across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. -* Review Microsoft Teams documentation and changelogs to stay aligned with the latest updates to APIs, permissions, and channel configurations. +* Always get the current channel’s **member list and roles** before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. +* **Adjust app functionality** and **access controls** based on user roles (owner, member, guest, external). +* Control **data access and sharing** based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). +* Identify whether users are **internal, guests, or external (cross-tenant)**, and authenticate them in their home tenant. Always **validate permissions** for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users (B2B guests) in private channels](#identify-guest-users-b2b-guests-in-private-channels) +* **Update help text and user guides** to explain how your app behaves in different channel types, including any limitations for guests or external users. +* Use **cache large member lists** and **change notifications** to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. +* **Validate your app's behavior** across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. +* **Review Microsoft Teams documentation and changelogs** to stay aligned with the latest updates to APIs, permissions, and channel configurations. ### Don'ts -* Restrict sensitive actions to owners or internal users and offer limited features to guests or external participants. -* Never include private-channel data in broader reports or public channels unless explicitly authorized. +* **Restrict sensitive actions** to owners or internal users and offer limited features to guests or external participants. +* **Never include private-channel data** in broader reports or public channels unless explicitly authorized. ## Frequently asked questions
Why isn’t the app visible when trying to add it to a channel? -The app may not appear if the manifest is missing required support, such as ``"supportsChannelFeatures": tier1``. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +The app may not appear if the **manifest is missing required support**, such as ``"supportsChannelFeatures": tier1``. Additionally, the **installer might not have sufficient permissions**, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
  @@ -582,7 +593,7 @@ The app may not appear if the manifest is missing required support, such as ``"s
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -This error occurs if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it has been successfully added to the channel. +This error occurs if the **app is installed at the team level but hasn’t been added to the channel**. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it has been successfully added to the channel.
  @@ -590,7 +601,7 @@ This error occurs if the app is installed at the team level but hasn’t been ad
Why does the channel roster appear incomplete, showing only owners or missing users? -the channel roster appears incomplete due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +The channel roster appears incomplete beacuse the **team members API is used instead of the correct channel-specific API**. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
  @@ -598,7 +609,7 @@ the channel roster appears incomplete due to using the team members API instead
Why does file access fail for some users even though they're part of the channel? -This failure can happen if the app is using the team’s main SharePoint site instead of the channel's specific site. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups. +This failure can happen if the **app is using the team’s main SharePoint site instead of the channel's specific site**. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups.
  @@ -606,7 +617,7 @@ This failure can happen if the app is using the team’s main SharePoint site in
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling `getAuthToken`. +Authentication issues often occur when the **app requests a token for the host tenant instead of the user’s home tenant**. To resolve this authentication issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling `getAuthToken`.
  @@ -614,7 +625,7 @@ Authentication issues often occur when the app requests a token for the host ten
How do I know my app was added to a channel? -This issue might occur if the app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, Bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. +This issue might occur if the **app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior**. Currently, there's no channel-level installedApps list available. Instead, Bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error.
  @@ -622,7 +633,7 @@ This issue might occur if the app is expects a centralized list of installed app
Why is my app failing to create message change notifications in shared or private channels? -Message change notifications might fail in shared or private channels because subscriptions to `/channels/{id}/messages` are blocked when using resource-specific consent (RSC) in these types of channels. If your app receives a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. +Message change notifications might fail in shared or private channels **because subscriptions to `/channels/{id}/messages` are blocked when using resource-specific consent (RSC) in these types of channels**. If your app receives a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel.
  @@ -630,7 +641,9 @@ Message change notifications might fail in shared or private channels because su
Why do file links still fail for external users even after the app is added to the channel? -This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. + +[Back to Top](#microsoft-teams-connect-shared-and-private-channels) ## Code sample From 6e6285cae870bc6dd351ea2b227e2071b0f62e54 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 07:05:36 +0530 Subject: [PATCH 065/109] Peer Reviewed by Neha-Part 1 --- .../build-apps-for-shared-private-channels.md | 23 ++++++++++--------- .../build-and-test/shared-channels.md | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 640b4f4365f..3d119f4b72d 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -10,15 +10,15 @@ ms.date: 04/09/2025 # Microsoft Teams connect shared and private channels -Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. You can experience multiple benefits, depending on your channel: +Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits, depending on your channel: -* Shared channels: Allow seamless communication with internal or external partners, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing +* Shared channels: Allow seamless communication with internal or external partners, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. * Private channels: Provide secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. ## Understand channels for app integration -When building or integrating apps with Microsoft Teams, understanding channel types is crucial, as they determine app visibility, user access, and data storage behavior as shown: +When building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior as shown: | Channels | Access | Collaboration | File storage location | |----------|----------------------------------|--------------------------------------------------------------------------------|-------------------------------------| @@ -45,21 +45,22 @@ Here’s an outline of the different channels and their capabilities, across var ## Understand how different channels impact app functionality -Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. +Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. Ensure that you: -* **Access limits in private and shared channels:** Only members who are specifically added to the channel can participate in these channels. If your bot targets ‘everyone’, it may violate privacy or miss external members. Use channel-specific membership APIs to determine the correct members. +* **Use channel-specific membership APIs** +Don't assume that team membership is equal to channel membership. Only members who are specifically added to the channel can participate in shared and private channels. If your bot targets ‘everyone’, it may violate privacy or miss external members. -* **Different user types:** Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant IDs before granting permissions. +* **Distinguish between users and roles** +Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant IDs before granting permissions. -* **SharePoint sites:** Private and shared channels have their own SharePoint sites. Always use the correct site URL for each channel to avoid missing files or unauthorized access errors. +* **Don't assume a single SharePoint site** +Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. -* **Data aggregation:** Aggregate or cross-post data across channels only when necessary. Keep data scoped to the channel unless clearly defined to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. - -![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](./assets/images/app-fundamentals/shared-channels-teams.png) | +* **Keep data scoped to channels** Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. > [!IMPORTANT] > -> Check your app’s capability (membership boundaries, storage location, external access) and don’t make any code changes, based on channel type. +> Check your app’s capabilities such as membership boundaries, storage location,and external access. Don't make any code changes, based on channel type. [Back to Top](#microsoft-teams-connect-shared-and-private-channels) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index d80f351ed34..b3b88ffe8c1 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -10,7 +10,7 @@ ms.date: 04/09/2025 # Microsoft Teams connect shared and private channels -Shared and private channels in Microsoft Teams enable flexible collaboration within and across teams or organizations. Shared channels allow seamless communication with internal or external partners. Private channels provide a secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. +Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits, depending on your channel: ## Understand Channel Models in Microsoft Teams From 2a3b083cd10eaa5bc4d9db6c29e1e1eb836bf798 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 07:29:06 +0530 Subject: [PATCH 066/109] Neha peer review part 2 --- .../build-apps-for-shared-private-channels.md | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 3d119f4b72d..4eed6968d14 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -26,7 +26,7 @@ When building or integrating apps with Microsoft Teams, understanding channel ty | Private | Only to selected team members | Suitable for scenarios requiring restricted access to bots, connectors, or files | Private channel’s SharePoint site | | Shared | Cross-team and cross-organization | Enables interaction with users outside the host team without requiring them to join the team | Shared channel’s SharePoint site | -## Capabilities across channels +### Capabilities across channels Here’s an outline of the different channels and their capabilities, across various parameters: @@ -43,7 +43,7 @@ Here’s an outline of the different channels and their capabilities, across var | | App installed to host team automatically available in channel | Yes | No | No | | | App must be added to each channel | No | Yes | Yes | -## Understand how different channels impact app functionality +### Understand how different channels impact app functionality Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. Ensure that you: @@ -66,23 +66,19 @@ Private and shared channels have their own SharePoint sites. Always use the corr ## Enable your app for shared and private channels -Enabling app support in shared and private channels depends on whether your app: - -* Uses channel or team membership to determine message delivery, task assignment, or permissions -* Accesses or manages files stored in Teams or SharePoint -* Combines or shares data across multiple channels or teams -* Customizes experience based on whether users (internal, guests, or external participants) +Enabling app support in shared and private channels is asy for most apps. If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple manifest update. -In case your app, doesn’t support any of the listed parameters, then perform the following steps to enable app support in shared and private channels: +If your apps don't: -1. Add ``"supportsChannelFeatures": "tier1"`` to your app manifest to enable support for shared and private channels. -2. To verify expected behavior, test your app in standard, private, and shared channels. +* Use channel or team membership to determine message delivery, task assignment, or permissions +* Access or manage files stored in Teams or SharePoint +* Combine or share data across multiple channels or teams +* Customize experience, based on users (internal, guests, or external participants) -See the following articles, for more information: +perform the following steps to enable app support in shared and private channels: -* [Manage channel membership](#manage-channel-membership) -* [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) -* [Verify if your app is added to a channel](#verify-if-your-app-is-added-to-a-channel) +1. Add ``"supportsChannelFeatures": "tier1"`` to your app manifest to enable support for shared and private channels. +2. To verify expected behavior, test your app in standard, private, and shared channels. > [!NOTE] > @@ -655,6 +651,8 @@ This happens when the **tenant’s sharing policy blocks the link type, or when ## See also +* [Manage channel membership](#manage-channel-membership) +* [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) * [Build tabs for Teams](../../tabs/what-are-tabs.md) * [App manifest schema for Teams](../../resources/schema/manifest-schema.md) * [Shared channels in Microsoft Teams](/microsoftteams/shared-channels) From 0df83061475690844b420d57febf7f69b888745d Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 08:44:03 +0530 Subject: [PATCH 067/109] Neha Peer reviewed -Part 3 --- .../build-apps-for-shared-private-channels.md | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 4eed6968d14..4c64be71278 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -48,15 +48,20 @@ Here’s an outline of the different channels and their capabilities, across var Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. Ensure that you: * **Use channel-specific membership APIs** -Don't assume that team membership is equal to channel membership. Only members who are specifically added to the channel can participate in shared and private channels. If your bot targets ‘everyone’, it may violate privacy or miss external members. + + Don't assume that team membership is equal to channel membership. Only members who are specifically added to the channel can participate in shared and private channels. If your bot targets ‘everyone’, it may violate privacy or miss external members. * **Distinguish between users and roles** -Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant IDs before granting permissions. + + Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant IDs before granting permissions. * **Don't assume a single SharePoint site** -Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. -* **Keep data scoped to channels** Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. + Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. + +* **Keep data scoped to channels** + + Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. > [!IMPORTANT] > @@ -77,7 +82,7 @@ If your apps don't: perform the following steps to enable app support in shared and private channels: -1. Add ``"supportsChannelFeatures": "tier1"`` to your app manifest to enable support for shared and private channels. +1. Add `supportsChannelFeatures`: `tier1` to your app manifest to enable support for shared and private channels. 2. To verify expected behavior, test your app in standard, private, and shared channels. > [!NOTE] @@ -89,7 +94,7 @@ perform the following steps to enable app support in shared and private channels Microsoft Teams now supports enhanced bot and tab capabilities in shared and private channels. -When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. +When loading the content UX in a shared or private channel, use the data received from the `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. For more information to enable your tab, see: @@ -98,7 +103,7 @@ For more information to enable your tab, see: ## Manage channel membership -Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. Get the list of all members in a channel. +Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers`` @@ -110,9 +115,9 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers`` * **Indirect members:** Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. * **External members:** Guest users, who are not part of your organization but have been granted access to a shared channel through guest access or cross-tenant collaboration. -Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel, as shown in the following table. +Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel, as shown in the following table: -| Member Type | Annotation Present? | Description | +| Member Type | Annotation | Description | |-----------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Direct Member | Yes | The user is added directly to the shared channel. | | Indirect Member | Yes | The user accesses the shared channel through another team. The `@microsoft.graph.originalSourceMembershipUrl` property includes a URL that points to the source team and indicates indirect membership. | @@ -120,29 +125,29 @@ Additionally, you can identify whether a member of a shared channel is direct or > [!NOTE] > You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `List allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists; either directly or indirectly. -## Manage indirect membership across channels +### Manage direct and indirect membership across channels You can manage indirect membership in channels using the following Microsoft Graph APIs: -* Use `allMembers` API to retrieve all users who are members of a specific channel. +* Use the `allMembers` API to retrieve all users who are members of a specific channel. ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers ``` -* Use `doesUserHaveAccess API` to determine whether the user is removed from the channel and can view all user accesses and relevant permissions. +* Use the `doesUserHaveAccess API` to determine whether the user is removed from the channel and can view all user accesses and relevant permissions. ```HTTP GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') ``` -* Use sharedWithTeams API to list all teams a channel is shared with. +* Use the`sharedWithTeams` API to list all teams a channel is shared with. ```HTTP GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams ``` -* Use the allowedMembers API to retrieve users from a shared team who can access a shared channel. +* Use the `allowedMembers` API to retrieve users from a shared team who can access a shared channel. ```HTTP GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/allowedMembers @@ -151,27 +156,19 @@ GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/al >[!NOTE] >`allowedMembers` API returns only newly associated users and doesn't apply to unshared events. -### Direct members - -Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. - -You can retrieve the list of direct members in a shared channel by using the ``hostTeamGroupID`` obtained from ``getContext`` and calling the appropriate API. This method returns all users who have been explicitly added to the shared channel, including both internal and external participants. - -To retrieve direct members of a shared channel: - -1. Call the following API: - - ```HTTP - GET /teams/{host-team-group-id}/channels/{channel-id}/members - ``` - [Back to Top](#microsoft-teams-connect-shared-and-private-channels) ## Get app notifications for direct and indirect membership changes -### [Graph](#tab/graph) +Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. +Depending on where you install your apps, go to the following: + +* [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) +* [Installing apps using BOT APIs](#installing-apps-using-bot-apis) + +### Installing apps using Microsoft Graph APIs -Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. To receive these notifications, you must: +To receive app notifications, you must: 1. [Install the app](concepts/deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. 2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. @@ -184,7 +181,7 @@ To receive both direct and indirect member update notifications, you must includ This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) -### [Bots](#tab/bots) +### Installing apps using BOT APIs Microsoft Teams now supports bot notifications for both direct and indirect members. This enhancement expands its Bot Framework SDK to support notifications for indirect members in shared channels. This update improves visibility into membership changes across teams, enabling bots to more effectively track user access in collaborative environments. It builds on the existing capability for bots to subscribe to `conversationUpdate` events in channels. From cd4ac7f82796b23cbd4ef18513204c45b0e44344 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 08:57:04 +0530 Subject: [PATCH 068/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 4c64be71278..e035e208680 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -12,9 +12,9 @@ ms.date: 04/09/2025 Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits, depending on your channel: -* Shared channels: Allow seamless communication with internal or external partners, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. +* **Shared channels**: Allow seamless communication with internal or external partners, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. -* Private channels: Provide secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. +* **Private channels**: Provide secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. ## Understand channels for app integration From c26fd6467916c3b893f6ed97cdcefb9ba9ff183a Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Wed, 1 Oct 2025 10:03:42 +0530 Subject: [PATCH 069/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 60 +++++++++++++++---- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index e035e208680..c3122a2555f 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -71,7 +71,7 @@ Understanding the difference between Microsoft Teams channel types is essential. ## Enable your app for shared and private channels -Enabling app support in shared and private channels is asy for most apps. If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple manifest update. +Enabling app support in shared and private channels is easy for most apps. If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple manifest update. If your apps don't: @@ -80,7 +80,7 @@ If your apps don't: * Combine or share data across multiple channels or teams * Customize experience, based on users (internal, guests, or external participants) -perform the following steps to enable app support in shared and private channels: +Perform the following steps to enable app support in shared and private channels: 1. Add `supportsChannelFeatures`: `tier1` to your app manifest to enable support for shared and private channels. 2. To verify expected behavior, test your app in standard, private, and shared channels. @@ -100,7 +100,7 @@ For more information to enable your tab, see: * [Get context for your tab for private channels](tabs/how-to/access-teams-context.md) * [Get context in shared channels](tabs/how-to/access-teams-context.md) - +* [Get context for your bot](bots/how-to/get-teams-context.md) ## Manage channel membership Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. @@ -183,7 +183,8 @@ This subscription enables apps to monitor membership changes in shared channels ### Installing apps using BOT APIs -Microsoft Teams now supports bot notifications for both direct and indirect members. This enhancement expands its Bot Framework SDK to support notifications for indirect members in shared channels. This update improves visibility into membership changes across teams, enabling bots to more effectively track user access in collaborative environments. It builds on the existing capability for bots to subscribe to `conversationUpdate` events in channels. +Microsoft Teams now supports bot notifications for both direct and indirect members. +This enhancement expands its Bot Framework SDK to support notifications for indirect members in shared channels. This update improves visibility into membership changes across teams, enabling bots to more effectively track user access in collaborative environments. It builds on the existing capability for bots to subscribe to `conversationUpdate` events in channels. ### Manage member added and removed events @@ -198,10 +199,47 @@ A member removed event is sent to your bot in the following scenarios: 2. When a user is removed from a conversation where the bot is installed. For more information, see [Conversation events - Teams | Microsoft Learn]() -The following Bot Framework SDK examples apply to both direct and indirect member add and remove events. To receive transitive member events, ensure your bot is set up with all the prerequisites. + +To receive `conversationUpdate` event notifications when indirect members are added or removed, configure your bot with the following prerequisites: + +1. Update the App manifest + + To declare support for shared channels, add the `supportedChannelTypes` property to your app manifest: + +```JSON + "supportedChannelTypes": [ + "sharedChannels", + ] +``` +2. Request Resource-Specific Consent (RSC) permission + + Your app must request the following RSC permission to access channel membership information: + +```json +{ + "authorization": { + "permissions": { + "resourceSpecific": [ + { + "name": "ChannelMember.Read.Group", + "type": "Application" + } + ] + } + } +} +``` + +3. Ensure the bot is enabled in the shared channel + + To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. + + + This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. +The following Bot Framework SDK examples apply to both direct and indirect member add and remove events. Member added event ```csharp @@ -255,7 +293,7 @@ public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnS ### Shared and unshared with team events -When a shared channel is added to another team, the Bot Framework might receive a conversationUpdate activity through the OnConversationUpdateActivityAsync method, but only if the bot is installed in the team or channel. +When a shared channel is added to another team, the Bot Framework might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. ```csharp protected override async Task OnConversationUpdateActivityAsync( @@ -333,7 +371,7 @@ When an app receives a 'member removed' notification for an indirect membership GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') ``` -When an app receives a 'member added' notification for an indirect membership update, see allMembers API to refresh the list of all members. +When an app receives a 'member added' notification for an indirect membership update, see `allMembers API` to refresh the list of all members. ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers @@ -389,10 +427,6 @@ Use this event to trigger app-specific logic such as: * Configuring tabs * Starting scheduled jobs -Bot events (like messages and mentions) will only begin after your app is added to the channel. - -There’s no direct API to check whether your app is added to a channel. - ## Authenticate external users to access app content in SharePoint You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. @@ -411,7 +445,7 @@ Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to ## Identify guest users (B2B guests) in private channels -You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. +You can identify if a member of private channel is a guest user, invited to your tenant from external organization, using `roles` property received for each object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. For guests, “roles” = “guest” @@ -619,7 +653,7 @@ Authentication issues often occur when the **app requests a token for the host t
How do I know my app was added to a channel? -This issue might occur if the **app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior**. Currently, there's no channel-level installedApps list available. Instead, Bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. +This issue might occur if the **app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior**. Currently, there's no channel-level installedApps list available. Instead, bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error.
  From 62a429a8bd5e2cd72e1415d8d0f14e03922cc938 Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Wed, 1 Oct 2025 10:09:58 +0530 Subject: [PATCH 070/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index c3122a2555f..52409bc477a 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -96,9 +96,8 @@ Microsoft Teams now supports enhanced bot and tab capabilities in shared and pri When loading the content UX in a shared or private channel, use the data received from the `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. -For more information to enable your tab, see: +See more: -* [Get context for your tab for private channels](tabs/how-to/access-teams-context.md) * [Get context in shared channels](tabs/how-to/access-teams-context.md) * [Get context for your bot](bots/how-to/get-teams-context.md) ## Manage channel membership From 96be8f884ff5cbd34d89003a7f258945b8cbf54e Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 10:25:37 +0530 Subject: [PATCH 071/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 640b4f4365f..e32c88ac8e6 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -198,11 +198,6 @@ A member added event is sent to your bot in the following scenarios: 1. When the bot, itself, is installed and added to a conversation 2. When a user is added to a conversation where the bot is installed -A member removed event is sent to your bot in the following scenarios: - -1. When the bot, itself, is uninstalled and removed from a conversation. -2. When a user is removed from a conversation where the bot is installed. - For more information, see [Conversation events - Teams | Microsoft Learn]() The following Bot Framework SDK examples apply to both direct and indirect member add and remove events. To receive transitive member events, ensure your bot is set up with all the prerequisites. @@ -585,7 +580,7 @@ Follow these best practices to ensure your app works reliably across all channel
Why isn’t the app visible when trying to add it to a channel? -The app may not appear if the **manifest is missing required support**, such as ``"supportsChannelFeatures": tier1``. Additionally, the **installer might not have sufficient permissions**, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +The app may not appear if the **manifest is missing required support**, such as ``supportsChannelFeatures: tier1``. Additionally, the **installer might not have sufficient permissions**, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
  @@ -625,7 +620,7 @@ Authentication issues often occur when the **app requests a token for the host t
How do I know my app was added to a channel? -This issue might occur if the **app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior**. Currently, there's no channel-level installedApps list available. Instead, Bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. +This issue might occur if the **app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior**. Currently, there's no channel-level installedApps list available. Instead, bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error.
  @@ -641,7 +636,7 @@ Message change notifications might fail in shared or private channels **because
Why do file links still fail for external users even after the app is added to the channel? -This happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. [Back to Top](#microsoft-teams-connect-shared-and-private-channels) From 9ed6a644cd735a4e580e45310b75c444bb3f6797 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 10:43:42 +0530 Subject: [PATCH 072/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 8e92dbc7260..6e6feb7509d 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -18,7 +18,7 @@ Shared and private channels in Microsoft Teams enable flexible collaboration wit ## Understand channels for app integration -When building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior as shown: +When you're building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior as shown: | Channels | Access | Collaboration | File storage location | |----------|----------------------------------|--------------------------------------------------------------------------------|-------------------------------------| @@ -43,13 +43,13 @@ Here’s an outline of the different channels and their capabilities, across var | | App installed to host team automatically available in channel | Yes | No | No | | | App must be added to each channel | No | Yes | Yes | -### Understand how different channels impact app functionality +### Understand how different channels determine app functionality Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. Ensure that you: * **Use channel-specific membership APIs** - Don't assume that team membership is equal to channel membership. Only members who are specifically added to the channel can participate in shared and private channels. If your bot targets ‘everyone’, it may violate privacy or miss external members. + Don't assume that team membership is equal to channel membership. Only members who are added to the channel can participate in shared and private channels. If your bot targets everyone, it may violate privacy or miss external members. * **Distinguish between users and roles** @@ -65,7 +65,7 @@ Understanding the difference between Microsoft Teams channel types is essential. > [!IMPORTANT] > -> Check your app’s capabilities such as membership boundaries, storage location,and external access. Don't make any code changes, based on channel type. +> Check your app’s capabilities such as membership boundaries, storage location, and external access. Don't make any code changes, based on channel type. [Back to Top](#microsoft-teams-connect-shared-and-private-channels) @@ -82,7 +82,7 @@ If your apps don't: Perform the following steps to enable app support in shared and private channels: -1. Add `supportsChannelFeatures`: `tier1` to your app manifest to enable support for shared and private channels. +1. Add `supportsChannelFeatures`: `tier1` to your app manifest, to enable support for shared and private channels. 2. To verify expected behavior, test your app in standard, private, and shared channels. > [!NOTE] @@ -112,7 +112,7 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers`` * **Direct members:** Users who are added directly to the channel, including users from other tenants (cross-tenants). * **Indirect members:** Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. -* **External members:** Guest users, who are not part of your organization but have been granted access to a shared channel through guest access or cross-tenant collaboration. +* **External members:** Guest users, who aren't part of your organization but are granted access to a shared channel through guest access or cross-tenant collaboration. Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel, as shown in the following table: @@ -160,7 +160,7 @@ GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/al ## Get app notifications for direct and indirect membership changes Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. -Depending on where you install your apps, go to the following: +Depending on where you install your apps, go to the following section: * [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) * [Installing apps using BOT APIs](#installing-apps-using-bot-apis) @@ -389,7 +389,7 @@ The `sharedWithTeams` subscription sends a single notification when a channel is ## Classify channels as in-tenant or out-tenant -You can classify members as in-tenant or out-tenant by comparing the ‘TenantId’ of the member or team with `ownerTenantId` as follows: +You can classify members as in-tenant or out-tenant by comparing the 'TenantId' of the member or team with `ownerTenantId` as follows: 1. Get the 'TenantId' of the member you wish to compare. @@ -397,7 +397,7 @@ You can classify members as in-tenant or out-tenant by comparing the ‘TenantId GET /teams/{host-team-group-id}/channels/{channel-id}/allMembers ``` -2. Call `microsoftTeams.app.getContext()` in your tab from the Teams JavaScript client library (TeamsJS SDK). The getContext() call returns context of the shared channel, which contains the details such as displayName, membershipType, ownerGroupId , and ownerTenantId. +2. Call `microsoftTeams.app.getContext()` in your tab from the Teams JavaScript client library (TeamsJS SDK). The getContext() call returns context of the shared channel, which contains the details such as displayName, membershipType, ownerGroupId, and ownerTenantId. 3. Compare the TenantId of the member to the ownerTenantId property and determine if the member is an in-tenant or out-tenant. @@ -443,13 +443,13 @@ You can identify if a member of private channel is a guest user, invited to your For guests, “roles” = “guest” -To accurately retrieve the all guest users in Private channel use the following``allMembers`` API: +To accurately, retrieve the all guest users in Private channel use the following``allMembers`` API: ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers`` ``` -This API works across standard and other channels and and is recommended for reliably indentifying guest members. +This API works across standard and other channels and is recommended for reliably identifying guest members. ## Access SharePoint data in shared and private channels @@ -492,7 +492,7 @@ Following is the expected drive behavior of the channels: External users remain in their home tenant while accessing the host channel’s sharepoint site. To enable access: * Configure cross-tenant access on both sides. -* Ensure your app is multi-tenant and has received consent in the host tenant. +* Ensure your app is multitenant and receives consent in the host tenant. #### [Guest users](#tab/guest-users) @@ -502,7 +502,7 @@ Consider the following steps: * Avoid using Organization-wide sharing links they typically exclude external users. * Use specific-people sharing, or rely on membership-based permissions. -* Check tenant or site policies, as they may block anonymous or organization-wide links. +* Check tenant or site policies, as they might block anonymous or organization-wide links. To grant access to specific users/groups, use the following API: @@ -530,7 +530,7 @@ Before publishing updates, validate your app behaves correctly in real situation ### Standard channel -Confirm that the existing functionality remains intact after your changes. Ensure tabs, bots and messaging extensions continue to work as expected. +Confirm that the existing functionality remains intact after your changes. Ensure tabs, bots, and messaging extensions continue to work as expected. ### Private channel @@ -546,7 +546,7 @@ Perform the following steps to validate: 4. If your app lists members or assigns tasks, confirm it only uses channel members and not the complete team. 5. Add a new member to the private channel and check: * Whether your app receives a membership change event - * Whether your membership API reflects the new member. + * Whether your membership API reflects the new member ### Shared channel @@ -571,16 +571,16 @@ Use two tenants or collaborate with a colleague from another organization via Te Perform the following steps to validate: 1. Have an external user send a message to your bot and confirm that it responds. - * The bot should receive the message, provided it is added to the appropriate scope (personal chat, group chat, or channel). + * The bot should receive the message, provided added to the appropriate scope (personal chat, group chat, or channel). 2. Have the external user trigger a task module or tab interaction and verify that the authentication succeeds. * If using SSO, ensure ``getAuthToken`` handles the user's home tenant ID correctly. 3. Attempt to send a direct message from your bot to the external user: - * This will fail if the user is outside your tenant + * This functionality fails if the user is outside your tenant * Confirm that in-channel communication still works. --- -Testing across these scenarios will help you spot any issues with functionality, permissions, and user experience. +Testings across these scenarios help you spot any issues with functionality, permissions, and user experience. ## Best practices for supporting all channels @@ -607,7 +607,7 @@ Follow these best practices to ensure your app works reliably across all channel
Why isn’t the app visible when trying to add it to a channel? -The app may not appear if the **manifest is missing required support**, such as ``supportsChannelFeatures: tier1``. Additionally, the **installer might not have sufficient permissions**, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +The app might not appear if the **manifest is missing required support**, such as ``supportsChannelFeatures: tier1``. Additionally, the **installer might not have sufficient permissions**, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.
  @@ -615,7 +615,7 @@ The app may not appear if the **manifest is missing required support**, such as
Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? -This error occurs if the **app is installed at the team level but hasn’t been added to the channel**. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it has been successfully added to the channel. +This error occurs if the **app is installed at the team level but hasn’t been added to the channel**. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it's successfully added to the channel.
  @@ -623,7 +623,7 @@ This error occurs if the **app is installed at the team level but hasn’t been
Why does the channel roster appear incomplete, showing only owners or missing users? -The channel roster appears incomplete beacuse the **team members API is used instead of the correct channel-specific API**. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +The channel roster appears incomplete because the **team members API is used instead of the correct channel-specific API**. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.
  @@ -631,7 +631,7 @@ The channel roster appears incomplete beacuse the **team members API is used ins
Why does file access fail for some users even though they're part of the channel? -This failure can happen if the **app is using the team’s main SharePoint site instead of the channel's specific site**. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups. +This failure can happen if the **app is using the team’s main SharePoint site instead of the channel's specific site**. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When you're sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups.
  @@ -639,7 +639,7 @@ This failure can happen if the **app is using the team’s main SharePoint site
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues often occur when the **app requests a token for the host tenant instead of the user’s home tenant**. To resolve this authentication issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling `getAuthToken`. +Authentication issues often occur when the **app requests a token for the host tenant instead of the user’s home tenant**. To resolve this issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`.
  @@ -663,7 +663,7 @@ Message change notifications might fail in shared or private channels **because
Why do file links still fail for external users even after the app is added to the channel? -This happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This faliure happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. [Back to Top](#microsoft-teams-connect-shared-and-private-channels) From 9570b9487a9b7100d43383ffaec7f455f50d79ef Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 10:52:11 +0530 Subject: [PATCH 073/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 6e6feb7509d..8af6f71c168 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -49,11 +49,11 @@ Understanding the difference between Microsoft Teams channel types is essential. * **Use channel-specific membership APIs** - Don't assume that team membership is equal to channel membership. Only members who are added to the channel can participate in shared and private channels. If your bot targets everyone, it may violate privacy or miss external members. + Don't assume that team membership is equal to channel membership. Only members who are added to the channel can participate in shared and private channels. If your bot targets everyone, it might violate privacy or miss external members. * **Distinguish between users and roles** - Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant IDs before granting permissions. + Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant ids before granting permissions. * **Don't assume a single SharePoint site** @@ -61,7 +61,7 @@ Understanding the difference between Microsoft Teams channel types is essential. * **Keep data scoped to channels** - Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. + Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps shouldn't include private channel data in team-wide reports unless permissions are clearly defined. > [!IMPORTANT] > @@ -573,7 +573,7 @@ Perform the following steps to validate: 1. Have an external user send a message to your bot and confirm that it responds. * The bot should receive the message, provided added to the appropriate scope (personal chat, group chat, or channel). 2. Have the external user trigger a task module or tab interaction and verify that the authentication succeeds. - * If using SSO, ensure ``getAuthToken`` handles the user's home tenant ID correctly. + * If using Single Sign-On authentication (SSO), ensure ``getAuthToken`` handles the user's home tenant ID correctly. 3. Attempt to send a direct message from your bot to the external user: * This functionality fails if the user is outside your tenant * Confirm that in-channel communication still works. @@ -613,9 +613,9 @@ The app might not appear if the **manifest is missing required support**, such a  
-Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? +Why am I getting a 403 error stating 'app not enabled in this channel' when calling channel APIs? -This error occurs if the **app is installed at the team level but hasn’t been added to the channel**. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to confirm it's successfully added to the channel. +This error occurs if the **app is installed at the team level but hasn’t been added to the channel**. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to verify successfully addition to the channel.
  @@ -663,7 +663,7 @@ Message change notifications might fail in shared or private channels **because
Why do file links still fail for external users even after the app is added to the channel? -This faliure happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This failure happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. [Back to Top](#microsoft-teams-connect-shared-and-private-channels) From 6c9aa72882ffb73daab9aa967ace1c9d1bf2e6a7 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 13:38:15 +0530 Subject: [PATCH 074/109] Updated --- msteams-platform/TOC.yml | 12 ++- .../build-apps-for-shared-private-channels.md | 80 +++++++++---------- 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/msteams-platform/TOC.yml b/msteams-platform/TOC.yml index b2c6c08db24..b57bbb1ff99 100644 --- a/msteams-platform/TOC.yml +++ b/msteams-platform/TOC.yml @@ -464,6 +464,9 @@ - name: Optimize bots with rate limits href: bots/how-to/rate-limit.md displayName: handle rate limit, detect transient exceptions, per thread limit, exponential backoff + - name: Apps for shared and private channels + href: msteams-platform/build-apps-for-shared-private-channels.md + displayName: shared channels, private channels - name: Explore advanced bot capabilities items: - name: Modify Teams bot API to fetch team or chat members @@ -522,6 +525,12 @@ - name: Apps for shared channels href: concepts/build-and-test/shared-channels.md displayName: Cross-tenant notifications, context for shared channel, apps and permissions in shared channels + - name: Apps for shared and private channels + href: msteams-platform/build-apps-for-shared-private-channels.md + displayName: shared channels, private channels + - name: Deep link to a tab + href: tabs/how-to/deep-link-to-tab.md + displayName: deep link, link to tab, link to specific content, sub-page in tab - name: Send activity feed notifications href: /graph/teams-send-activityfeednotifications?toc=/microsoftteams/platform/toc.json&bc=/microsoftteams/platform/breadcrumb/toc.json displayName: activity feed, notification, customize notification @@ -672,9 +681,6 @@ - name: Integrate meetings and calls in external apps href: get-started/b2c-apps.md displayName: Teams meeting, Teams call, Teams meeting and call for external apps, external apps -- name: Apps for Shared and Private Channels - href: msteams-platform/build-apps-for-shared-private-channels.md - displayName: shared channels, private channels - name: Build webhooks and connectors items: - name: Overview diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 8af6f71c168..61c09832e53 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -8,17 +8,19 @@ ms.topic: conceptual ms.date: 04/09/2025 --- -# Microsoft Teams connect shared and private channels +# Apps for shared and private channels Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits, depending on your channel: -* **Shared channels**: Allow seamless communication with internal or external partners, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. +* **Shared channels**: Allow seamless communication with internal or external members, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. * **Private channels**: Provide secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. +Bot and tab capabilities are supported in shared and private channels. + ## Understand channels for app integration -When you're building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior as shown: +When you're building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior: | Channels | Access | Collaboration | File storage location | |----------|----------------------------------|--------------------------------------------------------------------------------|-------------------------------------| @@ -32,16 +34,16 @@ Here’s an outline of the different channels and their capabilities, across var | Model | Channel Capabilities | Standard Channel | Shared Channels | Private Channels | |-------------|----------------------------------------------------------------------------------------|-----------------------------------|----------------------------------|----------------------------------| -| Membership | Can add people to the channel without adding to the host team | No | Yes | No | -| | Channel membership can be limited to a subset of the host team | No | Yes | Yes | -| | Channel can be shared with other teams to inherit members from the team | No | Yes | No | -| | Channel can be shared directly with its parent team to inherit members from parent team | N/A | Yes | No | -| | External users can participate in the channel | Yes (B2B collab users) | Yes (B2B Direct connect) | Yes (B2B collab users) | -| | Channel is hosted under a host team | Yes | Yes | | -| Storage | Each channel has a dedicated SharePoint site | No (Inherits team site) | Yes | Yes | -| App Model | App must be installed in the host team | Yes | Yes | Yes | -| | App installed to host team automatically available in channel | Yes | No | No | -| | App must be added to each channel | No | Yes | Yes | +| Membership | Can add people to the channel without adding to the host team | ❌ | ✔️ | ❌ | +| | Channel membership can be limited to a subset of the host team | ❌ | ✔️ | ✔️ | +| | Channel can be shared with other teams to inherit members from the team | ❌ | ✔️ | ❌ | +| | Channel can be shared directly with its parent team to inherit members from parent team | N/A | ✔️ | ❌ | +| | External users can participate in the channel | ✔️ (B2B collab users) | ✔️ (B2B Direct connect) | ✔️ (B2B collab users) | +| | Channel is hosted under a host team | ✔️ | ✔️ | | +| Storage | Each channel has a dedicated SharePoint site | ❌ (Inherits team site) | ✔️ | ✔️ | +| App Model | App must be installed in the host team | ✔️ | ✔️ | ✔️ | +| | App installed to host team automatically available in channel | ✔️ | ❌ | ❌ | +| | App must be added to each channel | ❌ | ✔️ | ✔️ | ### Understand how different channels determine app functionality @@ -88,7 +90,7 @@ Perform the following steps to enable app support in shared and private channels > [!NOTE] > > * Tab and bot apps in shared and private channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](concepts/cloud-overview.md), and [Teams operated by 21Vianet](concepts/sovereign-cloud.md) environments. -> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. | +> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. ### Get context for shared and private channels @@ -100,12 +102,13 @@ See more: * [Get context in shared channels](tabs/how-to/access-teams-context.md) * [Get context for your bot](bots/how-to/get-teams-context.md) + ## Manage channel membership Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. ```HTTP -GET /teams/{team-id}/channels/{channel-id}/allMembers`` +GET /teams/{team-id}/channels/{channel-id}/allMembers ``` ### Identify members @@ -357,8 +360,6 @@ When a shared channel is added to another team, the Bot Framework might receive ## Validate user access for membership updates -### Graph - When an app receives a 'member removed' notification for an indirect membership update, it’s important to verify whether the user is removed from the shared channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app should confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http) API to learn more about user accesses and relevant permissions. ```HTTP @@ -410,9 +411,7 @@ You can collaborate with external members outside of your organization using sha ## Verify app addition to a channel -There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. - -When your bot receives a `channelMemberAdded` event for itself in a `conversationUpdate`, your app is added to the channel. +There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. when your bot receives. When your bot receives a `channelMemberAdded` event for itself in a `conversationUpdate`, your app is added to the channel.There’s no dedicated API to check if your app is part of a channel. Use this event to trigger app-specific logic such as: @@ -604,66 +603,63 @@ Follow these best practices to ensure your app works reliably across all channel ## Frequently asked questions +
+
Why isn’t the app visible when trying to add it to a channel? -The app might not appear if the **manifest is missing required support**, such as ``supportsChannelFeatures: tier1``. Additionally, the **installer might not have sufficient permissions**, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +The app might not appear if the manifest is missing required support, such as ``supportsChannelFeatures: tier1``. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. -
+
Why am I getting a 403 error stating 'app not enabled in this channel' when calling channel APIs? -This error occurs if the **app is installed at the team level but hasn’t been added to the channel**. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to verify successfully addition to the channel. +This error occurs if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to verify successfully addition to the channel. -
+
Why does the channel roster appear incomplete, showing only owners or missing users? -The channel roster appears incomplete because the **team members API is used instead of the correct channel-specific API**. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +The channel roster appears incomplete because the team members API is used instead of the correct channel-specific API. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. -
+
Why does file access fail for some users even though they're part of the channel? -This failure can happen if the **app is using the team’s main SharePoint site instead of the channel's specific site**. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When you're sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups. +This failure can happen if the app is using the team’s main SharePoint site instead of the channel's specific site. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When you're sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups. -
+
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues often occur when the **app requests a token for the host tenant instead of the user’s home tenant**. To resolve this issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`. +Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`. -
+
How do I know my app was added to a channel? -This issue might occur if the **app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior**. Currently, there's no channel-level installedApps list available. Instead, bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. +This issue might occur if the app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. -
+
Why is my app failing to create message change notifications in shared or private channels? -Message change notifications might fail in shared or private channels **because subscriptions to `/channels/{id}/messages` are blocked when using resource-specific consent (RSC) in these types of channels**. If your app receives a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. +Message change notifications might fail in shared or private channels because subscriptions to `/channels/{id}/messages` are blocked when using resource-specific consent (RSC) in these types of channels. If your app receives a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. -
+
Why do file links still fail for external users even after the app is added to the channel? -This failure happens when the **tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel**. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This failure happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. + +
[Back to Top](#microsoft-teams-connect-shared-and-private-channels) From 6bceead5986c93bddf929031e1ddab9bf1611cf8 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 13:51:47 +0530 Subject: [PATCH 075/109] Update TOC.yml --- msteams-platform/TOC.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/TOC.yml b/msteams-platform/TOC.yml index b57bbb1ff99..65fea43d230 100644 --- a/msteams-platform/TOC.yml +++ b/msteams-platform/TOC.yml @@ -465,7 +465,7 @@ href: bots/how-to/rate-limit.md displayName: handle rate limit, detect transient exceptions, per thread limit, exponential backoff - name: Apps for shared and private channels - href: msteams-platform/build-apps-for-shared-private-channels.md + href: build-apps-for-shared-private-channels.md displayName: shared channels, private channels - name: Explore advanced bot capabilities items: @@ -526,7 +526,7 @@ href: concepts/build-and-test/shared-channels.md displayName: Cross-tenant notifications, context for shared channel, apps and permissions in shared channels - name: Apps for shared and private channels - href: msteams-platform/build-apps-for-shared-private-channels.md + href: build-apps-for-shared-private-channels.md displayName: shared channels, private channels - name: Deep link to a tab href: tabs/how-to/deep-link-to-tab.md From 1aeb652d8bf8ca35806c26c8c745e97434564fce Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 16:00:16 +0530 Subject: [PATCH 076/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 61c09832e53..3f604086425 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -10,7 +10,7 @@ ms.date: 04/09/2025 # Apps for shared and private channels -Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits, depending on your channel: +Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits: * **Shared channels**: Allow seamless communication with internal or external members, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. @@ -24,7 +24,7 @@ When you're building or integrating apps with Microsoft Teams, understanding cha | Channels | Access | Collaboration | File storage location | |----------|----------------------------------|--------------------------------------------------------------------------------|-------------------------------------| -| Standard | All team members by default | Ideal for team-wide collaboration where bots or tabs should be available to everyone | Team’s SharePoint site | +| Standard | All team members by default | Ideal for team-wide collaboration where bots or tabs must be available to everyone | Team’s SharePoint site | | Private | Only to selected team members | Suitable for scenarios requiring restricted access to bots, connectors, or files | Private channel’s SharePoint site | | Shared | Cross-team and cross-organization | Enables interaction with users outside the host team without requiring them to join the team | Shared channel’s SharePoint site | @@ -32,22 +32,22 @@ When you're building or integrating apps with Microsoft Teams, understanding cha Here’s an outline of the different channels and their capabilities, across various parameters: -| Model | Channel Capabilities | Standard Channel | Shared Channels | Private Channels | -|-------------|----------------------------------------------------------------------------------------|-----------------------------------|----------------------------------|----------------------------------| -| Membership | Can add people to the channel without adding to the host team | ❌ | ✔️ | ❌ | -| | Channel membership can be limited to a subset of the host team | ❌ | ✔️ | ✔️ | -| | Channel can be shared with other teams to inherit members from the team | ❌ | ✔️ | ❌ | -| | Channel can be shared directly with its parent team to inherit members from parent team | N/A | ✔️ | ❌ | -| | External users can participate in the channel | ✔️ (B2B collab users) | ✔️ (B2B Direct connect) | ✔️ (B2B collab users) | -| | Channel is hosted under a host team | ✔️ | ✔️ | | -| Storage | Each channel has a dedicated SharePoint site | ❌ (Inherits team site) | ✔️ | ✔️ | -| App Model | App must be installed in the host team | ✔️ | ✔️ | ✔️ | -| | App installed to host team automatically available in channel | ✔️ | ❌ | ❌ | -| | App must be added to each channel | ❌ | ✔️ | ✔️ | +| Model | Channel capabilities | Standard channel | Shared and private channels | +|---------------|------------------------------------------------------------------|-------------------------------------------|-------------------------------------------------------| +| **Membership**| Can add people to the channel without adding to the host team | ❌ | ✔️
(not supported for private channels) | +| | Channel membership can be limited to a subset of the host team | ❌ | ✔️ | +| | Channel can be shared with other teams to inherit members | ❌ | ✔️
(not supported for private channels) | +| | Channel can be shared directly with its parent team | N/A | ✔️
(not supported for private channels) | +| | External users can participate in the channel | ✔️
(B2B collaboration users) | ✔️ | +| | Channel is hosted under a host team | ✔️ | ✔️ | +| **Storage** | Each channel has a dedicated SharePoint site | ❌
(inherits team site) | ✔️ | +| **App Model** | App must be installed in the host team | ✔️ | ✔️ | +| | App installed to host team automatically available in channel | ✔️ | ❌ | +| | App must be added to each channel | ❌ | ✔️ | ### Understand how different channels determine app functionality -Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. Ensure that you: +Ensure that you understand that how different channels determine app functionality, membership, storage, or privacy, else can lead to broken functionality or unintended data exposure: * **Use channel-specific membership APIs** @@ -636,14 +636,14 @@ This failure can happen if the app is using the team’s main SharePoint site in
Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`. +Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app must request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`.

How do I know my app was added to a channel? -This issue might occur if the app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, bots should listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. +This issue might occur if the app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, bots must listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error.

From 8734d8a4f9e33b992f6f8a29aee1926e2ef7f5ce Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 16:05:41 +0530 Subject: [PATCH 077/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 3f604086425..b7340447409 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -73,7 +73,9 @@ Ensure that you understand that how different channels determine app functionali ## Enable your app for shared and private channels -Enabling app support in shared and private channels is easy for most apps. If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple manifest update. +Enabling app support in shared and private channels is easy for most apps. If your apps doesn't support the following + +If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple manifest update. If your apps don't: From a2342fc946af86e34073ebbe9de09aac9eee4266 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 16:21:17 +0530 Subject: [PATCH 078/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index b7340447409..ed02747b2da 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -73,18 +73,16 @@ Ensure that you understand that how different channels determine app functionali ## Enable your app for shared and private channels -Enabling app support in shared and private channels is easy for most apps. If your apps doesn't support the following +Enabling app support in shared and private channels is easy for most apps. If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple configuration change. -If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple manifest update. - -If your apps don't: +You can enable your app for shared and private channels, even if your apps don't support the following: * Use channel or team membership to determine message delivery, task assignment, or permissions * Access or manage files stored in Teams or SharePoint * Combine or share data across multiple channels or teams * Customize experience, based on users (internal, guests, or external participants) -Perform the following steps to enable app support in shared and private channels: +To enable app support in shared and private channels, perform the following steps: 1. Add `supportsChannelFeatures`: `tier1` to your app manifest, to enable support for shared and private channels. 2. To verify expected behavior, test your app in standard, private, and shared channels. @@ -96,9 +94,7 @@ Perform the following steps to enable app support in shared and private channels ### Get context for shared and private channels -Microsoft Teams now supports enhanced bot and tab capabilities in shared and private channels. - -When loading the content UX in a shared or private channel, use the data received from the `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. +When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. See more: From e3879e2cec605348a4f3398dce2b2f6c813dfe54 Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Wed, 1 Oct 2025 16:21:55 +0530 Subject: [PATCH 079/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index b7340447409..912de13ee34 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -165,10 +165,10 @@ GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/al ## Get app notifications for direct and indirect membership changes Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. -Depending on where you install your apps, go to the following section: +Depending on how you install your apps, go to the following section: * [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) -* [Installing apps using BOT APIs](#installing-apps-using-bot-apis) + ### Installing apps using Microsoft Graph APIs @@ -187,7 +187,7 @@ This subscription enables apps to monitor membership changes in shared channels ### Installing apps using BOT APIs -Microsoft Teams now supports bot notifications for both direct and indirect members. +Microsoft Teams supports bot notifications for both direct and indirect members. This enhancement expands its Bot Framework SDK to support notifications for indirect members in shared channels. This update improves visibility into membership changes across teams, enabling bots to more effectively track user access in collaborative environments. It builds on the existing capability for bots to subscribe to `conversationUpdate` events in channels. ### Manage member added and removed events From af7619b5727af041987c58014cdc3d2b6ccdaeac Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 17:06:34 +0530 Subject: [PATCH 080/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index ed02747b2da..319bf1b2172 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -227,7 +227,7 @@ To receive `conversationUpdate` event notifications when indirect members are ad 3. Ensure the bot is enabled in the shared channel - To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. + To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. @@ -409,7 +409,7 @@ You can collaborate with external members outside of your organization using sha ## Verify app addition to a channel -There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. when your bot receives. When your bot receives a `channelMemberAdded` event for itself in a `conversationUpdate`, your app is added to the channel.There’s no dedicated API to check if your app is part of a channel. +When your bot receives a `channelMemberAdded` event for itself in a `conversationUpdate`, your app is added to the channel. There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. Use this event to trigger app-specific logic such as: @@ -585,14 +585,14 @@ Follow these best practices to ensure your app works reliably across all channel ### Dos -* Always get the current channel’s **member list and roles** before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. -* **Adjust app functionality** and **access controls** based on user roles (owner, member, guest, external). -* Control **data access and sharing** based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). -* Identify whether users are **internal, guests, or external (cross-tenant)**, and authenticate them in their home tenant. Always **validate permissions** for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users (B2B guests) in private channels](#identify-guest-users-b2b-guests-in-private-channels) -* **Update help text and user guides** to explain how your app behaves in different channel types, including any limitations for guests or external users. -* Use **cache large member lists** and **change notifications** to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. -* **Validate your app's behavior** across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. -* **Review Microsoft Teams documentation and changelogs** to stay aligned with the latest updates to APIs, permissions, and channel configurations. +* Always get the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. +* Adjust app functionality and access controls based on user roles (owner, member, guest, external). +* Control data access and sharing based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). +* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users (B2B guests) in private channels](#identify-guest-users-b2b-guests-in-private-channels) +* Update help text and user guides to explain how your app behaves in different channel types, including any limitations for guests or external users. +* Use cache large member lists and change notifications to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. +* Validate your app's behavior across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. +* Review Microsoft Teams documentation and changelogs to stay aligned with the latest updates to APIs, permissions, and channel configurations. ### Don'ts From 05f56e05bd75797f197eeeb2ca7ee3d2ef996b3a Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 18:12:18 +0530 Subject: [PATCH 081/109] Neha Changes in Graph Section --- .../build-apps-for-shared-private-channels.md | 84 +++++++------------ 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 912de13ee34..a5e2aea4925 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -71,23 +71,19 @@ Ensure that you understand that how different channels determine app functionali [Back to Top](#microsoft-teams-connect-shared-and-private-channels) -## Enable your app for shared and private channels +## Enable apps for shared and private channels -Enabling app support in shared and private channels is easy for most apps. If your apps doesn't support the following - -If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple manifest update. - -If your apps don't: +You can enable app support in shared and private channels, even if your apps don't: * Use channel or team membership to determine message delivery, task assignment, or permissions * Access or manage files stored in Teams or SharePoint * Combine or share data across multiple channels or teams * Customize experience, based on users (internal, guests, or external participants) -Perform the following steps to enable app support in shared and private channels: + To enable app support in shared and private channels: -1. Add `supportsChannelFeatures`: `tier1` to your app manifest, to enable support for shared and private channels. -2. To verify expected behavior, test your app in standard, private, and shared channels. +1. Add `supportsChannelFeatures`: `tier1` to your app manifest. +2. Verify expected behavior, and test your app across channels. > [!NOTE] > @@ -96,18 +92,11 @@ Perform the following steps to enable app support in shared and private channels ### Get context for shared and private channels -Microsoft Teams now supports enhanced bot and tab capabilities in shared and private channels. - -When loading the content UX in a shared or private channel, use the data received from the `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. - -See more: - -* [Get context in shared channels](tabs/how-to/access-teams-context.md) -* [Get context for your bot](bots/how-to/get-teams-context.md) +When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [[Get context in shared channels](tabs/how-to/access-teams-context.md)] and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) -## Manage channel membership +### Manage channel membership -Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. +Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. For more information, see ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers @@ -119,7 +108,7 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers * **Indirect members:** Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. * **External members:** Guest users, who aren't part of your organization but are granted access to a shared channel through guest access or cross-tenant collaboration. -Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel, as shown in the following table: +Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel: | Member Type | Annotation | Description | |-----------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -127,50 +116,44 @@ Additionally, you can identify whether a member of a shared channel is direct or | Indirect Member | Yes | The user accesses the shared channel through another team. The `@microsoft.graph.originalSourceMembershipUrl` property includes a URL that points to the source team and indicates indirect membership. | > [!NOTE] -> You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `List allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists; either directly or indirectly. +> You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists, either directly or indirectly. -### Manage direct and indirect membership across channels +### Manage indirect membership across channels You can manage indirect membership in channels using the following Microsoft Graph APIs: -* Use the `allMembers` API to retrieve all users who are members of a specific channel. +* Use the `allMembers` API to retrieve all users who are members of a specific channel. -```HTTP -GET /teams/{team-id}/channels/{channel-id}/allMembers -``` + ```HTTP + GET /teams/{team-id}/channels/{channel-id}/allMembers + ``` -* Use the `doesUserHaveAccess API` to determine whether the user is removed from the channel and can view all user accesses and relevant permissions. +* Use the `doesUserHaveAccess` API to determine whether the user is removed from the channel and can view all user accesses and relevant permissions. -```HTTP -GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') -``` + ```HTTP + GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') + ``` * Use the`sharedWithTeams` API to list all teams a channel is shared with. -```HTTP -GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams -``` + ```HTTP + GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams + ``` * Use the `allowedMembers` API to retrieve users from a shared team who can access a shared channel. -```HTTP -GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/allowedMembers -``` + ```HTTP + GET /teams/{team-id}/channels/{channel-id}/sharedWithTeams/{sharewithteamsId}/allowedMembers + ``` >[!NOTE] ->`allowedMembers` API returns only newly associated users and doesn't apply to unshared events. +>The `allowedMembers` API returns only newly associated users and doesn't apply to unshared events. -[Back to Top](#microsoft-teams-connect-shared-and-private-channels) +[Back to Top](#enable-apps-for-shared-and-private-channels) -## Get app notifications for direct and indirect membership changes +## Get app notifications for membership changes Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. -Depending on how you install your apps, go to the following section: - -* [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) - - -### Installing apps using Microsoft Graph APIs To receive app notifications, you must: @@ -185,11 +168,6 @@ To receive both direct and indirect member update notifications, you must includ This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) -### Installing apps using BOT APIs - -Microsoft Teams supports bot notifications for both direct and indirect members. -This enhancement expands its Bot Framework SDK to support notifications for indirect members in shared channels. This update improves visibility into membership changes across teams, enabling bots to more effectively track user access in collaborative environments. It builds on the existing capability for bots to subscribe to `conversationUpdate` events in channels. - ### Manage member added and removed events A member added event is sent to your bot in the following scenarios: @@ -210,7 +188,8 @@ To receive `conversationUpdate` event notifications when indirect members are ad "sharedChannels", ] ``` -2. Request Resource-Specific Consent (RSC) permission + +2. Request Resource-Specific Consent (RSC) permission Your app must request the following RSC permission to access channel membership information: @@ -231,8 +210,7 @@ To receive `conversationUpdate` event notifications when indirect members are ad 3. Ensure the bot is enabled in the shared channel - To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. - + To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. From 914c7f996251e57d503034a5e6e472966c865d28 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 18:18:46 +0530 Subject: [PATCH 082/109] added API links --- msteams-platform/build-apps-for-shared-private-channels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index a5e2aea4925..9e582d09b44 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -96,7 +96,7 @@ When loading the user experience in a shared or private channel, use the data re ### Manage channel membership -Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. For more information, see +Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. For more information, see [List allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers @@ -340,7 +340,7 @@ When a shared channel is added to another team, the Bot Framework might receive ## Validate user access for membership updates -When an app receives a 'member removed' notification for an indirect membership update, it’s important to verify whether the user is removed from the shared channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app should confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http) API to learn more about user accesses and relevant permissions. +When an app receives a 'member removed' notification for an indirect membership update, it’s important to verify whether the user is removed from the shared channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app should confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. ```HTTP GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') From 2b985638058e85dc853ddf1b1cb5acf1bdfa7237 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 18:34:56 +0530 Subject: [PATCH 083/109] Neha section, part 2 changes --- .../build-apps-for-shared-private-channels.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 9e582d09b44..d4de1ac966e 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -92,11 +92,11 @@ You can enable app support in shared and private channels, even if your apps don ### Get context for shared and private channels -When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [[Get context in shared channels](tabs/how-to/access-teams-context.md)] and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) +When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). ### Manage channel membership -Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. For more information, see [List allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) +Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. For more information, see [List allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ). ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers @@ -115,8 +115,8 @@ Additionally, you can identify whether a member of a shared channel is direct or | Direct Member | Yes | The user is added directly to the shared channel. | | Indirect Member | Yes | The user accesses the shared channel through another team. The `@microsoft.graph.originalSourceMembershipUrl` property includes a URL that points to the source team and indicates indirect membership. | -> [!NOTE] -> You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists, either directly or indirectly. + > [!NOTE] + > You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists, either directly or indirectly. ### Manage indirect membership across channels @@ -157,10 +157,10 @@ Apps installed in shared channels receive notifications when users are added to To receive app notifications, you must: -1. [Install the app](concepts/deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. +1. Install the app in a host team and enable it for the shared channel. For more information on installing the app, see [Install the app](concepts/deploy-and-publish/apps-upload.md). 2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. -To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership.md). +To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. For more information, see [Channel membership access](/graph/teams-changenotifications-channelmembership.md). ```HTTP /teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` @@ -340,13 +340,13 @@ When a shared channel is added to another team, the Bot Framework might receive ## Validate user access for membership updates -When an app receives a 'member removed' notification for an indirect membership update, it’s important to verify whether the user is removed from the shared channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app should confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. +When an app receives a 'member removed' notification for an indirect membership update, it’s important to verify whether the user is removed from the shared channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app should confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. ```HTTP GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') ``` -When an app receives a 'member added' notification for an indirect membership update, see `allMembers API` to refresh the list of all members. +When an app receives a 'member added' notification for an indirect membership update, see see the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API to refresh the list of all members. ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers From ff0205198774f89ff65fa9fcd395fad019452ad8 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 18:55:41 +0530 Subject: [PATCH 084/109] Neha final changes --- .../build-apps-for-shared-private-channels.md | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index d4de1ac966e..a17789dba7e 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -168,6 +168,16 @@ To receive both direct and indirect member update notifications, you must includ This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) +### Handle bulk membership changes + +If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the`sharedWithTeams` subscription resource: + +```HTTP +/teams/{team-id}/channels/{channel-id}/sharedWithTeams +``` + +The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. + ### Manage member added and removed events A member added event is sent to your bot in the following scenarios: @@ -340,35 +350,19 @@ When a shared channel is added to another team, the Bot Framework might receive ## Validate user access for membership updates -When an app receives a 'member removed' notification for an indirect membership update, it’s important to verify whether the user is removed from the shared channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app should confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. +When an app receives a *member removed* notification for an indirect membership update, it’s important to verify whether the user is removed from the channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app must confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. ```HTTP GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') ``` -When an app receives a 'member added' notification for an indirect membership update, see see the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API to refresh the list of all members. +When an app receives a *member added* notification for an indirect membership update, see the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API to refresh the list of all members. ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers ``` -### Handle bulk membership changes - -If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. This feature reduces notification volume and improves performance. - -### Use `sharedWithTeams` subscription for bulk membership changes - -To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new `sharedWithTeams` subscription resource: - -```HTTP -/teams/{team-id}/channels/{channel-id}/sharedWithTeams -``` - -The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the allMembers API after receiving a 'shared with' or 'unshared from' team notification. - -[Back to Top](#microsoft-teams-connect-shared-and-private-channels) - -## Classify channels as in-tenant or out-tenant +### Classify members as in-tenant or out-tenant You can classify members as in-tenant or out-tenant by comparing the 'TenantId' of the member or team with `ownerTenantId` as follows: @@ -378,9 +372,11 @@ You can classify members as in-tenant or out-tenant by comparing the 'TenantId' GET /teams/{host-team-group-id}/channels/{channel-id}/allMembers ``` -2. Call `microsoftTeams.app.getContext()` in your tab from the Teams JavaScript client library (TeamsJS SDK). The getContext() call returns context of the shared channel, which contains the details such as displayName, membershipType, ownerGroupId, and ownerTenantId. +2. Call `microsoftTeams.app.getContext()` in your tab from the Teams JavaScript client library. The getContext() call returns context of the shared channel, which contains the details such as `displayName`, `membershipType`, `ownerGroupId`, and `ownerTenantId`. -3. Compare the TenantId of the member to the ownerTenantId property and determine if the member is an in-tenant or out-tenant. +3. Compare the `TenantId` of the member to the `ownerTenantId` property and determine if the member is an in-tenant or out-tenant. + +[Back to Top](#enable-apps-for-shared-and-private-channels) ## Understand app permissions in shared channels From ec567e95b12758f8317f2b0081e19345b2c66d1e Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Wed, 1 Oct 2025 19:40:52 +0530 Subject: [PATCH 085/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 82 ++++++++++--------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index a17789dba7e..9474a9e1843 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -168,44 +168,18 @@ To receive both direct and indirect member update notifications, you must includ This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) -### Handle bulk membership changes - -If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the`sharedWithTeams` subscription resource: - -```HTTP -/teams/{team-id}/channels/{channel-id}/sharedWithTeams -``` - -The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. - -### Manage member added and removed events - -A member added event is sent to your bot in the following scenarios: +The `conversationUpdate` event is sent to your bot when it receives notifications on membership updates for teams where it is added. To receive both direct and indirect member update notifications, configure your bot with the following prerequisites: -1. When the bot, itself, is installed and added to a conversation -2. When a user is added to a conversation where the bot is installed - -For more information, see [Conversation events - Teams | Microsoft Learn]() - -To receive `conversationUpdate` event notifications when indirect members are added or removed, configure your bot with the following prerequisites: +1. Update the app manifest. Add `supportsChannelFeatures`: `tier1` to declare app readiness. -1. Update the App manifest - - To declare support for shared channels, add the `supportedChannelTypes` property to your app manifest: - -```JSON - "supportedChannelTypes": [ - "sharedChannels", - ] -``` - -2. Request Resource-Specific Consent (RSC) permission + +2. Request Resource-Specific Consent (RSC) permission Your app must request the following RSC permission to access channel membership information: -```json -{ - "authorization": { + ```json + { + "authorization": { "permissions": { "resourceSpecific": [ { @@ -214,19 +188,38 @@ To receive `conversationUpdate` event notifications when indirect members are ad } ] } - } -} -``` + } + } + ``` 3. Ensure the bot is enabled in the shared channel - To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. + To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. +### Manage member added and removed events + +A member added event is sent to your bot in the following scenarios: + +1. When the bot, itself, is installed and added to a conversation +2. When a user is added to a conversation where the bot is installed + +A member removed event is sent to your bot in the following scenarios: + +1. When the bot, itself, is uninstalled and removed from a conversation. +2. When a user is removed from a conversation where the bot is installed. + +For more information, see [Conversation events.](/graph/teams-changenotifications-teammembership) + +If the bot is installed in the team or channel, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, when a shared channel is added to another team. + + + When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. -The following Bot Framework SDK examples apply to both direct and indirect member add and remove events. +The following Agents SDK examples apply to both direct and indirect member add and remove events. + Member added event ```csharp @@ -278,9 +271,20 @@ public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnS --- +### Handle bulk membership changes + +If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the`sharedWithTeams` subscription resource: + +```HTTP +/teams/{team-id}/channels/{channel-id}/sharedWithTeams +``` + +The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. + + ### Shared and unshared with team events -When a shared channel is added to another team, the Bot Framework might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. +When a shared channel is added to another team, the Agents SDK might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. ```csharp protected override async Task OnConversationUpdateActivityAsync( From 46b0943db27cd2e1d2597c4db06100bf17b4f02c Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 20:44:38 +0530 Subject: [PATCH 086/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 9474a9e1843..88858159d63 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -78,7 +78,7 @@ You can enable app support in shared and private channels, even if your apps don * Use channel or team membership to determine message delivery, task assignment, or permissions * Access or manage files stored in Teams or SharePoint * Combine or share data across multiple channels or teams -* Customize experience, based on users (internal, guests, or external participants) +* Customize experience, based on users (internal, guests, or external members) To enable app support in shared and private channels: @@ -92,7 +92,7 @@ You can enable app support in shared and private channels, even if your apps don ### Get context for shared and private channels -When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). +When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). ### Manage channel membership @@ -172,8 +172,7 @@ The `conversationUpdate` event is sent to your bot when it receives notification 1. Update the app manifest. Add `supportsChannelFeatures`: `tier1` to declare app readiness. - -2. Request Resource-Specific Consent (RSC) permission +2. Request Resource-Specific Consent (RSC) permission Your app must request the following RSC permission to access channel membership information: @@ -194,7 +193,7 @@ The `conversationUpdate` event is sent to your bot when it receives notification 3. Ensure the bot is enabled in the shared channel - To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. + To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. @@ -214,8 +213,6 @@ For more information, see [Conversation events.](/graph/teams-changenotification If the bot is installed in the team or channel, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, when a shared channel is added to another team. - - When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. The following Agents SDK examples apply to both direct and indirect member add and remove events. @@ -281,7 +278,6 @@ If there are bulk membership changes, Teams curbs individual membership update n The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. - ### Shared and unshared with team events When a shared channel is added to another team, the Agents SDK might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. From 7dacab1f607d8568eb98f6f712b6a795463c8677 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Wed, 1 Oct 2025 20:52:53 +0530 Subject: [PATCH 087/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 151 +++++++++--------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 625dbd68b7e..12fbb214663 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -7,6 +7,9 @@ ms.localizationpriority: high ms.topic: conceptual ms.date: 04/09/2025 --- +> [!NOTE] +> +> * Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md). # Apps for shared and private channels @@ -16,7 +19,7 @@ Shared and private channels in Microsoft Teams enable flexible collaboration wit * **Private channels**: Provide secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -Bot and tab capabilities are supported in shared and private channels. +Bot and tab apps are supported in shared and private channels. ## Understand channels for app integration @@ -45,6 +48,10 @@ Here’s an outline of the different channels and their capabilities, across var | | App installed to host team automatically available in channel | ✔️ | ❌ | | | App must be added to each channel | ❌ | ✔️ | +> [!IMPORTANT] +> +> Check your app’s capabilities such as membership boundaries, storage location, and external access. Don't make any code changes, based on channel type. + ### Understand how different channels determine app functionality Ensure that you understand that how different channels determine app functionality, membership, storage, or privacy, else can lead to broken functionality or unintended data exposure: @@ -57,7 +64,7 @@ Ensure that you understand that how different channels determine app functionali Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant ids before granting permissions. -* **Don't assume a single SharePoint site** +* **Don't assume a single SharePoint site tied to a team** Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. @@ -65,10 +72,6 @@ Ensure that you understand that how different channels determine app functionali Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps shouldn't include private channel data in team-wide reports unless permissions are clearly defined. -> [!IMPORTANT] -> -> Check your app’s capabilities such as membership boundaries, storage location, and external access. Don't make any code changes, based on channel type. - [Back to Top](#microsoft-teams-connect-shared-and-private-channels) ## Enable your app for shared and private channels @@ -165,7 +168,6 @@ Depending on how you install your apps, go to the following section: * [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) - ### Installing apps using Microsoft Graph APIs To receive app notifications, you must: @@ -411,7 +413,7 @@ You can collaborate with external members outside of your organization using sha When your bot receives a `channelMemberAdded` event for itself in a `conversationUpdate`, your app is added to the channel. There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. -Use this event to trigger app-specific logic such as: +Use this `channelMemberAdded` event to trigger app-specific logic such as: * Sending a welcome message * Fetching the channel roster @@ -424,26 +426,27 @@ You need to complete this step when your app stores content in the SharePoint si ### [Tabs](#tab/tabs) -Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ``channel.ownerTenantId`` for JSv2 or host tenant ID for JSv1 received under ``getContext`` call. +1. Save host tenant ID of shared channel where tab is configured. +2. Retrieve the host tenant ID using `channel.ownerTenantId` in JSv2 or from the `getContext` call in JSv1. ### [Bots](#tab/bots1) -For any event payload or action payload received for a bot, use Get hostTenant ID, from ``turnContext.activity.conversation.tenantId``. +To retrieve the host tenant ID for any event or action payload received by a bot, use `turnContext.activity.conversation.tenantId`. --- -Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the shared channel. +Now, send saved host tenantId inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside SharePoint site attached to the shared channel. -## Identify guest users (B2B guests) in private channels +## Identify guest users in channels -You can identify if a member of private channel is a guest user, invited to your tenant from external organization, using `roles` property received for each object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. +You can identify if a member of a channel is a guest user, invited to your tenant from external organization, using `roles` property received for each object in [List members of a channel](/graph/api/channel-list-members) response. -For guests, “roles” = “guest” +For guests, 'roles' = 'guest' -To accurately, retrieve the all guest users in Private channel use the following``allMembers`` API: +To accurately, retrieve the all guest users in a channel use the following `allMembers` API: ```HTTP -GET /teams/{team-id}/channels/{channel-id}/allMembers`` +GET /teams/{team-id}/channels/{channel-id}/allMembers ``` This API works across standard and other channels and is recommended for reliably identifying guest members. @@ -452,24 +455,24 @@ This API works across standard and other channels and is recommended for reliabl If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. -Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). +Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder](/graph/api/channel-get-filesfolder). [Back to Top](#microsoft-teams-connect-shared-and-private-channels) -### Resolve storage correctly for channel files +### Access SharePoint storage correctly for channel files -To access a channel’s sharepoint files root, use the following API: +To access a channel’s SharePoint files root, use the following API: ```HTTP GET /teams/{teamId}/channels/{channelId}/filesFolder ``` -This returns a DriveItem object for that channel's files root. +This API returns a DriveItem object for that channel's files root. For more, see [channel files](/graph/api/channel-get-filesfolder?view=graph-rest-1.0&tabs=http) Use the following properties for all subsequent file operations: -* `parentReference.driveId`: The sharepoint drive ID for the channel’s site. -* `itemId`: The folder ID for the channel’s root. +* `parentReference.driveId`: The SharePoint driveId for the channel’s site. +* `itemId`: The folderId for the channel’s root. Following is the expected drive behavior of the channels: @@ -479,29 +482,29 @@ Following is the expected drive behavior of the channels: > [!NOTE] > > Always store and reuse the `driveId` and `itemId` returned by the API. -> Avoid hardcoding library names or URLs based on assumptions about the team site, as the team site location can change. -> Use the preceding API for all channel types. +> Don't hardcode library names or URLs based on assumptions about the team site, as the team site location can change. +> Use this `GET /teams/{teamId}/channels/{channelId}/filesFolder` API for all channel types. ### Manage file access for external or guest users #### [External users](#tab/external-users) -External users remain in their home tenant while accessing the host channel’s sharepoint site. To enable access: +External users remain in their tenant while accessing the host channel’s sharepoint site. To enable access: -* Configure cross-tenant access on both sides. -* Ensure your app is multitenant and receives consent in the host tenant. +1. Configure cross-tenant access on both sides. +2. Ensure your app is multitenant and receives consent in the host tenant. #### [Guest users](#tab/guest-users) -The channel’s sharepoint site automatically grants access to all channel members, including tenant guests. +The channel’s SharePoint site automatically grants access to all channel members, including tenants. -Consider the following steps: +Esnure the following: -* Avoid using Organization-wide sharing links they typically exclude external users. +* Avoid using organization-wide sharing links they typically exclude external users. * Use specific-people sharing, or rely on membership-based permissions. * Check tenant or site policies, as they might block anonymous or organization-wide links. -To grant access to specific users/groups, use the following API: +To grant access to specific users or groups, use the following API: ```HTTP POST /drives/{driveId}/items/{itemId}/invite @@ -521,44 +524,27 @@ Call getAuthToken() with the external user's tenant ID (`user.tenant.id` or `tid [Back to Top](#microsoft-teams-connect-shared-and-private-channels) -## Test your app across channel types +## Test your app across channels -Before publishing updates, validate your app behaves correctly in real situations behaves across all channel types. +Before publishing updates, ensure your app works correctly across all channel types in real situations. ### Standard channel Confirm that the existing functionality remains intact after your changes. Ensure tabs, bots, and messaging extensions continue to work as expected. -### Private channel - -Create a private channel P in Team A with atleast two members (one owner, one member). - -Perform the following steps to validate: - -1. Add the app to Team A then add it to private channel P. -2. Verify that your tab loads correctly in the private channel. -3. Test bot responses for different user types: - * In-tenant member - * Guest user or external user -4. If your app lists members or assigns tasks, confirm it only uses channel members and not the complete team. -5. Add a new member to the private channel and check: - * Whether your app receives a membership change event - * Whether your membership API reflects the new member - ### Shared channel ### [Shared channel (same tenant)](#tab/sharedchannel) -Create shared channel X in Team A, then share it with Team B (requires owner permissions). +Create shared channel in Team A, then share it with Team B (requires owner permissions). Perform the following steps to validate: 1. Add the app to Team A (host team), then to Channel X. -2. Validate that members from Team B. - * Can see the tab - * Receive bot responses -3. Unshare the channel from Team B and confirm: - * Your bot receives a ``channelUnshared`` event +2. Validate that the members from Team B: +Can see the tab and receive bot responses. +1. Unshare the channel from Team B and confirm: + * Your bot receives a `channelUnshared` event * Membership updates are handled correctly ### [Shared channel (external tenant)](#tab/sharedchannel-externaltenant) @@ -567,32 +553,45 @@ Use two tenants or collaborate with a colleague from another organization via Te Perform the following steps to validate: -1. Have an external user send a message to your bot and confirm that it responds. - * The bot should receive the message, provided added to the appropriate scope (personal chat, group chat, or channel). -2. Have the external user trigger a task module or tab interaction and verify that the authentication succeeds. - * If using Single Sign-On authentication (SSO), ensure ``getAuthToken`` handles the user's home tenant ID correctly. -3. Attempt to send a direct message from your bot to the external user: +1. Have an external user send a message to your bot and confirm that it responds. The bot must receive the message, provided added to the appropriate scope (personal chat, group chat, or channel). +1. Have the external user trigger a task module or tab interaction and verify that the authentication succeeds. + * If using Single Sign-On authentication (SSO), ensure `getAuthToken` handles the user's home tenant ID correctly. +2. Attempt to send a direct message from your bot to the external user: * This functionality fails if the user is outside your tenant * Confirm that in-channel communication still works. +### Private channel + +Create a private channel in Team A with atleast two members (owner and member). + +Perform the following steps to validate: + +1. Add the app to Team A then add it to private channel. +2. Verify that your tab loads correctly in the private channel. +3. Test bot responses for different user types: + * In-tenant member + * Guest user or external user +4. If your app lists members or assigns tasks, confirm it only uses channel members and not the complete team. +5. Add a new member to the private channel and check: + * Whether your app receives a membership change event. + * Whether your membership API reflects the new member. + --- Testings across these scenarios help you spot any issues with functionality, permissions, and user experience. ## Best practices for supporting all channels -Follow these best practices to ensure your app works reliably across all channel types: - ### Dos -* Always get the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. -* Adjust app functionality and access controls based on user roles (owner, member, guest, external). -* Control data access and sharing based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). -* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users (B2B guests) in private channels](#identify-guest-users-b2b-guests-in-private-channels) -* Update help text and user guides to explain how your app behaves in different channel types, including any limitations for guests or external users. -* Use cache large member lists and change notifications to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. -* Validate your app's behavior across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. -* Review Microsoft Teams documentation and changelogs to stay aligned with the latest updates to APIs, permissions, and channel configurations. +* **Always retrieve the current channel’s member list and roles** before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. +* **Adjust app functionality and access controls** based on user roles (owner, member, guest, external). +* **Control data access and sharing** based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). +* **Determine** whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users in channels](#identify-guest-users-in-channels) +* **Update help text and user guides** to explain how your app behaves in different channel types, including any limitations for guests or external users. +* **Use cache large member lists and change notifications** to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. +* **Validate your app's behavior** across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. +* **Review Microsoft Teams documentation and changelogs** to stay aligned with the latest updates to APIs, permissions, and channel configurations. ### Don'ts @@ -606,35 +605,35 @@ Follow these best practices to ensure your app works reliably across all channel
Why isn’t the app visible when trying to add it to a channel? -The app might not appear if the manifest is missing required support, such as ``supportsChannelFeatures: tier1``. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. +The app might not appear if the manifest is missing required support, such as `supportsChannelFeatures: tier1`. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID.

Why am I getting a 403 error stating 'app not enabled in this channel' when calling channel APIs? -This error occurs if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ``ChannelMember.Read.Group`` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ``channelMemberAdded`` event to verify successfully addition to the channel. +This error occurs if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, `ChannelMember.Read.Group` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the `channelMemberAdded` event to verify successfully addition to the channel.

Why does the channel roster appear incomplete, showing only owners or missing users? -The channel roster appears incomplete because the team members API is used instead of the correct channel-specific API. To resolve this issue, use the ``/channels/{id}/allMembers`` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. +The channel roster appears incomplete because the team members API is used instead of the correct channel-specific API. To resolve this issue, use the `/channels/{id}/allMembers` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster.

Why does file access fail for some users even though they're part of the channel? -This failure can happen if the app is using the team’s main SharePoint site instead of the channel's specific site. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When you're sharing files, use 'people with existing access' links or the invite API to give access to specific users or groups. +This failure can happen if the app is using the team’s main SharePoint site instead of the channel's specific site. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When you're sharing files, use **people with existing access** links or the invite API to give access to specific users or groups.

Why are external users experiencing authentication issues in tabs or task modules? -Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing ``context.user.tenant.id`` with the host or owner tenant ID. If they're different, the user is external, and your app must request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`. +Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing `context.user.tenant.id` with the host or owner tenant ID. If they're different, the user is external, and your app must request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`.

@@ -655,7 +654,7 @@ Message change notifications might fail in shared or private channels because su
Why do file links still fail for external users even after the app is added to the channel? -This failure happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +This failure happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, ensure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site.
From e38826938d4ee97a5fbc30db9c6c35e6c972f72b Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 21:48:04 +0530 Subject: [PATCH 088/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 1172b11b048..fb82b38565a 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -76,24 +76,14 @@ Ensure that you understand that how different channels determine app functionali ## Enable apps for shared and private channels -<<<<<<< HEAD -Enabling app support in shared and private channels is easy for most apps. If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple configuration change. - -You can enable your app for shared and private channels, even if your apps don't support the following: -======= You can enable app support in shared and private channels, even if your apps don't: ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c * Use channel or team membership to determine message delivery, task assignment, or permissions * Access or manage files stored in Teams or SharePoint * Combine or share data across multiple channels or teams * Customize experience, based on users (internal, guests, or external members) -<<<<<<< HEAD To enable app support in shared and private channels, perform the following steps: -======= - To enable app support in shared and private channels: ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c 1. Add `supportsChannelFeatures`: `tier1` to your app manifest. 2. Verify expected behavior, and test your app across channels. @@ -105,16 +95,7 @@ To enable app support in shared and private channels, perform the following step ### Get context for shared and private channels -<<<<<<< HEAD -When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. - -See more: - -* [Get context in shared channels](tabs/how-to/access-teams-context.md) -* [Get context for your bot](bots/how-to/get-teams-context.md) -======= When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c ### Manage channel membership @@ -176,14 +157,11 @@ You can manage indirect membership in channels using the following Microsoft Gra ## Get app notifications for membership changes Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. -<<<<<<< HEAD Depending on how you install your apps, go to the following section: * [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) ### Installing apps using Microsoft Graph APIs -======= ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c To receive app notifications, you must: @@ -224,10 +202,6 @@ The `conversationUpdate` event is sent to your bot when it receives notification 3. Ensure the bot is enabled in the shared channel To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. -<<<<<<< HEAD - -======= ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. From 0f9938b3a2370ca964409804f5e935923cf63bd9 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 22:19:22 +0530 Subject: [PATCH 089/109] Self-review done --- .../build-apps-for-shared-private-channels.md | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index fb82b38565a..38ebda1e934 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -7,9 +7,6 @@ ms.localizationpriority: high ms.topic: conceptual ms.date: 04/09/2025 --- -> [!NOTE] -> -> * Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md). # Apps for shared and private channels @@ -21,6 +18,10 @@ Shared and private channels in Microsoft Teams enable flexible collaboration wit Bot and tab apps are supported in shared and private channels. +> [!NOTE] +> +> Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md). + ## Understand channels for app integration When you're building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior: @@ -72,7 +73,7 @@ Ensure that you understand that how different channels determine app functionali Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps shouldn't include private channel data in team-wide reports unless permissions are clearly defined. -[Back to Top](#microsoft-teams-connect-shared-and-private-channels) +[Back to Top](#apps-for-shared-and-private-channels) ## Enable apps for shared and private channels @@ -95,11 +96,11 @@ To enable app support in shared and private channels, perform the following step ### Get context for shared and private channels -When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). - +When loading the user experience in a shared and private channel, use the data received from the `getContext` call for shared and private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) + ### Manage channel membership -Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. For more information, see [List allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ). +Use the `allMembers` API that manages and monitors channel memberships across standard, shared, and private channels. It enhances accuracy by reflecting direct and indirect members correctly. For more information, see [List allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true). ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers @@ -157,11 +158,6 @@ You can manage indirect membership in channels using the following Microsoft Gra ## Get app notifications for membership changes Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. -Depending on how you install your apps, go to the following section: - -* [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) - -### Installing apps using Microsoft Graph APIs To receive app notifications, you must: @@ -176,6 +172,17 @@ To receive both direct and indirect member update notifications, you must includ This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) +### Handle bulk membership changes + +If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the`sharedWithTeams` subscription resource: + +```HTTP +/teams/{team-id}/channels/{channel-id}/sharedWithTeams +``` + +The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. + +Bots The `conversationUpdate` event is sent to your bot when it receives notifications on membership updates for teams where it is added. To receive both direct and indirect member update notifications, configure your bot with the following prerequisites: 1. Update the app manifest. Add `supportsChannelFeatures`: `tier1` to declare app readiness. @@ -276,16 +283,6 @@ public async Task OnMembersRemovedAsync(ITurnContext turnContext, AppState turnS --- -### Handle bulk membership changes - -If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the`sharedWithTeams` subscription resource: - -```HTTP -/teams/{team-id}/channels/{channel-id}/sharedWithTeams -``` - -The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. - ### Shared and unshared with team events When a shared channel is added to another team, the Agents SDK might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. From bdb686202125ec77a40845059bfbcad5aed068be Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 1 Oct 2025 22:47:40 +0530 Subject: [PATCH 090/109] self-review final changes --- .../build-apps-for-shared-private-channels.md | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 38ebda1e934..66d71cd072d 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -10,6 +10,10 @@ ms.date: 04/09/2025 # Apps for shared and private channels +> [!NOTE] +> +> Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md). + Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits: * **Shared channels**: Allow seamless communication with internal or external members, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. @@ -18,10 +22,6 @@ Shared and private channels in Microsoft Teams enable flexible collaboration wit Bot and tab apps are supported in shared and private channels. -> [!NOTE] -> -> Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md). - ## Understand channels for app integration When you're building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior: @@ -30,7 +30,7 @@ When you're building or integrating apps with Microsoft Teams, understanding cha |----------|----------------------------------|--------------------------------------------------------------------------------|-------------------------------------| | Standard | All team members by default | Ideal for team-wide collaboration where bots or tabs must be available to everyone | Team’s SharePoint site | | Private | Only to selected team members | Suitable for scenarios requiring restricted access to bots, connectors, or files | Private channel’s SharePoint site | -| Shared | Cross-team and cross-organization | Enables interaction with users outside the host team without requiring them to join the team | Shared channel’s SharePoint site | +| Shared | Cross-team and cross-organization | Enables interaction with users outside the host team without requiring them to join the team | Shared channel’s SharePoint site | ### Capabilities across channels @@ -96,7 +96,7 @@ To enable app support in shared and private channels, perform the following step ### Get context for shared and private channels -When loading the user experience in a shared and private channel, use the data received from the `getContext` call for shared and private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) +When loading the user experience in a shared and private channel, use the data received from the `getContext` call for shared and private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). ### Manage channel membership @@ -164,15 +164,15 @@ To receive app notifications, you must: 1. Install the app in a host team and enable it for the shared channel. For more information on installing the app, see [Install the app](concepts/deploy-and-publish/apps-upload.md). 2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. -To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. For more information, see [Channel membership access](/graph/teams-changenotifications-channelmembership.md). +To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. For more information, see [channel membership](/graph/teams-changenotifications-channelmembership). ```HTTP /teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` ``` -This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) +This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [create a subscription.](/graph/teams-changenotifications-teammembership) -### Handle bulk membership changes +### Handle bulk membership notification changes If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the`sharedWithTeams` subscription resource: @@ -182,7 +182,6 @@ If there are bulk membership changes, Teams curbs individual membership update n The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. -Bots The `conversationUpdate` event is sent to your bot when it receives notifications on membership updates for teams where it is added. To receive both direct and indirect member update notifications, configure your bot with the following prerequisites: 1. Update the app manifest. Add `supportsChannelFeatures`: `tier1` to declare app readiness. @@ -224,7 +223,7 @@ A member removed event is sent to your bot in the following scenarios: 1. When the bot, itself, is uninstalled and removed from a conversation. 2. When a user is removed from a conversation where the bot is installed. -For more information, see [Conversation events.](/graph/teams-changenotifications-teammembership) +For more information, see [conversation events.](/graph/teams-changenotifications-teammembership) If the bot is installed in the team or channel, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, when a shared channel is added to another team. @@ -369,7 +368,7 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers ### Classify members as in-tenant or out-tenant -You can classify members as in-tenant or out-tenant by comparing the 'TenantId' of the member or team with `ownerTenantId` as follows: +You can classify members as in-tenant or out-tenant by comparing the `TenantId' of the member or team with`ownerTenantId` as follows: 1. Get the 'TenantId' of the member you wish to compare. @@ -655,7 +654,3 @@ This failure happens when the tenant’s sharing policy blocks the link type, or * [Build tabs for Teams](../../tabs/what-are-tabs.md) * [App manifest schema for Teams](../../resources/schema/manifest-schema.md) * [Shared channels in Microsoft Teams](/microsoftteams/shared-channels) -* [Channel resource type](/graph/api/resources/channel) -* [Retention policy for Teams locations](/microsoft-365/compliance/create-retention-policies) -* [Use guest access and external access to collaborate with people outside your organization](/microsoftteams/communicate-with-users-from-other-organizations) -* [Manage external meetings and chat with people and organizations using Microsoft identities](/microsoftteams/trusted-organizations-external-meetings-chat?tabs=organization-settings) From 437a495167410cf2f539b5f7d15e6a7188b10a4e Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 3 Oct 2025 09:38:17 +0530 Subject: [PATCH 091/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 45 ++++--------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 1172b11b048..7a4bf928f86 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -72,28 +72,18 @@ Ensure that you understand that how different channels determine app functionali Aggregate or cross-post data across channels only when necessary, to prevent accidental leaks. For example, analytics apps shouldn't include private channel data in team-wide reports unless permissions are clearly defined. -[Back to Top](#microsoft-teams-connect-shared-and-private-channels) +[Back to Top](#apps-for-shared-and-private-channels) ## Enable apps for shared and private channels -<<<<<<< HEAD -Enabling app support in shared and private channels is easy for most apps. If your apps don't depend on channel membership, channel-specific file storage, or deal with cross-channel data access scenarios, you can enable app support with a simple configuration change. - -You can enable your app for shared and private channels, even if your apps don't support the following: -======= You can enable app support in shared and private channels, even if your apps don't: ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c * Use channel or team membership to determine message delivery, task assignment, or permissions * Access or manage files stored in Teams or SharePoint * Combine or share data across multiple channels or teams * Customize experience, based on users (internal, guests, or external members) -<<<<<<< HEAD -To enable app support in shared and private channels, perform the following steps: -======= To enable app support in shared and private channels: ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c 1. Add `supportsChannelFeatures`: `tier1` to your app manifest. 2. Verify expected behavior, and test your app across channels. @@ -105,16 +95,7 @@ To enable app support in shared and private channels, perform the following step ### Get context for shared and private channels -<<<<<<< HEAD -When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. - -See more: - -* [Get context in shared channels](tabs/how-to/access-teams-context.md) -* [Get context for your bot](bots/how-to/get-teams-context.md) -======= When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c ### Manage channel membership @@ -171,19 +152,11 @@ You can manage indirect membership in channels using the following Microsoft Gra >[!NOTE] >The `allowedMembers` API returns only newly associated users and doesn't apply to unshared events. -[Back to Top](#enable-apps-for-shared-and-private-channels) +[Back to Top](#apps-for-shared-and-private-channels) ## Get app notifications for membership changes Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. -<<<<<<< HEAD -Depending on how you install your apps, go to the following section: - -* [Installing apps using Microsoft Graph APIs](#installing-apps-using-microsoft-graph-apis) - -### Installing apps using Microsoft Graph APIs -======= ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c To receive app notifications, you must: @@ -410,7 +383,7 @@ GET /teams/{host-team-group-id}/channels/{channel-id}/allMembers 3. Compare the `TenantId` of the member to the `ownerTenantId` property and determine if the member is an in-tenant or out-tenant. -[Back to Top](#enable-apps-for-shared-and-private-channels) +[Back to Top](#apps-for-shared-and-private-channels) ## Understand app permissions in shared channels @@ -467,7 +440,7 @@ If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder](/graph/api/channel-get-filesfolder). -[Back to Top](#microsoft-teams-connect-shared-and-private-channels) +[Back to Top](#apps-for-shared-and-private-channels) ### Access SharePoint storage correctly for channel files @@ -532,7 +505,7 @@ Use getContext() to retrieve channel context. Compare `user.tenant.id` with `cha 2. Request token from home tenant Call getAuthToken() with the external user's tenant ID (`user.tenant.id` or `tid`) to ensure the token is issued from their home tenant. -[Back to Top](#microsoft-teams-connect-shared-and-private-channels) +[Back to Top](#apps-for-shared-and-private-channels) ## Test your app across channels @@ -570,6 +543,8 @@ Perform the following steps to validate: * This functionality fails if the user is outside your tenant * Confirm that in-channel communication still works. +--- + ### Private channel Create a private channel in Team A with atleast two members (owner and member). @@ -585,9 +560,7 @@ Perform the following steps to validate: 5. Add a new member to the private channel and check: * Whether your app receives a membership change event. * Whether your membership API reflects the new member. - ---- - + Testings across these scenarios help you spot any issues with functionality, permissions, and user experience. ## Best practices for supporting all channels @@ -668,7 +641,7 @@ This failure happens when the tenant’s sharing policy blocks the link type, or
-[Back to Top](#microsoft-teams-connect-shared-and-private-channels) +[Back to Top](#apps-for-shared-and-private-channels) ## Code sample From 411cdfbb579993e659d6edb2f12f40a53d3628f8 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 3 Oct 2025 10:08:02 +0530 Subject: [PATCH 092/109] Update shared-channels.md --- .../build-and-test/shared-channels.md | 534 +++--------------- 1 file changed, 63 insertions(+), 471 deletions(-) diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 29e70b297bd..724ded4269d 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -1,5 +1,5 @@ --- -title: Teams Connects Shared and Private Channels +title: Teams Connect Shared Channels author: surbhigupta description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. ms.author: surbhigupta @@ -8,530 +8,122 @@ ms.topic: conceptual ms.date: 04/09/2025 --- -# Microsoft Teams connect shared and private channels +# Microsoft Teams Connect shared channels -Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits, depending on your channel: +Microsoft Teams Connect shared channels allow members of a channel to collaborate with users across other teams and organizations. You can create and share a shared channel with: -## Understand Channel Models in Microsoft Teams - -When building or integrating apps with Microsoft Teams, understand how different channel types affect visibility, membership, and data storage. - -* **Standard channels:** Accessible to every team member by default. The standard channels support team-wide collaboration and are suitable for scenarios where bots, or tabs, need to be accessible to every team member. Files shared in standard channels are stored in the team’s SharePoint site. - -* **Private channels:** Visible only to a selected subset of team members. The private channels are suited for scenarios that require tighter control over membership and data, such as limiting bots, connectors, or stored files to only members of the private channel. Files shared in private channels are stored in a dedicated SharePoint site, separate from the team’s default site. - -* **Shared channels:** Designed for cross-team and cross-organization collaboration. They support scenarios where app components such as bots and tabs, need to interact with users who aren’t part of the host team, without requiring those users to join the team. Files are managed in the shared channel's SharePoint site. - -## Teams channels – capabilities comparison - -Let's see how Teams channels type differ in their capabilities. - -| **Model** | **Channel Capability** | **Standard Channel** | **Other Channels** | -|----------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------------------| -| **Membership** | Can add people to the channel without adding to the host team | :x: | Supported (Shared channels) | -| | Channel membership can be limited to a subset of the host team | :x: | Supported | -| | Channel can be shared with other teams to inherit members | :x: | Supported (Shared channels) | -| | Channel can be shared directly with its parent team | N/A | Supported (Shared channels) | -| | External users can participate in the channel | :white_check_mark: (B2B collab users) | :white_check_mark: (B2B Direct Connect in Shared channels, B2B collab users in Private channels) | -| | Channel is hosted under a host team | :white_check_mark: | :white_check_mark: | -| **Storage** | Each channel has a dedicated SharePoint site | :x: (Inherits team site) | :white_check_mark: | -| **App Model** | App must be installed in the host team | :white_check_mark: | :white_check_mark: | -| | App installed to host team automatically available in channel | :white_check_mark: | :x: | -| | App must be added to each channel | :x: | :white_check_mark: | - -## Understand channel differences that impact app functionality - -Understanding the difference between Microsoft Teams channel types is essential. Incorrect assumptions about membership, storage, or privacy can lead to broken functionality or unintended data exposure. - -* In private and shared channels, not everyone in the team has access. Only members who are specifically added to the channel can participate in these channels. If your bot targets "everyone," it may violate privacy or miss external members. Always use channel-specific membership APIs to determine the correct members. - -* Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Always validate user roles and tenant IDs before granting permissions or executing actions. - -* Private and shared channels have their own SharePoint sites. If your app targets the wrong site, it may encounter missing files or unauthorized access errors. Always resolve the correct site URL for each channel. - -* Aggregate or cross-post data across channels only when necessary. Keep data scoped to the channel unless clearly defined to prevent accidental leaks. For example, analytics apps should not include private channel data in team-wide reports unless permissions are clearly defined. - -![Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A.](../../assets/images/app-fundamentals/shared-channels-teams.png) | +* Members of another team within the same organization. +* Individuals within the same organization. +* Individuals and other teams of other organizations. > [!NOTE] > -> Don't depend on channel type to determine behavior. Avoid making make any logic decisions based on the channel type in your code. Instead, check for the capabilities your app needs (for example, membership boundaries, storage location, external access) and always use APIs and patterns that work across all channel types. +> * Tab apps in shared channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. +> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. -Use the following guidance to enable app support for shared and private channels. +Teams Connect shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. -## Enable app support for shared and private channels +:::image type="content" source="~/assets/images/app-fundamentals/shared-channels-teams.png" alt-text="Diagram shows Team B from organization A and Team C from organization B collaborating in a shared channel as Team A."::: -You can enable app support for shared and private channels based on whether your app is: - -* Using channel or team membership to determine message delivery, task assignment, or permissions -* Accessing or managing files stored in Teams or SharePoint -* Combining or sharing data across multiple channels or teams -* Customizing the experience based on whether users are internal, guests, or external participants +## Enable your app for shared channels SupportedChannelTypes is an optional property that enables your app in non-standard channels. If your app supports the team scope and the property is defined, Teams enables your app in each channel type accordingly. Private and shared channels are supported. For more information, see [supportedChannelTypes](/microsoft-365/extensibility/schema/root#supportedchanneltypes). -1. Add ```"supportsChannelFeatures": "tier1"``` to your app manifest to enable support for shared and private channels. -2. To verify expected behavior, test your app in standard, private, and shared channels. - -If your app uses any of the preceding features, see the following articles, for more information: - -* [Manage channel membership](#manage-channel-membership) -* [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) -* [Verify if your app is added to a channel](#verify-if-your-app-is-added-to-a-channel) +```JSON + "supportedChannelTypes": [ + "sharedChannels", + "privateChannels" + ] +``` > [!NOTE] > -> * Tab and bot apps in shared and private channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](../sovereign-cloud.md) environments. -> * SharePoint and the SharePoint pages apps aren't supported for shared channels in GCC, GCC High, DoD, and Teams operated by 21Vianet environments. | +> * If your app supports the team scope, it functions in standard channels, regardless of what values are defined in this property. +> * Your app might need to account for the unique properties of each of these channel types in order to function properly. +> * Only **tabs** are currently supported in **private** and **shared** channels in Microsoft Teams. -### Get context for shared and private channels +## Get context for shared channels -When loading the content UX in a shared or private channel, use the data received from `getContext` call for shared or private channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. +When the content UX is loaded in a shared channel, use the data received from `getContext` call for shared channel changes. `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates the shared channel. For more information to enable your tab, see: * [Get context for your tab for private channels](../../tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels) * [Get context in shared channels](../../tabs/how-to/access-teams-context.md#get-context-in-shared-channels) -## Manage channel membership +## Apps and permissions in shared channels -This section explains how to view and manage the membership of Microsoft Teams Channels. - -### Retrieve full channel membership - -To accurately retrieve the all members of any Microsoft Teams channel Standard, Private, or Shared use the ``allMembers`` API: - -```HTTP -GET /teams/{team-id}/channels/{channel-id}/allMembers`` -``` - -This API works across all channel types and returns the actual members of a channel, rather than the broader team members. For shared channels, it also includes indirect members, such as users from other teams who have been granted access. - -### Understand shared channel membership - -Shared channels support three types of membership direct, indirect and external allowing flexible collaboration across teams. - -#### Direct members +You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. -Direct members are users who has been explicitly added to the shared channel itself. Direct members has access to the shared channel regardless of their team membership. +> [!NOTE] +> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. -You can retrieve the list of direct members in a shared channel by using the ``hostTeamGroupID`` obtained from ``getContext`` and calling the appropriate API. This method returns all users who have been explicitly added to the shared channel, including both internal and external participants. +## Get shared channel membership -To retrieve direct members of a shared channel: +You can get direct shared channel membership by using the `hostTeamGroupID` from `getContext` and following these steps: -1. Call the following API: +1. Get direct members with [GET channel members API](/graph/api/channel-list-members?view=graph-rest-beta&tabs=http&preserve-view=true) API. - ```HTTP + ```http GET /teams/{host-team-group-id}/channels/{channel-id}/members ``` -#### Indirect members - -Indirect members are users who can access shared channel through their membership in a team that the channel is shared with. These users are not added directly to the channel but are eligible to participate because their team has been granted access. - -To retrieve indirect members of a shared channel: - -1. Call the following API to identify which teams the channel is shared with: - -```HTTP -GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams -``` +2. Get each shared team with GET `sharedWithTeams` API. -2. Call the following API for each team returned: - -```HTTP -GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{shared-team-id}/allowedMembers -``` - -#### External members - -An external member are users who is not part of your organization but has been granted access to a shared channel through guest access or cross-tenant collaboration. - -To retrieve external members of a shared channel: - -1. Call the following API: - -```HTTP -GET /teams/{host-team-group-id}/channels/{channel-id}/members -``` - -## Get app notifications for direct and indirect membership changes - -### [Graph](#tab/graph) - -Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. To receive these notifications, you must: - -1. [Install the app](../deploy-and-publish/apps-upload.md) in a host team and enable it for the shared channel. -2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. - -To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. To learn more, see [Channel membership access](/graph/teams-changenotifications-channelmembership). - -```HTTP -`/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` -``` - -This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) - -### [Bot Framework](#tab/bot-framework) - -When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. - -```csharp - protected override async Task OnTeamsMembersAddedAsync( - IList membersAdded, - TeamInfo teamInfo, - ITurnContext turnContext, - CancellationToken cancellationToken) - { - var extended = turnContext.Activity.GetChannelData(); - var source = extended?.MembershipSource - ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); - - if (source != null) - { - _logger.LogInformation("MemberAdded via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", - source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); - - await turnContext.SendActivityAsync( - MessageFactory.Text($"👤 Member added via **{source.SourceType}** ({source.MembershipType})."), - cancellationToken); - } - - await base.OnTeamsMembersAddedAsync(membersAdded, teamInfo, turnContext, cancellationToken); -``` - -Similarly, when a member is removed from the channel, the ```OnMembersRemovedAsync``` method is called. This method allows the bot to handle clean-up tasks or adjust access controls as needed. - -```csharp - protected override async Task OnTeamsMembersRemovedAsync( - IList membersRemoved, - TeamInfo teamInfo, - ITurnContext turnContext, - CancellationToken cancellationToken) - { - var source = turnContext.Activity.GetChannelData()?.MembershipSource - ?? (turnContext.Activity.ChannelData as JObject)?["membershipSource"]?.ToObject(); - - if (source != null) - { - _logger.LogInformation("MemberRemoved via {SourceType} ({MembershipType}). SourceId={Id}, TeamGroupId={TeamGroupId}, TenantId={TenantId}", - source.SourceType, source.MembershipType, source.Id, source.TeamGroupId, source.TenantId); - - await turnContext.SendActivityAsync( - MessageFactory.Text($"👋 Member removed (source **{source.SourceType}**, {source.MembershipType})."), - cancellationToken); - } - - await base.OnTeamsMembersRemovedAsync(membersRemoved, teamInfo, turnContext, cancellationToken); - } -``` - -These Bot Framework endpoints are essential for monitoring membership changes and maintaining accurate membership data across shared and private channel. + ```http + GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams + ``` ---- +3. Use GET members of each shared team (Team X) with GET `sharedWithTeams` API. -## Validate user access for membership updates + ```http + GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members -When an app receives a notification for an indirect membership update, it’s important to verify whether the user still has access to the shared channel as the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, the app should confirm whether the user's access is truly lost. Use the ```doesUserHaveAccess``` API to determine whether the user still has access to the shared channel. +## Classify members in the shared channel as in-tenant or out-tenant -```HTTP -GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') -``` +You can classify members as in-tenant or out-tenant by comparing `tenantID` of the member or team with `hostTeamTenantID` as follows: -See [doesUserHaveAccess API](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http) to learn more about user accesses and relevant permissions. +1. Get the member you wish to compare. -## Handle bulk membership changes + ```http + GET /teams/{host-team-group-id}/channels/{channel-id}/members + ``` -If there are bulk membership changes, Teams curbs individual membership update notifications when a channel is shared or unshared with a team. This feature reduces notification volume and improves performance. +2. Use `getContext`, compare the `tenantID` of the member to the `hostTenantID` property. -### Use sharedWithTeams subscription for bulk membership changes + -### [Graph](#tab/graph-bulk) +## Microsoft Entra native identity -To reduce notification overload during membership updates, such as when a shared channel is added to or removed from a team with thousands of members, use the new sharedWithTeams subscription resource: +Apps must function cross-tenants in installation and usage. The following table lists the channel types and their corresponding group IDs: -```HTTP -`/teams/{team-id}/channels/{channel-id}/sharedWithTeams` -``` +|Channel type| groupId | hostTeamGroupId | +|----------|---------|-----------------| +|Regular | Team Microsoft Entra group ID | Team Microsoft Entra group ID | +|Shared | Empty | Host Team Microsoft Entra group ID | -The sharedWithTeams subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the /allMembers API after receiving a "shared with" or "unshared from" team notification. +## Apps in federated group chats with external users > [!NOTE] -> To support membership updates in shared channels, apps using resource-specific consent (RSC) must request extended permissions. -> These permissions let the app: > -> * Access membership data (both direct and indirect members). -> * Receive and respond to membership change notifications. - -### [Bot Framework](#tab/botframework-bulk) - -When a shared channel is added to another team, the Bot Framework might receive a conversationUpdate activity through the ```OnConversationUpdateActivityAsync``` method, but only if the bot is installed in the team or channel. - -```csharp - protected override async Task OnConversationUpdateActivityAsync( - ITurnContext turnContext, - CancellationToken cancellationToken) - { - // Always present on Teams activities - var tcd = turnContext.Activity.GetChannelData(); - var eventType = tcd?.EventType?.ToLowerInvariant(); - - // Read extended shared-channel shape (safe even if fields are absent) - var extended = turnContext.Activity.GetChannelData(); - - // Also keep a raw JObject for logging / future-proof access - var raw = turnContext.Activity.ChannelData as JObject - ?? (turnContext.Activity.ChannelData != null - ? JObject.FromObject(turnContext.Activity.ChannelData) - : new JObject()); - - // Helpful baseline log - _logger.LogInformation("ConversationUpdate eventType={EventType}, channelId={ChannelId}, teamId={TeamId}", - eventType, tcd?.Channel?.Id, tcd?.Team?.Id); - - switch (eventType) - { - case "channelshared": - { - var hostTeam = extended?.Team; // The channel's host team - var sharedWith = extended?.SharedWithTeams ?? new List(); - - _logger.LogInformation("ChannelShared: hostTeam={HostTeamId}, sharedWithCount={Count}", - hostTeam?.Id, sharedWith.Count); - - foreach (var team in sharedWith) - { - _logger.LogInformation("SharedWithTeam: id={Id}, name={Name}, aadGroupId={AadGroupId}, tenantId={TenantId}", - team.Id, team.Name, team.AadGroupId, team.TenantId); - } - - // Optional: surface a quick confirmation in-channel - await turnContext.SendActivityAsync( - MessageFactory.Text($"✅ Channel shared with {sharedWith.Count} team(s)."), - cancellationToken); - break; - } - - case "channelunshared": - { - var unsharedFrom = extended?.UnsharedFromTeams ?? new List(); - - _logger.LogInformation("ChannelUnshared: unsharedFromCount={Count}", unsharedFrom.Count); - - foreach (var team in unsharedFrom) - { - _logger.LogInformation("UnsharedFromTeam: id={Id}, name={Name}, aadGroupId={AadGroupId}, tenantId={TenantId}", - team.Id, team.Name, team.AadGroupId, team.TenantId); - } - - await turnContext.SendActivityAsync( - MessageFactory.Text($"❎ Channel unshared from {unsharedFrom.Count} team(s)."), - cancellationToken); - break; - } - - default: - // No-op; continue normal routing - break; - } - - await base.OnConversationUpdateActivityAsync(turnContext, cancellationToken); - } -``` +> * Apps in federated group chats with external users aren't available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](../cloud-overview.md#teams-app-capabilities), and [Teams operated by 21Vianet](~/concepts/sovereign-cloud.md) environments. +> * Apps aren't supported in one-on-one chats, channels, or meetings with external users. ---- +Teams supports the use of apps in federated group chats with external users. These users can't add, update, or remove apps from the group chat. Only the host of the group chat can add, update, or remove apps. However, all members of the chat, including external users, can use apps under the following conditions: -## Understand app permissions in shared channels +* The tenant admin of the group chat host's organization and the tenant admin of the external user's organization must allow the use of the app in federated group chats. For more information, see [Teams apps for external attendees or guests from outside an organization](/microsoftteams/apps-external-users). +* The app allows access to external users in federated group chats. -You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. +If you're developing an app for use in federated group chats with external users, register your app as a multitenant app in Microsoft Entra ID. This action allows users across multiple organizations to access your app. > [!NOTE] -> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. - -## Verify if your app is added to a channel - -For bots using the Bot Framework SDK, if your bot receives a channelMemberAdded event in a conversationUpdate activity for itself, it indicates that the app is added to the channel. -Begin your channel-specific logic at that point, for example, send a welcome message, fetch the roster, configure tabs, or schedule jobs as needed. Bot events start flowing only after the app is added to the channel - -There’s no direct API to check whether your app is added to a channel. - -> [!NOTE] -> -> * Use ```GET /teams/{team-id}/installedApps```, to list installed apps at the team level. -> * Channel level InstalledApps aren't listed. -> * Avoid using team-level installations to determine which apps are in a channel. - -## Authenticate external users to access app content in SharePoint - -You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. - -### [Tabs](#tab/tabs) - -Save host tenant ID of shared channel where tab is configured. You can get host tenant ID from ```channel.ownerTenantId``` for JSv2 or host tenant ID for JSv1 received under ```getContext``` call. - -### [Bots](#tab/bots) - -For any event payload or action payload received for a bot, use Get hostTenant ID, from ```turnContext.activity.conversation.tenantId```. - ---- - -Now, send saved host tenant ID inside tenantId parameter of getAuthToken call to allow cross-tenant users to access content hosted inside Sharepoint site attached to the shared channel. - -## Identify guest users (B2B guests) in private channels - -You can identify if a member of private channel is guest user, invited to your tenant from external organization, using 'roles' property received for each [conversationMember](/graph/api/resources/conversationmember) object in [List members of a channel - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-list-members) response. - -For guests, “roles” = “guest” - -## Access sharepoint data in shared and private channels - -If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel—not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. - -Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder - Microsoft Graph v1.0 | Microsoft Learn](/graph/api/channel-get-filesfolder). +> If you want to test the [code sample](#code-sample) with an external user in a federated group chat, you must first add the external user as a guest to your tenant. For more information, see [Quickstart: Add a guest user and send an invitation](/entra/external-id/b2b-quickstart-add-guest-users-portal). After adding the user to the tenant, go to the federated group chat and add the guest to test the app. ## Code sample -|Sample name|Description|Node.js| -|-------------|-------------|------| -|Teams Conversation Bot|This sample app displays the names of the members in a federated group chat with external users.|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-feed-members/nodejs/)| - -## Test your app across channel types - -Before publishing updates, validate your app behaves correctly in real situations behaves across all channel types. - -### Standard channel - -Confirm that the existing functionality remains intact after your changes. Ensure tabs, bots and messaging extensions continue to work as expected. - -### Private channel - -Try this setup: Create a private channel P in Team A with atleast two members (one owner, one member). - -Test steps: - -1. Add the app to Team A then add it to private channel P. -2. Verify that your tab loads correctly in the private channel. -3. Test bot responses for different user types: - * In-tenant member - * Guest user - * External user (if applicable) -4. If your app lists members or assigns tasks, confirm it only uses channel members and not the complete team. -5. Add a new member to the private channel and check: - * Whether your bot receives a membership change event - * Whether your membership API reflects the new member. - -### Shared channel (same tenant) - -Try this setup: Create shared channel X in Team A, then share it with Team B (requires owner permissions). - -Test steps: - -1. Add the app to Team A (host team), then to Channel X. -2. Validate that members from Team B. - * Can see the tab - * Receive bot responses -3. Unshare the channel from Team B and confirm: - * Your bot receives a ``channelUnshared`` event - * Membership updates are handled correctly - -### Shared channel (external tenant) - -Try this setup: Use two tenants or collaborate with a colleague from another organization via Teams Connect. - -Test steps: - -1. Have an external user send a message to your bot, does it respond? -2. Trigger a task module or tab interaction as the external user: - * Does authentication succeed? - * If using SSO, ensure ``getAuthToken`` handles the user's home tenant ID correctly. -3. Attempt a direct message from your bot to the external user: - * This will fail if the user is outside your tenant - * Confirm that in-channel communication still works. - -Testing across these scenarios will help you spot any issues with functionality, permissions, and user experience. - -## Best practices for supporting all channels - -Follow these best practices to ensure your app works reliably across all channel types: - -* Always retrieve the current channel’s member list and roles before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. - -* Adjust app functionality and access controls based on user roles (owner, member, guest, external). Limit sensitive actions to owners or internal users, and offer limited features to guests or external participants. - -* Control data access and sharing based on channel membership and permissions. Never include private-channel data in broader reports or public channels unless explicitly authorized. - -* Identify whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when they access files. - -* Update help text and user guides to explain how your app behaves in different channel types, including any limitations for guests or external users. - -* Cache large member lists and use change notifications to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. - -* Test your app across different user roles and channel configurations including owners, members, guests, and external users to confirm it behaves correctly and enforces appropriate permissions. - -* Review Microsoft Teams documentation and changelogs to keep your app aligned with the latest updates to APIs, permissions, and channel configurations. - -## Frequently asked questions - -
-Why isn’t the app visible when trying to add it to a channel? - -If an app isn’t visible when trying to add it to a channel, there are a few likely causes. The app manifest might be missing required support, such as ```"supportsChannelFeatures": tier1```, which enables compatibility with channel features. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. - -
-  -
-
-Why am I getting a 403 error stating "app not enabled in this channel" when calling channel APIs? - -You’ll see a 403 error saying "app not enabled in this channel" if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, first confirm that the app is explicitly added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, ```ChannelMember.Read.Group``` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the ```channelMemberAdded``` event to confirm it has been successfully added to the channel. - -
-  -
-
-Why does the channel roster appear incomplete, showing only owners or missing users? - -If the channel roster appears incomplete showing only owners or missing users, it might be due to using the team members API instead of the correct channel-specific API. To resolve this issue, use the ```/channels/{id}/allMembers``` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. - -
-  -
-
-Why does file access fail for some users even though they're part of the channel? - -This failure can happen if the app is using the team’s main SharePoint site instead of the specific site linked to the channel. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When sharing files, use "people with existing access" links or the invite API to give access to specific users or groups. - -
-  -
-
-Why are external users experiencing authentication issues in tabs or task modules? - -Authentication issues in tabs or task modules for external users often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this authentication issue, check whether the user is external by comparing ```context.user.tenant.id``` with the host or owner tenant ID. If they're different, the user is external, and your app should request the token for the user’s home tenant. You can do this by passing the correct tenant ID (tid) when calling getAuthToken. - -
-  -
-
-How do I know my app was added to a channel? - -This issue might occur if the app is expecting a centralized list of installed apps at the channel level or relying on team-level installation behavior. Currently, there's no channel-level installedApps list available. Bots should instead listen for the channelMemberAdded event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. - -
-  -
-
-Why is my app failing to create message change notifications in shared or private channels? - -Message change notifications might fail in shared or private channels because subscriptions to ```/channels/{id}/messages``` are blocked when using resource-specific consent (RSC) in these types of channels. If your app encounters a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. - -
-  -
-
-Why do file links still fail for external users even after the app is added to the channel? - -This happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the "people with existing access" option or use the invite API to grant access to specific users. Also, make sure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +| Sample name | Description | Node.js | +|-------------|-------------|------|----| +| Teams Conversation Bot | This sample app displays the names of the members in a federated group chat with external users. |[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-feed-members/nodejs/)| ## See also @@ -541,4 +133,4 @@ This happens when the tenant’s sharing policy blocks the link type, or when th * [Channel resource type](/graph/api/resources/channel) * [Retention policy for Teams locations](/microsoft-365/compliance/create-retention-policies) * [Use guest access and external access to collaborate with people outside your organization](/microsoftteams/communicate-with-users-from-other-organizations) -* [Manage external meetings and chat with people and organizations using Microsoft identities](/microsoftteams/trusted-organizations-external-meetings-chat?tabs=organization-settings) +* [Manage external meetings and chat with people and organizations using Microsoft identities](/microsoftteams/trusted-organizations-external-meetings-chat?tabs=organization-settings) \ No newline at end of file From 6ec3194d27539957aac49a13a3e82d45ba276d55 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 3 Oct 2025 10:16:11 +0530 Subject: [PATCH 093/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 7a4bf928f86..8b904eafaa7 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -1,7 +1,7 @@ --- title: Teams connect shared and private channels author: surbhigupta -description: Learn about Teams Connect shared channels to securely collaborate with internal and external users in a shared space without switching tenants. +description: Learn about apps for shared and privated channels to securely collaborate with internal and external users in a shared space. ms.author: surbhigupta ms.localizationpriority: high ms.topic: conceptual From ea5baf4e1e6463d8f2f644ce8ab4147ecf76b544 Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Fri, 3 Oct 2025 10:46:52 +0530 Subject: [PATCH 094/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 8b904eafaa7..d4a96cf1023 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -216,9 +216,7 @@ A member removed event is sent to your bot in the following scenarios: 1. When the bot, itself, is uninstalled and removed from a conversation. 2. When a user is removed from a conversation where the bot is installed. -For more information, see [Conversation events.](/graph/teams-changenotifications-teammembership) - -If the bot is installed in the team or channel, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, when a shared channel is added to another team. +For more information, see [Conversation events.](bots/how-to/conversations/subscribe-to-conversation-events.md) When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. @@ -287,7 +285,7 @@ The `sharedWithTeams` subscription sends a single notification when a channel is ### Shared and unshared with team events -When a shared channel is added to another team, the Agents SDK might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. +If the bot is installed in the team or channel, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, when a shared channel is added to another team. ```csharp protected override async Task OnConversationUpdateActivityAsync( From ac705433c8b3e58c10d6c22c5ea685281ae16a96 Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Fri, 3 Oct 2025 10:53:59 +0530 Subject: [PATCH 095/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index d4a96cf1023..e104ddfdc65 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -197,10 +197,6 @@ The `conversationUpdate` event is sent to your bot when it receives notification 3. Ensure the bot is enabled in the shared channel To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. -<<<<<<< HEAD - -======= ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. From 4fb771107946e4a744d55c73eaa3458eb8ee23cc Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Fri, 3 Oct 2025 11:07:12 +0530 Subject: [PATCH 096/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index e104ddfdc65..b3b6bc90a1a 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -214,8 +214,6 @@ A member removed event is sent to your bot in the following scenarios: For more information, see [Conversation events.](bots/how-to/conversations/subscribe-to-conversation-events.md) -When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. - The following Agents SDK examples apply to both direct and indirect member add and remove events. Member added event @@ -281,7 +279,7 @@ The `sharedWithTeams` subscription sends a single notification when a channel is ### Shared and unshared with team events -If the bot is installed in the team or channel, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, when a shared channel is added to another team. +When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. ```csharp protected override async Task OnConversationUpdateActivityAsync( From 90fb99eb7a980b9a1f922b8dae6f7584a1120bff Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 3 Oct 2025 11:18:43 +0530 Subject: [PATCH 097/109] Up --- msteams-platform/TOC.yml | 3 --- msteams-platform/build-apps-for-shared-private-channels.md | 4 ---- 2 files changed, 7 deletions(-) diff --git a/msteams-platform/TOC.yml b/msteams-platform/TOC.yml index bd8b58c7a65..55f4af0f291 100644 --- a/msteams-platform/TOC.yml +++ b/msteams-platform/TOC.yml @@ -528,9 +528,6 @@ - name: Apps for shared and private channels href: build-apps-for-shared-private-channels.md displayName: shared channels, private channels - - name: Deep link to a tab - href: tabs/how-to/deep-link-to-tab.md - displayName: deep link, link to tab, link to specific content, sub-page in tab - name: Send activity feed notifications href: /graph/teams-send-activityfeednotifications?toc=/microsoftteams/platform/toc.json&bc=/microsoftteams/platform/breadcrumb/toc.json displayName: activity feed, notification, customize notification diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 8b904eafaa7..7d4849e5b50 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -197,10 +197,6 @@ The `conversationUpdate` event is sent to your bot when it receives notification 3. Ensure the bot is enabled in the shared channel To receive member event notifications, install the bot at the team level and manually allow it in the shared channel. -<<<<<<< HEAD - -======= ->>>>>>> 46b0943db27cd2e1d2597c4db06100bf17b4f02c This process ensures the bot is active and authorized to receive notifications for both direct and indirect members. From 4fdb1c766d939f1ee03af0b31d492ac1f03009b5 Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 3 Oct 2025 11:37:22 +0530 Subject: [PATCH 098/109] Updated --- .../build-apps-for-shared-private-channels.md | 12 ++++++++---- .../concepts/build-and-test/shared-channels.md | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index b3b6bc90a1a..c4687c03509 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -212,7 +212,11 @@ A member removed event is sent to your bot in the following scenarios: 1. When the bot, itself, is uninstalled and removed from a conversation. 2. When a user is removed from a conversation where the bot is installed. -For more information, see [Conversation events.](bots/how-to/conversations/subscribe-to-conversation-events.md) +For more information, see [Conversation events.](/graph/teams-changenotifications-teammembership) + +If the bot is installed in the team or channel, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, when a shared channel is added to another team. + +When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. The following Agents SDK examples apply to both direct and indirect member add and remove events. @@ -279,7 +283,7 @@ The `sharedWithTeams` subscription sends a single notification when a channel is ### Shared and unshared with team events -When a new member is added to a shared channel, the ```OnMembersAddedAsync``` method is called. This method provides the context and details of the user who was added, allowing the bot to respond accordingly. +When a shared channel is added to another team, the Agents SDK might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. ```csharp protected override async Task OnConversationUpdateActivityAsync( @@ -430,7 +434,7 @@ This API works across standard and other channels and is recommended for reliabl If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. -Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id--channel-id) and pass in [Get filesFolder](/graph/api/channel-get-filesfolder). +Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id-channel-id) and pass in [Get filesFolder](/graph/api/channel-get-filesfolder). [Back to Top](#apps-for-shared-and-private-channels) @@ -442,7 +446,7 @@ To access a channel’s SharePoint files root, use the following API: GET /teams/{teamId}/channels/{channelId}/filesFolder ``` -This API returns a DriveItem object for that channel's files root. For more, see [channel files](/graph/api/channel-get-filesfolder?view=graph-rest-1.0&tabs=http) +This API returns a DriveItem object for that channel's files root. For more, see [channel files](/graph/api/channel-get-filesfolder?view=graph-rest-1.0&tabs=http&preserve-view=true) Use the following properties for all subsequent file operations: diff --git a/msteams-platform/concepts/build-and-test/shared-channels.md b/msteams-platform/concepts/build-and-test/shared-channels.md index 724ded4269d..3fa5a204076 100644 --- a/msteams-platform/concepts/build-and-test/shared-channels.md +++ b/msteams-platform/concepts/build-and-test/shared-channels.md @@ -78,6 +78,7 @@ You can get direct shared channel membership by using the `hostTeamGroupID` from ```http GET /teams/{host-team-group-id}/channels/{channel-id}/sharedWithTeams/{teamX}/members + ``` ## Classify members in the shared channel as in-tenant or out-tenant From f12f7803c017c1b72f6e70f45d1b97b2eb24fbff Mon Sep 17 00:00:00 2001 From: KirtiJha-MSFT Date: Fri, 3 Oct 2025 12:19:03 +0530 Subject: [PATCH 099/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index c4687c03509..f4a6f10afb6 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -7,12 +7,13 @@ ms.localizationpriority: high ms.topic: conceptual ms.date: 04/09/2025 --- -> [!NOTE] -> -> * Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md). # Apps for shared and private channels +> [!NOTE] +> +> * Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md) + Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits: * **Shared channels**: Allow seamless communication with internal or external members, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. @@ -579,62 +580,61 @@ Testings across these scenarios help you spot any issues with functionality, per ## Frequently asked questions -
-
Why isn’t the app visible when trying to add it to a channel? The app might not appear if the manifest is missing required support, such as `supportsChannelFeatures: tier1`. Additionally, the installer might not have sufficient permissions, only team members or owners can add apps, and local policies must allow app installation. If the channel is an incoming shared channel (shared into a team), apps can't be added directly from that location. In such cases, switch to the host team to add the app to the channel. You can detect whether a channel is shared-in by checking the channel metadata for the host team ID. - -

+  +
Why am I getting a 403 error stating 'app not enabled in this channel' when calling channel APIs? This error occurs if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, `ChannelMember.Read.Group` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the `channelMemberAdded` event to verify successfully addition to the channel. - -

+  +
Why does the channel roster appear incomplete, showing only owners or missing users? The channel roster appears incomplete because the team members API is used instead of the correct channel-specific API. To resolve this issue, use the `/channels/{id}/allMembers` API to retrieve the full channel roster. If the response still shows only owners, the app likely isn't added to the channel. Prompt the user to add the app to the channel, then retry the request to fetch the updated roster. - -

+  +
Why does file access fail for some users even though they're part of the channel? This failure can happen if the app is using the team’s main SharePoint site instead of the channel's specific site. Your organization’s sharing policies might block the type of link, or external users might lack the necessary permissions. To resolve this issue, make sure your app uses the channel’s filesFolder property to get the correct driveId and itemId for file operations. When you're sharing files, use **people with existing access** links or the invite API to give access to specific users or groups. - -

+  +
Why are external users experiencing authentication issues in tabs or task modules? Authentication issues often occur when the app requests a token for the host tenant instead of the user’s home tenant. To resolve this issue, check whether the user is external by comparing `context.user.tenant.id` with the host or owner tenant ID. If they're different, the user is external, and your app must request the token for the user’s home tenant. You can do this step by passing the correct tenant ID (tid) when calling `getAuthToken`. - -

+  +
How do I know my app was added to a channel? This issue might occur if the app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, bots must listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. - -

+  +
Why is my app failing to create message change notifications in shared or private channels? Message change notifications might fail in shared or private channels because subscriptions to `/channels/{id}/messages` are blocked when using resource-specific consent (RSC) in these types of channels. If your app receives a 403 error when attempting to create a subscription, this behavior is expected. To resolve this issue, use on-demand message reads after the app is successfully added to the channel. - -

+  +
Why do file links still fail for external users even after the app is added to the channel? This failure happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, ensure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. - +
[Back to Top](#apps-for-shared-and-private-channels) From fac6d326dc830bd2ea7984d77680c70bf70f373f Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Mon, 6 Oct 2025 08:35:38 +0530 Subject: [PATCH 100/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 101 +++++++++--------- 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index f4a6f10afb6..188fdf701c2 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -282,9 +282,54 @@ If there are bulk membership changes, Teams curbs individual membership update n The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. -### Shared and unshared with team events -When a shared channel is added to another team, the Agents SDK might receive a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, but only if the bot is installed in the team or channel. +## Validate user access for membership updates + +When an app receives a *member removed* notification for an indirect membership update, it’s important to verify whether the user is removed from the channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app must confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. + +```HTTP +GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') +``` + +When an app receives a *member added* notification for an indirect membership update, see the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API to refresh the list of all members. + +```HTTP +GET /teams/{team-id}/channels/{channel-id}/allMembers +``` + +### Classify members as in-tenant or out-tenant + +You can classify members as in-tenant or out-tenant by comparing the 'TenantId' of the member or team with `ownerTenantId` as follows: + +1. Get the 'TenantId' of the member you wish to compare. + +```HTTP +GET /teams/{host-team-group-id}/channels/{channel-id}/allMembers +``` + +2. Call `microsoftTeams.app.getContext()` in your tab from the Teams JavaScript client library. The getContext() call returns context of the shared channel, which contains the details such as `displayName`, `membershipType`, `ownerGroupId`, and `ownerTenantId`. + +3. Compare the `TenantId` of the member to the `ownerTenantId` property and determine if the member is an in-tenant or out-tenant. + +[Back to Top](#apps-for-shared-and-private-channels) + +## Understand app permissions in shared channels + +You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. + +> [!NOTE] +> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. + +## Verify app addition to a channel + +When a shared channel is added to another team, the Agents SDK receives a `conversationUpdate` activity through the `OnConversationUpdateActivityAsync` method, only if the bot is installed in the team. There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. + +Use this `channelMemberAdded` event to trigger app-specific logic such as: + +* Sending a welcome message +* Fetching the channel roster +* Configuring tabs +* Starting scheduled jobs ```csharp protected override async Task OnConversationUpdateActivityAsync( @@ -352,54 +397,6 @@ When a shared channel is added to another team, the Agents SDK might receive a } ``` -## Validate user access for membership updates - -When an app receives a *member removed* notification for an indirect membership update, it’s important to verify whether the user is removed from the channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app must confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. - -```HTTP -GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') -``` - -When an app receives a *member added* notification for an indirect membership update, see the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API to refresh the list of all members. - -```HTTP -GET /teams/{team-id}/channels/{channel-id}/allMembers -``` - -### Classify members as in-tenant or out-tenant - -You can classify members as in-tenant or out-tenant by comparing the 'TenantId' of the member or team with `ownerTenantId` as follows: - -1. Get the 'TenantId' of the member you wish to compare. - -```HTTP -GET /teams/{host-team-group-id}/channels/{channel-id}/allMembers -``` - -2. Call `microsoftTeams.app.getContext()` in your tab from the Teams JavaScript client library. The getContext() call returns context of the shared channel, which contains the details such as `displayName`, `membershipType`, `ownerGroupId`, and `ownerTenantId`. - -3. Compare the `TenantId` of the member to the `ownerTenantId` property and determine if the member is an in-tenant or out-tenant. - -[Back to Top](#apps-for-shared-and-private-channels) - -## Understand app permissions in shared channels - -You can collaborate with external members outside of your organization using shared channels. App permissions in shared channels follow the host team's app roster and host tenant's app policy. - -> [!NOTE] -> The [activity feed notification API](/graph/teams-send-activityfeednotifications) doesn't support cross-tenant notifications for apps in a shared channel. - -## Verify app addition to a channel - -When your bot receives a `channelMemberAdded` event for itself in a `conversationUpdate`, your app is added to the channel. There’s no dedicated API to check if your app is part of a channel. Bots can detect when your app is added to a channel indirectly. - -Use this `channelMemberAdded` event to trigger app-specific logic such as: - -* Sending a welcome message -* Fetching the channel roster -* Configuring tabs -* Starting scheduled jobs - ## Authenticate external users to access app content in SharePoint You need to complete this step when your app stores content in the SharePoint site of the tenant that hosts the channel and requests a SharePoint token. @@ -433,7 +430,7 @@ This API works across standard and other channels and is recommended for reliabl ## Access SharePoint data in shared and private channels -If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Each private channel has its own SPO site that is only accessible to members of that specific shared or private channel. +If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Both shared and private channels have their own SPO site that is only accessible to members of that specific shared or private channel. Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id-channel-id) and pass in [Get filesFolder](/graph/api/channel-get-filesfolder). @@ -565,12 +562,10 @@ Testings across these scenarios help you spot any issues with functionality, per ### Dos * **Always retrieve the current channel’s member list and roles** before performing actions. For example, when sending notifications or assigning tasks, target only the actual channel members and not the entire team. -* **Adjust app functionality and access controls** based on user roles (owner, member, guest, external). * **Control data access and sharing** based on channel membership and permissions. For more information, see [Manage channel membership](#manage-channel-membership). * **Determine** whether users are internal, guests, or external (cross-tenant), and authenticate them in their home tenant. Always validate permissions for cross-tenant scenarios, especially when accessing files. For more information, see [Identify guest users in channels](#identify-guest-users-in-channels) * **Update help text and user guides** to explain how your app behaves in different channel types, including any limitations for guests or external users. * **Use cache large member lists and change notifications** to update them, rather than relying on frequent API calls. For example, refresh your cache only when a membership change event occurs. -* **Validate your app's behavior** across all channel types and user roles. Test with owners, members, guests, and external users to ensure correct permissions and consistent functionality. * **Review Microsoft Teams documentation and changelogs** to stay aligned with the latest updates to APIs, permissions, and channel configurations. ### Don'ts From 047c67f54f4c05857cf6ce7ed715ec7d63cc15e1 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 8 Oct 2025 10:56:47 +0530 Subject: [PATCH 101/109] intro change slight --- msteams-platform/build-apps-for-shared-private-channels.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 188fdf701c2..06b2e029cd7 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -12,16 +12,14 @@ ms.date: 04/09/2025 > [!NOTE] > -> * Apps in shared and private channel is currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md) +> Apps in shared and private channel are currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md) -Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. You can experience multiple benefits: +Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. Currently, Bot and tab apps are supported in shared and private channels. With this ypdate, you can experience multiple benefits: * **Shared channels**: Allow seamless communication with internal or external members, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. * **Private channels**: Provide secure space for selected team members to collaborate on sensitive or confidential content, ensuring privacy and focused discussions within the team. -Bot and tab apps are supported in shared and private channels. - ## Understand channels for app integration When you're building or integrating apps with Microsoft Teams, understanding channel types is crucial, as different channels determine app visibility, user access, and data storage behavior: @@ -282,7 +280,6 @@ If there are bulk membership changes, Teams curbs individual membership update n The `sharedWithTeams` subscription sends a single notification when a channel is shared or unshared with a team. It avoids thousands of per-user notifications and improves performance for apps that monitor membership changes. Ensure that you update the shared channel member list using the [allMembers](/graph/api/channel-list-allmembers?view=graph-rest-1.0&tabs=http&preserve-view=true ) API after receiving a *shared with* or *unshared from* team notification. - ## Validate user access for membership updates When an app receives a *member removed* notification for an indirect membership update, it’s important to verify whether the user is removed from the channel, especially since the same user might have both direct and indirect membership. For example, if a user is removed from a team that shares a channel, your app must confirm whether the user's access to the shared channel is revoked. Use the `doesUserHaveAccess` API to determine whether the user is removed from the shared channel. See [doesUserHaveAccess](/graph/api/channel-doesuserhaveaccess?view=graph-rest-beta&tabs=http&preserve-view=true ) API to learn more about user accesses and relevant permissions. From 358341636b57c96d8b889a905bdd6990f58f6b21 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 8 Oct 2025 13:23:59 +0530 Subject: [PATCH 102/109] changes incorporated --- .../build-apps-for-shared-private-channels.md | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 06b2e029cd7..b2ab309ce0b 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -14,7 +14,7 @@ ms.date: 04/09/2025 > > Apps in shared and private channel are currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md) -Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. Currently, Bot and tab apps are supported in shared and private channels. With this ypdate, you can experience multiple benefits: +Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. Currently, Bot and tab apps are supported in shared and private channels. With this update, you can experience multiple benefits: * **Shared channels**: Allow seamless communication with internal or external members, without changing the user’s context. These channels ensure secure granular access control and real-time membership syncing. @@ -57,15 +57,15 @@ Ensure that you understand that how different channels determine app functionali * **Use channel-specific membership APIs** - Don't assume that team membership is equal to channel membership. Only members who are added to the channel can participate in shared and private channels. If your bot targets everyone, it might violate privacy or miss external members. + Don't assume that team membership is equal to channel membership. Only members who are added to the channel can participate in shared and private channels. * **Distinguish between users and roles** - Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). Your app must distinguish between these roles to manage access, data visibility, and feature availability. Validate user roles and tenant ids before granting permissions. + Channel members might include in-tenant users, guests, or cross-tenant users (external users from other tenants). If your app needs to distinguish between various users to manage access, data visibility, and feature availability, then you must validate user roles and tenant IDs before granting permissions. * **Don't assume a single SharePoint site tied to a team** - Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. + Unlike standard channels, which all share sharpoint site with the team, Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. * **Keep data scoped to channels** @@ -75,18 +75,29 @@ Ensure that you understand that how different channels determine app functionali ## Enable apps for shared and private channels -You can enable app support in shared and private channels, even if your apps don't: +Most apps can support shared and private channels with a simple manifest update. Based on either of the following scenarios, you can decide the approach: + +* [Apps with no dependence on specified parameters](#apps-with-no-dependence-on-specified-parameters) +* [Apps with dependence on specified parameters](#apps-with-dependence-on-specified-parameters) + +### Apps with no dependence on specified parameters + +If your app doesn’t: * Use channel or team membership to determine message delivery, task assignment, or permissions * Access or manage files stored in Teams or SharePoint * Combine or share data across multiple channels or teams * Customize experience, based on users (internal, guests, or external members) - To enable app support in shared and private channels: +then, you only need to: 1. Add `supportsChannelFeatures`: `tier1` to your app manifest. 2. Verify expected behavior, and test your app across channels. +### Apps with dependence on specified parameters + +If your app handles advanced scenarios, or depends on the specified prameters listed in the [Apps with no dependence on specified parameters](#apps-with-no-dependence-on-specified-parameters) section, then read through this guide for targeted updates and the best practices. Don't re-write your code. + > [!NOTE] > > * Tab and bot apps in shared and private channels are available in [Government Community Cloud (GCC), GCC High, Department of Defense (DoD)](concepts/cloud-overview.md), and [Teams operated by 21Vianet](concepts/sovereign-cloud.md) environments. From 8c72e04bcb62324e5cbbc77cf52aba66b22ebeb8 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 8 Oct 2025 13:48:10 +0530 Subject: [PATCH 103/109] part 3 changes --- .../build-apps-for-shared-private-channels.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index b2ab309ce0b..3c83051672d 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -12,7 +12,7 @@ ms.date: 04/09/2025 > [!NOTE] > -> Apps in shared and private channel are currently in developer preview [Public developer preview](resources/dev-preview/developer-preview-intro.md) +> Apps in shared and private channel are currently in [Public developer preview](resources/dev-preview/developer-preview-intro.md). Shared and private channels in Microsoft Teams enable flexible collaboration within teams and across organizations. Currently, Bot and tab apps are supported in shared and private channels. With this update, you can experience multiple benefits: @@ -65,7 +65,7 @@ Ensure that you understand that how different channels determine app functionali * **Don't assume a single SharePoint site tied to a team** - Unlike standard channels, which all share sharpoint site with the team, Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. + Unlike standard channels, which share SharPoint site with the team, Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. * **Keep data scoped to channels** @@ -94,6 +94,8 @@ then, you only need to: 1. Add `supportsChannelFeatures`: `tier1` to your app manifest. 2. Verify expected behavior, and test your app across channels. +There is no dependence on classical and admin access for `supportsChannelFeatures`: `tier1`. + ### Apps with dependence on specified parameters If your app handles advanced scenarios, or depends on the specified prameters listed in the [Apps with no dependence on specified parameters](#apps-with-no-dependence-on-specified-parameters) section, then read through this guide for targeted updates and the best practices. Don't re-write your code. @@ -121,12 +123,12 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers * **Indirect members:** Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. * **External members:** Guest users, who aren't part of your organization but are granted access to a shared channel through guest access or cross-tenant collaboration. -Additionally, you can identify whether a member of a shared channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access to a shared channel: +You can identify whether a member of a shared or private channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access the channels: -| Member Type | Annotation | Description | -|-----------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Direct Member | Yes | The user is added directly to the shared channel. | -| Indirect Member | Yes | The user accesses the shared channel through another team. The `@microsoft.graph.originalSourceMembershipUrl` property includes a URL that points to the source team and indicates indirect membership. | +|Member Type |Annotation scope | +|---------|---------| +|Direct member | The `@microsoft.graph.originalSourceMembershipUrl` property shows that the user is directly added to the channels | +|Indirect member |The `@microsoft.graph.originalSourceMembershipUrl` property includes a URL that points to the source team and indicates indirect membership. | > [!NOTE] > You might receive duplicate notifications when a member is added to a shared channel. This scenario can happen if the member is already part of the shared channel directly or indirectly. Use the `allMembers` API to view all the direct and indirect members. Ignore the notification if the member already exists, either directly or indirectly. @@ -141,7 +143,7 @@ You can manage indirect membership in channels using the following Microsoft Gra GET /teams/{team-id}/channels/{channel-id}/allMembers ``` -* Use the `doesUserHaveAccess` API to determine whether the user is removed from the channel and can view all user accesses and relevant permissions. +* Use the `doesUserHaveAccess` API to determine whether the user is removed from the channel and can view all user accesses and relevant permissions. Apps with classic application permissions and RSC permissions can use this API. ```HTTP GET /teams/{team-id}/channels/{channel-id}/doesUserHaveAccess(userId='@userid',tenantId='@TenantID',userPrincipalName='@UserPrincipalName') From 40f9688bad99801a3f187962e9e44d8438bda3fb Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 8 Oct 2025 13:54:51 +0530 Subject: [PATCH 104/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 3c83051672d..60f8b491bf5 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -178,7 +178,7 @@ To receive app notifications, you must: To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. For more information, see [Channel membership access](/graph/teams-changenotifications-channelmembership.md). ```HTTP -/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true` +/teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true ``` This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) From 203b9a7b96d27b78a39c24b2bc3c3933d7e1760b Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Tue, 14 Oct 2025 13:01:31 +0530 Subject: [PATCH 105/109] Update build-apps-for-shared-private-channels.md --- .../build-apps-for-shared-private-channels.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 60f8b491bf5..1b9dfce6c1f 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -121,7 +121,6 @@ GET /teams/{team-id}/channels/{channel-id}/allMembers * **Direct members:** Users who are added directly to the channel, including users from other tenants (cross-tenants). * **Indirect members:** Users who are members of the team, with which the channel is shared, including teams in the same tenant or in a cross-tenant. -* **External members:** Guest users, who aren't part of your organization but are granted access to a shared channel through guest access or cross-tenant collaboration. You can identify whether a member of a shared or private channel is direct or indirect by checking the `@microsoft.graph.originalSourceMembershipUrl` annotation. This property identifies the source of a member’s access the channels: @@ -166,13 +165,13 @@ You can manage indirect membership in channels using the following Microsoft Gra [Back to Top](#apps-for-shared-and-private-channels) -## Get app notifications for membership changes +## Get app notifications for graph membership changes -Apps installed in shared channels receive notifications when users are added to or removed from a team that shares the channel. +Apps installed in shared and private channels receive notifications when users are added to or removed from a team that shares the channel. To receive app notifications, you must: -1. Install the app in a host team and enable it for the shared channel. For more information on installing the app, see [Install the app](concepts/deploy-and-publish/apps-upload.md). +1. Install the app in a host team and enable it for the shared or private channel. For more information on installing the app, see [Install the app](concepts/deploy-and-publish/apps-upload.md). 2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. For more information, see [Channel membership access](/graph/teams-changenotifications-channelmembership.md). @@ -181,7 +180,9 @@ To receive both direct and indirect member update notifications, you must includ /teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true ``` -This subscription enables apps to monitor membership changes in shared channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) +This subscription enables apps to monitor membership changes in channels and its associated teams. For more information on how to create a Microsoft Graph change notification subscription, see [Create a subscription.](/graph/teams-changenotifications-teammembership) + +## Get app notifications for bot membership changes The `conversationUpdate` event is sent to your bot when it receives notifications on membership updates for teams where it is added. To receive both direct and indirect member update notifications, configure your bot with the following prerequisites: From f1997cdf13c88d840e1c836aed993bbc466e03a5 Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Tue, 14 Oct 2025 15:23:30 +0530 Subject: [PATCH 106/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 1b9dfce6c1f..21ccf3b6408 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -107,7 +107,7 @@ If your app handles advanced scenarios, or depends on the specified prameters li ### Get context for shared and private channels -When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#retrieve-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). +When loading the user experience in a shared or private channel, use the data received from the `getContext` call for shared or private channels. The `getContext` call publishes two new properties, `hostTeamGroupID` and `hostTenantID`, which are used to retrieve channel membership using Microsoft Graph APIs. `hostTeam` is the team that creates both private and shared channels. For more information, see [Get context in shared channels](tabs/how-to/access-teams-context.md#get-context-in-shared-channels) and [Get context for your tab for private channels](tabs/how-to/access-teams-context.md#retrieve-context-in-private-channels). ### Manage channel membership @@ -174,7 +174,7 @@ To receive app notifications, you must: 1. Install the app in a host team and enable it for the shared or private channel. For more information on installing the app, see [Install the app](concepts/deploy-and-publish/apps-upload.md). 2. Create a valid Microsoft Graph change notification subscription to monitor associated team membership changes and shared or unshared events using supported APIs. -To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. For more information, see [Channel membership access](/graph/teams-changenotifications-channelmembership.md). +To receive both direct and indirect member update notifications, you must include both the query string parameters when creating a subscription. If the query strings aren't provided, the subscription only delivers notifications for direct member updates. For more information, see [Channel membership access] ```HTTP /teams/{team-id}/channels/getAllMembers?notifyOnIndirectMembershipUpdate=true&suppressNotificationWhenSharedUnsharedWithTeam=true From ed0945f56d4de71302c0fbf4268ee7f2313c14ce Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Tue, 14 Oct 2025 15:40:48 +0530 Subject: [PATCH 107/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 21ccf3b6408..7fb9e4aa9f4 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -656,7 +656,7 @@ This failure happens when the tenant’s sharing policy blocks the link type, or * [Manage channel membership](#manage-channel-membership) * [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) -* [Build tabs for Teams](../../tabs/what-are-tabs.md) +* [Build tabs for Teams](tabs/what-are-tabs.md) * [App manifest schema for Teams](../../resources/schema/manifest-schema.md) * [Shared channels in Microsoft Teams](/microsoftteams/shared-channels) * [Channel resource type](/graph/api/resources/channel) From 9c23c33d2ceb6c603f7bd75f38eebf3d59ce7ed3 Mon Sep 17 00:00:00 2001 From: v-shgarcha Date: Tue, 14 Oct 2025 16:43:45 +0530 Subject: [PATCH 108/109] Update build-apps-for-shared-private-channels.md --- msteams-platform/build-apps-for-shared-private-channels.md | 1 - 1 file changed, 1 deletion(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 7fb9e4aa9f4..7e381be7ea9 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -657,7 +657,6 @@ This failure happens when the tenant’s sharing policy blocks the link type, or * [Manage channel membership](#manage-channel-membership) * [Understand app permissions in shared channels](#understand-app-permissions-in-shared-channels) * [Build tabs for Teams](tabs/what-are-tabs.md) -* [App manifest schema for Teams](../../resources/schema/manifest-schema.md) * [Shared channels in Microsoft Teams](/microsoftteams/shared-channels) * [Channel resource type](/graph/api/resources/channel) * [Retention policy for Teams locations](/microsoft-365/compliance/create-retention-policies) From cca152dd1e2c3fb75b0c18ee3233126eddd5d545 Mon Sep 17 00:00:00 2001 From: NehaHEDAU-MSFT Date: Wed, 15 Oct 2025 15:59:45 +0530 Subject: [PATCH 109/109] Acrolinx and warnings --- .../build-apps-for-shared-private-channels.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/msteams-platform/build-apps-for-shared-private-channels.md b/msteams-platform/build-apps-for-shared-private-channels.md index 7e381be7ea9..a3e005d60fa 100644 --- a/msteams-platform/build-apps-for-shared-private-channels.md +++ b/msteams-platform/build-apps-for-shared-private-channels.md @@ -1,7 +1,7 @@ --- title: Teams connect shared and private channels author: surbhigupta -description: Learn about apps for shared and privated channels to securely collaborate with internal and external users in a shared space. +description: Learn about apps for shared and private channels to securely collaborate with internal and external users in a shared space. ms.author: surbhigupta ms.localizationpriority: high ms.topic: conceptual @@ -65,7 +65,7 @@ Ensure that you understand that how different channels determine app functionali * **Don't assume a single SharePoint site tied to a team** - Unlike standard channels, which share SharPoint site with the team, Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. + Unlike standard channels, which share SharePoint site with the team, Private and shared channels have their own SharePoint sites. Always use the correct URL for each channel, to avoid missing files or unauthorized access errors. * **Keep data scoped to channels** @@ -89,16 +89,16 @@ If your app doesn’t: * Combine or share data across multiple channels or teams * Customize experience, based on users (internal, guests, or external members) -then, you only need to: +Then, you only need to: -1. Add `supportsChannelFeatures`: `tier1` to your app manifest. -2. Verify expected behavior, and test your app across channels. +1. Add `supportsChannelFeatures`: `tier1` to your app manifest +2. Verify expected behavior, and test your app across channels -There is no dependence on classical and admin access for `supportsChannelFeatures`: `tier1`. +There's no dependence on classical and admin access for `supportsChannelFeatures`: `tier1`. ### Apps with dependence on specified parameters -If your app handles advanced scenarios, or depends on the specified prameters listed in the [Apps with no dependence on specified parameters](#apps-with-no-dependence-on-specified-parameters) section, then read through this guide for targeted updates and the best practices. Don't re-write your code. +If your app handles advanced scenarios, or depends on the specified parameters listed in the [Apps with no dependence on specified parameters](#apps-with-no-dependence-on-specified-parameters) section, then read through this guide for targeted updates and the best practices. Don't rewrite your code. > [!NOTE] > @@ -184,7 +184,7 @@ This subscription enables apps to monitor membership changes in channels and its ## Get app notifications for bot membership changes -The `conversationUpdate` event is sent to your bot when it receives notifications on membership updates for teams where it is added. To receive both direct and indirect member update notifications, configure your bot with the following prerequisites: +The `conversationUpdate` event is sent to your bot when it receives notifications on membership updates for teams where it's added. To receive both direct and indirect member update notifications, configure your bot with the following prerequisites: 1. Update the app manifest. Add `supportsChannelFeatures`: `tier1` to declare app readiness. @@ -431,7 +431,7 @@ You can identify if a member of a channel is a guest user, invited to your tenan For guests, 'roles' = 'guest' -To accurately, retrieve the all guest users in a channel use the following `allMembers` API: +To accurately retrieve the all guest users in a channel, use the following `allMembers` API: ```HTTP GET /teams/{team-id}/channels/{channel-id}/allMembers @@ -443,7 +443,7 @@ This API works across standard and other channels and is recommended for reliabl If you're building an app using [SharePoint](/sharepoint/dev/spfx/integrate-with-teams-introduction) Framework, you need to use the SharePoint Online (SPO) site linked to the shared channel, not the one linked to the host team group. Both shared and private channels have their own SPO site that is only accessible to members of that specific shared or private channel. -Use the Graph API to access the document library of the SPO site linked to a shared or private channel. Ensure you pass the Team ID and Channel ID received from the [Get Host Team Group ID & Channel ID](#get-host-team-group-id-channel-id) and pass in [Get filesFolder](/graph/api/channel-get-filesfolder). +Use the Microsoft Graph invite API to access the document library of the SPO site linked to a shared or private channel. [Back to Top](#apps-for-shared-and-private-channels) @@ -486,7 +486,7 @@ External users remain in their tenant while accessing the host channel’s share The channel’s SharePoint site automatically grants access to all channel members, including tenants. -Esnure the following: +Ensure that you: * Avoid using organization-wide sharing links they typically exclude external users. * Use specific-people sharing, or rely on membership-based permissions. @@ -563,8 +563,8 @@ Perform the following steps to validate: * Guest user or external user 4. If your app lists members or assigns tasks, confirm it only uses channel members and not the complete team. 5. Add a new member to the private channel and check: - * Whether your app receives a membership change event. - * Whether your membership API reflects the new member. + * Whether your app receives a membership change event + * Whether your membership API reflects the new member Testings across these scenarios help you spot any issues with functionality, permissions, and user experience. @@ -596,7 +596,7 @@ The app might not appear if the manifest is missing required support, such as `s
Why am I getting a 403 error stating 'app not enabled in this channel' when calling channel APIs? -This error occurs if the app is installed at the team level but hasn’t been added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, `ChannelMember.Read.Group` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the `channelMemberAdded` event to verify successfully addition to the channel. +This error occurs if the app is installed at the team level but isn't added to the channel. To resolve this issue, confirm that the app is added to the channel. If your app uses resource-specific consent (RSC), verify that the permissions declared in the manifest match the API calls being made, for example, `ChannelMember.Read.Group` for reading channel membership. After adding the app, retry the operation. For bots, initiate channel-specific logic when the bot receives the `channelMemberAdded` event to verify successfully addition to the channel.
 
@@ -624,7 +624,7 @@ Authentication issues often occur when the app requests a token for the host ten
How do I know my app was added to a channel? -This issue might occur if the app is expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, bots must listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error. +This issue might occur if the app expects a centralized list of installed apps at the channel level or relies on team-level installation behavior. Currently, there's no channel-level installedApps list available. Instead, bots must listen for the `channelMemberAdded` event within the channel to detect when they're added. When the app gets a 403 error and misses the event, it asks the user to add the bot to the channel and manages the error.
 
@@ -638,7 +638,7 @@ Message change notifications might fail in shared or private channels because su
Why do file links still fail for external users even after the app is added to the channel? -This failure happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, ensure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site. +The message change notification failure happens when the tenant’s sharing policy blocks the link type, or when the user doesn’t have access to the item, even if they’re a member of the channel. Another common cause is that the app might generate links pointing to the team drive instead of the channel’s dedicated drive. To resolve this issue, reissue the links using the 'people with existing access' option or use the invite API to grant access to specific users. Also, ensure the links reference the channel drive, which can be identified using the filesFolder property, rather than the team site.