1
votes

We use the Microsoft Graph API "POST teams/v1.0" to create Microsoft Teams team programmatically. This endpoint allows the creation of teams with predefined content such as settings, apps, channels, and tabs. However, we started facing today issues when trying to create a team with predefined tabs. The problem can be easily reproduced in Microsoft Graph Explorer. This is what the sample request looks like:

POST https://graph.microsoft.com/v1.0/teams

{
    "[email protected]": "https://graph.microsoft.com/v1.0/teamsTemplates('standard')",
    "visibility": "Private",
    "displayName": "Sample Engineering Team",
    "description": "This is a sample engineering team, used to showcase the range of properties supported by this API",
    "channels": [
        {
            "displayName": "Announcements ????",
            "isFavoriteByDefault": true,
            "description": "This is a sample announcements channel that is favorited by default. Use this channel to make important team, product, and service announcements."
        },
        {
            "displayName": "Training ????️",
            "isFavoriteByDefault": true,
            "description": "This is a sample training channel, that is favorited by default, and contains an example of pinned website and YouTube tabs.",
            "tabs": [
                {
                    "[email protected]": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.web')",
                    "displayName": "A Pinned Website",
                    "configuration": {
                        "contentUrl": "https://docs.microsoft.com/microsoftteams/microsoft-teams"
                    }
                },
                {
                    "[email protected]": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.youtube')",
                    "displayName": "A Pinned YouTube Video",
                    "configuration": {
                        "contentUrl": "https://tabs.teams.microsoft.com/Youtube/Home/YoutubeTab?videoId=X8krAMdGvCQ",
                        "websiteUrl": "https://www.youtube.com/watch?v=X8krAMdGvCQ"
                    }
                }
            ]
        },
        {
            "displayName": "Planning ???? ",
            "description": "This is a sample of a channel that is not favorited by default, these channels will appear in the more channels overflow menu.",
            "isFavoriteByDefault": false
        },
        {
            "displayName": "Issues and Feedback ????",
            "description": "This is a sample of a channel that is not favorited by default, these channels will appear in the more channels overflow menu."
        }
    ],
    "memberSettings": {
        "allowCreateUpdateChannels": true,
        "allowDeleteChannels": true,
        "allowAddRemoveApps": true,
        "allowCreateUpdateRemoveTabs": true,
        "allowCreateUpdateRemoveConnectors": true
    },
    "guestSettings": {
        "allowCreateUpdateChannels": false,
        "allowDeleteChannels": false
    },
    "funSettings": {
        "allowGiphy": true,
        "giphyContentRating": "Moderate",
        "allowStickersAndMemes": true,
        "allowCustomMemes": true
    },
    "messagingSettings": {
        "allowUserEditMessages": true,
        "allowUserDeleteMessages": true,
        "allowOwnerDeleteMessages": true,
        "allowTeamMentions": true,
        "allowChannelMentions": true
    },
    "discoverySettings": {
        "showInTeamsSearchAndSuggestions": true
    },
    "installedApps": [
        {
            "[email protected]": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.vsts')"
        },
        {
            "[email protected]": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('1542629c-01b3-4a6d-8f76-1938b779e48d')"
        }
    ]
}

This is what the error response includes:

[
   "message":"Tabs with duplicate DisplayName are not allowed.",
   "errorCode":"Unknown",
   "message":"'Channel Name' must not be empty.",
   "errorCode":"Unknown",
   "message":"'Channel Name' should not be empty.",
   "errorCode":"Unknown",
   "message":"'Channel Name' must not be empty.",
   "errorCode":"Unknown",
   "message":"'Channel Name' should not be empty.",
   "errorCode":"Unknown"
]

If the JSON object doesn't contain any tab configuration, the POST v1.0/teams endpoint works correctly. Here the test scenarios we covered:

  • POST beta/teams API
  • POST v1.0/teams API
  • delegated permission
  • application permission

Thoughts?

2

2 Answers

0
votes

I haven't been able to test this, but I'm suspecting your tab json should have a displayName property instead of name. As I don't see a name property listed here: https://docs.microsoft.com/en-us/graph/api/resources/teamstab?view=graph-rest-1.0

So your tabs section would be:

"tabs":[
   {
      "[email protected]":"https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.web')",
      "displayName":"A Pinned Website",
      "configuration":{
         "contentUrl":"https://docs.microsoft.com/microsoftteams/microsoft-teams"
      }
   },
   {
      "[email protected]":"https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.youtube')",
      "displayName":"A Pinned YouTube Video",
      "configuration":{
         "contentUrl":"https://tabs.teams.microsoft.com/Youtube/Home/YoutubeTab?videoId=X8krAMdGvCQ",
         "websiteUrl":"https://www.youtube.com/watch?v=X8krAMdGvCQ"
      }
   }
]

Edit: I just tried it, and couldn't get it to work either.

But, I've found a workaround by first posting the complete request without the tabs section, and then adding the tab(s) separately by posting to https://graph.microsoft.com/v1.0/teams/{team-id}/channels/{channel-id}/tabs

The way I did this manually (I'm sure there are better ways to retrieve to team-id and channel-id):

  1. Post the request without the tabs section.
  2. Retrieve the id of the created team with GET https://graph.microsoft.com/v1.0/me/joinedTeams.
  3. Call GET https://graph.microsoft.com/v1.0/teams/{team-id}/channels to retrieve the channels.
  4. I posted the tab segment below to https://graph.microsoft.com/v1.0/teams/{team-id}/channels/{channel-id}/tabs, and retrieved a 201 created response.
{
    "[email protected]": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.web')",
    "displayName": "A Pinned Website",
    "configuration": {
        "contentUrl": "https://docs.microsoft.com/microsoftteams/microsoft-teams"
    }
}
0
votes

This was an issue to do with payload that has channels with tabs - not the name or displayName properties. It has been fixed in MS Graph v1.0.

Also note that both name and displayName on the tabs will work but the documented property is displayName so I suggest you switch to that instead of name.

Here is a sample of a payload I have tested myself. The example in documentation should work with displayName on the tabs configuration.