Dynamics 365 entities, like accounts or opportunities, can be displayed inside of a tab on a Microsoft Teams channel. The tab can be added manually with just few simple steps, but sometimes it might be needed to automatically provision the tab, for example linking an account to General channel during team creation.
On this blog post I’ll go through the basics what are required when provisioning Dynamics 365 tab and to make collaboration integration work correctly. For examples I’m using Flow created with Power Automate. Flow creates a new team, when new account is created, and configures Dynamics 365 tab.
Adding a Dynamics 365 tab manually
For configuring a Dynamics 365 tab for the first time, Environment and Dynamics 365 sales app needs to be selected.

After that is done, only thing needed is searching and picking a Dynamics 365 entity to be displayed.

And when checked from Dynamics 365 side, clicking Collaborate button on that linked entity it shows that connection is made.

Seems fairly easy to reproduce in provisioning solution.
Dynamics 365 tab configuration
There isn’t actually official documentation what is required for Dynamics 365 tab configuration. Easiest way to discover tab configuration is utilizing Microsoft Graph Explorer (https://developer.microsoft.com/en-us/graph/graph-explorer/preview) and reading configuration from a Teams channel, where tab is already configured.
Here is the complete Dynamics 365 tab configuration fetched from Graph API (HTTP GET: https://graph.microsoft.com/v1.0/teams/<team id>/channels/<channel id>/tabs).
{
"id": "535c1c4e-05ea-4ece-948e-f1f0605c1a72",
"displayName": "D365",
"webUrl": "https://teams.microsoft.com/l/channel/19%3a679cea04927947f3b5600c036a26ea4b%40thread.skype/tab%3a%3a9a2016df-9080-4cce-afd2-8ec94b50bdd4?webUrl=https%3a%2f%2forg-x.crm4.dynamics.com%2fmain.aspx%3fappid%3d10d23763-ba41-ea11-a813-000d3a6542c9%26pageType%3dentityrecord%26etn%3daccount%26id%3d714ce340-3b64-ea11-a811-000d3a654ce0&label=D365&groupId=cf373130-41cf-4556-9717-0d3bfdd9a655&tenantId=a8e7d2ad-32f9-4ee6-9fbe-f8ebe1f48871",
"configuration": {
"entityId": null,
"contentUrl": "https://msteamstabintegration.crm.dynamics.com/Home/Bootstrapper#pageType=dynamics-host&dynamicsUrl=https%3A%2F%2Forg-x.crm4.dynamics.com%2Fmain.aspx%3Fappid%3D10d23763-ba41-ea11-a813-000d3a6542c9%26pageType%3Dentityrecord%26etn%3Daccount%26id%3D714ce340-3b64-ea11-a811-000d3a654ce0%26navbar%3Doff%26flags%3DFCB.AllowLegacyDialogsInUci%3Dfalse",
"removeUrl": "https://msteamstabintegration.crm.dynamics.com/Home/Bootstrapper#pageType=tab-remove",
"websiteUrl": "https://org-x.crm4.dynamics.com/main.aspx?appid=10d23763-ba41-ea11-a813-000d3a6542c9&pageType=entityrecord&etn=account&id=714ce340-3b64-ea11-a811-000d3a654ce0"
}
}
Sections needed for provisioning are contentUrl, removeUrl and websiteUrl. Teams AppId is also required, which is for Dynamics 365 tab cd2d8695-bdc9-4d8e-9620-cc963ed81f41.
Example: Creating a team and a Dynamics 365 tab with Power Automate
For adding a Dynamics 365 tab to display an entity on Teams channel, you need to add Dynamics 365 app to a team, add a new tab to a channel and create Microsoft Teams Collaboration entity to Common Data Service (CDS). On my example I’m also provisioning a new team, when new Account is created on Dynamics 365.
Required parameters
For building a tab call these parameters are needed. For Dynamics, open an entity and you can get all needed parameters from the browser.
- Environment – first part of Dynamics 365 Url, for examples https://org-x.crm4.dynamics.com
- (Sales) AppId – Query string parameter appid
- Organization ID – found from Dynamics on Setting -> Customizations -> Developer Resources and there Instance Reference Information
And when utilizing Power Automate, you need to create a new app registration to Azure AD and consent Group.ReadWrite.All permission to Microsoft Graph API, and use Tenant ID, Client ID and Client Secret on HTTP actions to call Graph.
More information about creating an Azure AD App Registration can be found here: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
My suggestion is to add all the required parameters as variables or store variables on a custom Common Data Service configuration entity.
Flow trigger
Flow is triggered with When a record is created CDS trigger and it trigger, when new Account entity is created.

Creating a team
For creating a team, first correct user id is needed from CDS. In the example the account owner is added as a team owner. For getting correct user id, Get record CDS action is used with returned Owner id from the trigger.

Next team is created with HTTP action. Action call Microsoft Graph Beta API teams endpoint. Entity name is the account name from the trigger, it is just added as a variable. For owners data bind user id is azureactivedirectoryobjecid, which is returned from Get User CDS action. Dynamics 365 teams app is also to newly created team in the same call.

Body of the call:
{ "template@odata.bind": "https://graph.microsoft.com/beta/teamsTemplates('standard')", "displayName": "@{variables('EntityName')}", "description": "", "owners@odata.bind": [ "https://graph.microsoft.com/beta/users('@{body('Get_User')?['azureactivedirectoryobjectid']}')" ], "installedApps": [ { "teamsApp@odata.bind": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/cd2d8695-bdc9-4d8e-9620-cc963ed81f41" } ] }
After the call, id of the newly created team needs to be retrieved. The simple way is to just add a delay and parse the id from the Location header of the returned object, because usually team is created within seconds.
Location: /teams/{teamId}/operations/{operationId}
For my example I created a loop, which handles the status returned from Create Team call defined in Location header.

Creating a Dynamics 365 tab
A tab is created simply by doing a HTTP POST call to Graph’s tab endpoint.
https://graph.microsoft.com/v1.0/teams/<team id>/channels/<channel id>/tabs
More info: https://docs.microsoft.com/en-us/graph/api/teamstab-add?view=graph-rest-1.0
I have created variables for ContentUrl and WebUrl parameters, where Environment and SalesAppId are variables described earlier, EntityType is account and EntityId is accountid returned from the trigger.


Channel id the the General channel on newly created team is also needed and it can be retrieved by calling:
https://graph.microsoft.com/beta/teams/<team id>/primaryChannel

In my example channel id is also set as variable for later use.

Next Dynamics 365 tab can be created.

After running the call, Dynamics 365 tab is visible on the channel.

Creating a Teams collaboration entity to CDS
Finally Microsoft Teams Collaboration entity needs to be added to Common Data Service, otherwise collaboration features are not working correctly on the Dynamics 365 entity.
What needs to be added?
To see what is actually added to Common Data Service, add a tab to a channel using Teams in the browser. Using browser’s developer tools, you can see that HTTP POST call is made to PostPinTasks endpoint with CrmTeamsCollabEntity object.

Next table describes properties of CrmTeamsCollabEntity.
Property | Property on CDS action | Value |
---|---|---|
RegardingObjectID | Related Dynamics 365 Record ID | ID of the Dynamics 365 Entity |
RegardingObjectType | Related Dynamics 365 Record ID (Entity Code) | Dynamics 365 entity type code |
RegardingObjectTypeName | Related Dynamics 365 Record Type Name | Dynamics 365 entity type name |
msdyn_ChannelFolderRelativeUrl | Collaboration Channel Relative Folder URL | Teams Channel Folder URL, i.e. /sites/<team name>/<channel name> |
msdyn_ChannelID | Collaboration Channel ID | Teams Channel ID |
msdyn_ChannelName | Collaboration Channel Name | Teams Channel Name |
msdyn_ChannelType | Collaboration Channel Type | Teams channel type (regular/private) |
msdyn_GroupID | Collaboration Group Identifier | Team id |
msdyn_TeamID | Collaboration Team ID | Teams channel id |
msdyn_TeamName | Collaboration Team Name | Team Name |
msdyn_TeamSiteURL | Team Site Url | URL of the underlying team site on SharePoiint |
msdyn_TenantID | Collaboration Tenant Identifier | Tenant ID |
msdyn_WebUrl | Collaboration tab web url | Tab web url (from tab configuration) |
msdyn_appId | Collaboration app id which was used to pin | ID of the Dynamics 365 Entity |
msdyn_ContentUrl | Collaboration tab content url | Tab content url (from tab configuration) |
msdyn_pipedEntityId | Collaboration piped entity id which was used | Contains Dynamics 365 organization id, Sales app id, entity id, entity code and entity name |
Retrieve the required parameters and create a CDS entity
For getting all required information, two Graph API calls are needed to get Url of the underlying team site, channel folder Url and Url of the default Documents library.


Finally Microsoft Teams Collaboration Entity can be created.

Next table explains properties, which are added as expressions
Property | Value |
---|---|
Collaboration Channel Relative Folder URL | Replacing ‘%20’ with ‘ ‘ on webUrl returned from Get Team Drive action and adding General channel URL (‘/General’) |
Team Site URL | webUrl returned from Get team site action |
Collaboration Channel Name | name returned from Get Team Drive action |
Collaboration Team Name | displayName returned from Get team site action |
When CDS collaboration entity is created correcly, you can see a collaboration entitity by clicking Collaborate on the account.

And files are also linked correctly on Document Associated Grid.

Findings
Here are my finding when I was investigating the CDS configuration.
When a team or a channel is created via Microsoft Graph API, a folder related to a channel is not available before you actually open the Files tab on Teams. Document Associated Grid also returns an error, before Files tab is accessed for the first time.
Also calling Microsoft Graph’s Get a DriveItem endpoint (/teams/{teamId}/channels/{channelId}/filesFolder), NotFound error is returned with a message “Sharepoint folder not found.”. Endpoint is available currently on Beta version, so that might be the issue. Workaround is to generate channel related folder URL based on SharePoint site URL, document library URL and channel name. This configuration is included in the example.
Afterword
When provisioning tabs to Microsoft Teams, which are integrating external systems, you need to take care of what is happening during tab creation. As you can see in this case, there is also some configuration happening outside Microsoft Teams. You can get some clues using a browser and browser’s developer tools to see what calls are created to external API’s. And, if there isn’t any documentation available, you just need to try things out and learn. Use Microsoft Graph Explorer for testing and debugging your Graph API calls, and when ready move them to your provisioning solution.
You can find my example Flow on my Github account: https://github.com/mpaukkon/Microsoft365Dev/blob/master/PowerAutomate/Dynamics365TabToTeams/Dynamics365tabintegration.zip
Hi, thanks for this, very helpful!
I’m actually facing the issue with the SP library not provisioned for created Teams, but I cannot apply your workaround as both calls fail.
In my case the ‘drive’ call fails with:
“code”: “ResourceNotFound”,
“message”: “Unable to provision resource.”,
and ‘sites/root’
“code”: “ResourceNotFound”,
“message”: “Resource provisioning is in progress. Please try again.”,
LikeLike
Hi, I’ve been using this integration for some time now and it’s been working great, unfortunately since yesterday it has stopped working! The tabs added fail to load with a http 500 error. It looks like MS has made some changes as if you look into the network traffic you can see the error message as: AADSTS65001: The user or administrator has not consented to use the application with ID ’44a02aaa-7145-4925-9dcd-79e6e1b94eff’ named ’Microsoft Dynamics 365 Apps Integration’. Send an interactive authorization request for this user and resource.
I’m seeing it in multiple tenants so I expect it’s affecting everyone. Have you seen this issue?
LikeLike