How to add a SharePoint content as a tab in Teams channel using Graph API

With European Collaboration Summit 2021 closing in, I am focusing this time on more Graph API since my session at the event is about Microsoft Teams Graph API. Adding a SharePoint page to the team is just one of examples I do during my session. I will be also adding a Power App, Whiteboard, OneNote and do a lot more with Graph API on a team context.

Adding a SharePoint page to a team during provisioning is something people ask me about. I did write about this couple of years ago in my blog but I think it is time to highlight the information up again.

Officially adding a SharePoint page as a team channel tab with configuration is not supported. We can add a page anyway! 😎

It does state that it is the configuration is not supported, but also tries to make us adding it via Website tab. That would create issues with authentication, so we don’t want to go to that direction. Instead we use SharePoint app to add the pag to team channel as a tab.

Steps needed

  1. Get URL to the page
  2. Have URL to the team site
  3. Format the content URL from site and page URL
  4. Create JSON payload
  5. Call Graph API to add the tab
  6. Done!

I assume you have the URL for the page you are going to add already. And also the URL for the team site. This covers steps 1 and 2 and we can focus on the formatting of content URL. We need also to add encoding to the site address and page file name. Content URL is formatted like this:

https://{siteaddress}/_layouts/15/teamslogon.aspx?spfx=true&dest={encodedsiteaddress}%2FSitePages%2FHome.aspx

It is important to create the Content URL in this format, to take advantage of authentication.

How I do this in my demo PowerShell is the following:

$spcontentURL = $targetsiteURL + '/_layouts/15/teamslogon.aspx?spfx=true&dest='
$spencodedURL = $targetsiteURL
$spencodedURL = $spencodedURL.Replace("/", "%2F")
$spencodedURL = $spencodedURL.Replace(":", "%3A")
$spcontentURL = $spcontentURL + $spencodedURL
$spcontentURL = $spcontentURL + '%2FSitePages%2FHome.aspx'

I assume (and know) that the only thing I need to care about are spaces and / characters. You need to also have a Website URL to the page there, so it can be opened easily in the web by pressing the globe button.

$spWebsiteUrl = $targetsiteURL + '/SitePages/Home.aspx'

Building the payload is not complicated. You are using the TeamsAppID there to identify SharePoint application. The ID is given in the Docs page.

$spJSON = '
{
"teamsAppId": "2a527703-1f6f-4559-a332-d8a7d288cd88",
"name": "SharePoint tab",
"displayName": "SharePoint Home page",	
"sortOrderIndex": "10000",	
"configuration": {
        "contentUrl": "'+ $spcontentURL + '",
        "websiteUrl": "' + $spWebsiteUrl + '",          	
}}
'

Graph API is the same as adding any other tab to the channel.

https://graph.microsoft.com/beta/teams/{teamID}/channels/{ChannelID}/tabs

In my demo I just place the tab to the General channel.

$piTabsURI = "https://graph.microsoft.com/beta/teams/" + $teamID + "/channels/" + $PrimaryChannelID + "/tabs"
$graphResponse = Invoke-RestMethod -Method Post -Uri $piTabsURI -Headers @{"Authorization" = "Bearer $accessToken" } -Body $spJSON -ContentType "application/json"

Testing it out

After running the script we can see SharePoint Home page added to the team channel tabs

And we also see it has been connected to the the SharePoint application – just like we intended to. We can change the tab target normally from there if we want to.

And it works on mobile Teams also without requiring any extra authentication

It is not just for SharePoint pages

You can use the new SharePoint application to attach also Document Libraries and Lists to the team as a channel tab.

Document Libraries and Lists: pay attention to the contentURL format. Use the earlier stated format:

https://{siteaddress}/_layouts/15/teamslogon.aspx?spfx=true&dest={encodedurl}%2F_layouts%2F15%2Flistallitems.aspx%3Fapp%3DteamsPage%26listUrl%3D%2Fsites%2F{sitename}%2F{encodeddoclibname}

The same applies for Lists for most parts. Remember to encode URL and use teamslogon.aspx format for contentUrl .

https://{siteaddress}/_layouts/15/teamslogon.aspx?spfx=true&dest={encodedURL}%2FLists%2F{encodedlistName}%2FAllItems.aspx%3Fp%3D11

WebsiteUrl is just encoded URL (.webUrl) to Doclib or List.

💡The easiest way to get familiar with these is to add a tab to a team and use Graph Explorer to fetch channel tabs to see details and formats.

Using Graph API to add a SharePoint Home page – or other SharePoint resources – to the team during provisioning will it easier for the team to start utilizing and adding relevant content there.

9 thoughts on “How to add a SharePoint content as a tab in Teams channel using Graph API

  1. Hi
    If I create a team and then add that team´s SharePoint home page to that team´s channel as a tab I don´t get any warning.
    I guess you are talking about a bit different situation (“with configuration”).

    Like

    1. I am indeed referring to Teams Graph API documentation when adding a tab to a channel.. When adding a tab manually, or even when using Graph API to add a SharePoint app is a different situation. Adding a SharePoint page as tab has been there for years, without warning (SharePoint app has changed also during those years).

      Like

  2. Hello Mr.Metaverse,

    I have created a Custom Connector with an action to add a Sharepoint Library Tab to a Channel. My problem is that I can add “…/Shared Documents” as the Content URL, but I cannot add “…/Shared Documents/Subfolder1/ as Content URL. I get the error message “Not Found”. I know that the subfolder is there. Can you tell me why I gen an error? I have tried encoding the full URL and also encoding only from “/Sites/” and onward. Nothing works.
    I don’t understand your libarry example above, because you use some path that does not look like Sharepoint libraries. All I get from that example is that the URL should be encoded, which does not seem to work for me.

    BR,
    Thomas the API Noob

    Like

    1. Hi Thomas

      You can only add Document Library, not a specific folder, as far as I know. If you go to Teams and add manually SharePoint tab you can see available options.

      And as for the library example I think you mean this one:
      https://siteaddress/_layouts/15/teamslogon.aspx?spfx=true&dest=encodedurl%2F_layouts%2F15%2Flistallitems.aspx%3Fapp%3DteamsPage%26listUrl%3D%2Fsites%2Fsitename%2Fencodeddoclibname

      This has SSO inside it – that mechanism is used in various places but I admit it can look a bit confusing. Document library details are in encodeddoclibname part. Basically it is an URL from the site (encoded url)/layouts/15/listallitems.aspx and so on until it ends with /sitename/doclibname.

      Like

      1. Hi Vesa,
        OK, so I have now moved everything at the same level as “Shared Documents” and now I’m able to add the tabs. But.. there is always a but.. I now have problems assigning rights. I tried two ways:

        1. Using the Sharepoint connector “Grant access to an item or folder” (addroleassignment) to assign rights to the folder fails, because root folders don’t have IDs and that is required.

        2. Using “addroleassignment” in a “Send an HTTP request to SharePoint” connector fails, because, using “/_api/web/SiteUsers/getByEmail(…)”, I can only get the PrincipalID of the serviceuser (maby because it created the directories or the Team/Group?). I use a custom connector to get the ID of a distribution Group and I loop over the users in the group getting the PrincipalIDs using their UPNs. I have created a forum post on this here:
        https://powerusers.microsoft.com/t5/Building-Flows/getByEmail-to-get-userprincipalid/m-p/1463409#M163892

        If you can see solutions where I’m stuck, or can think of a third option, I will be forever greatful 🙂

        BR,
        Thomas

        Like

  3. Just thinking that can’t you add those permissions to the site (Office 365 Group) instead of just to Document Library? Giving people contribute permissions would grant them permissions to DocLibs that inherit their permissions from the site.

    It is possible to retrieve DocLib root ID via Graph AP. I didn’t check if that would be useful in your scenario.

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.