Copying files to Private Channel using Graph API

I was approached with a scenario: Once I have created a Private Channel how can I automatically copy files there? Since I didn’t have a direct answer it was time to open Graph Explorer and start digging.

Create a Private Channel

You need to have a suitable team first.
/me/joinedTeams is quite a good Graph API path for that.
Store that TeamID and create a private channel:

POST 
https://graph.microsoft.com/beta/teams/{TeamID}/channels
{
  "@odata.type": "#Microsoft.Teams.Core.channel",
  "membershipType": "private",
  "displayName": "Inner loop",
  "description": "This is for private content"
}

In return you get a Private Channel ID. Store that too. Just for kicks check that do you get any tabs returned.

https://graph.microsoft.com/v1.0/teams/{TeamID}/channels/{PrivateChannelID}/tabs?$expand=teamsApp

Of course you don’t get any tabs. Posts and Files are not returned with tabs query!
So let’s create tab.

POST
https://graph.microsoft.com/v1.0/teams/{TeamID}/channels/{PrivateChannelID}/tabs
{
  "displayName": "website",
  "teamsApp@odata.bind" : "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/com.microsoft.teamspace.tab.web",
  "configuration": {
     "contentUrl": "https://yourtenant.sharepoint.com/sites/intranet"
  }
}

Now if you try to retrieve tabs you get the website tab in the return set.

Get the Site

If you are thinking to use the source team to retrieve private channel’s drive.. you are going down the wrong path easily.


Facts:
#1: Private Channel is it’s own site collection.
#2: Private Channel is not a group
#3: Private channel site collection is named: sourceteamsite-privatechannelname


First we need to get the source team’s site collection name.

https://graph.microsoft.com/beta/groups/{TeamID}/sites/root

Store the Sitename and add private channel internal name to it without spaces.

Now we can retrieve the Site information:

https://graph.microsoft.com/beta/sites/yourtenant.sharepoint.com:/sites/storemanagers-innerloop

Again: store the SiteId. This id is a long one.

Get the Drive and Folder ID

Next: get drives of the Site. You need to look for the Document Library ( wheredriveType=”documentLibrary in the result set)

https://graph.microsoft.com/beta/sites/{SiteID}/drives

Store the Document Library Drive id

And no, you are not done. You need to retrieve the drive’s root id.

https://graph.microsoft.com/beta/drives/{DocumentLibraryDriveID)/root

Store the RootID

Now.. Retrieve all items of that drive’s root.

https://graph.microsoft.com/beta/drives/{DocumentLibraryDriveID}/items/{RootID}/children

There should be only one entity: the folder named by your Private channel team! Store PrivateChannelFolderID.

Copy the file into Private Channel

Copying file is tricky if you don’t pay attention. You need to use URL for the source file and JSON body for the target (=your Private channel folder).

POST
https://graph.microsoft.com/beta/drives/{SourceDocumentLibraryDriveID)/items/{SourceItemID}/copy
{
  "parentReference": {
    "driveId": "{DocumentLibraryDriveID}",
    "id": "{PrivateChannelFolderID}"
  },
  "name": "Teams Spotlight 20200218.pptx"
}

And you are done!

You can retrieve files with Graph API using /drives/{DocumentLibraryDriveID}/items/{PrivateChannelFolderID}/children

But of course it is easier to check with Teams app:

And yes – that is the new Files Experience. It just appeared on my dev tenant today!

7 thoughts on “Copying files to Private Channel using Graph API

  1. I’m using your tutorial to copy the files from template private channel to new private channel, but after creating the private channel with http request the private channel Sharepoint site is not created and power automate gives me error saying site can’t be found. How did your script worked?

    Like

    1. That article is two years old. There has been API changes since that.
      First @odata.type needs to be changed #Microsoft.Teams.Core.channel –> #Microsoft.Graph.channel
      Once you have the Site ID, you retrieve the drive
      https://graph.microsoft.com/beta/sites/{Site ID}/drive
      Get the root
      https://graph.microsoft.com/beta/drives/{Drive ID}/root
      Get folder
      https://graph.microsoft.com/beta/drives/{Drive ID}/items/{Root ID}/children
      List files under folder
      https://graph.microsoft.com/beta/drives/{Drive ID}/items/{Folder ID}/children

      Surprisingly this time this all worked without touching the Files-tab in Teams. So provisioning when creating private channels has been fixed.

      Perhaps you had the error in odata.type, since it was changed also. Alternatively I recommend doing a few seconds wait (or even 15) after creation – that process is not necessarily happening at the same instant.

      Like

      1. Hi Vesa,
        I can’t seem to get this work. When trying to fetch site information from private channel. Power Automate gives me “Requested site could not be found” error. When I try to go to that URL it gives me “404 File no found” error. Not until I go to Teams and two times go to Files tab (because first time gives error) the private channel Sharepoint site is created. How did you get yours to work? Can you advice me?

        Like

  2. Hi Vesa,
    I can’t still get the site ID, because when I run this command: (with my site info)
    https://graph.microsoft.com/beta/sites/yourtenant.sharepoint.com:/sites/storemanagers-innerloop
    It just gives me error:
    “code”: “itemNotFound”,
    “message”: “Requested site could not be found”,

    I don’t know what I’m doing wrong, but the site isn’t created until I go to the Files tab twice (first time error, second time it works). Then this request works, but if I want to automate the site creation with private channels, I can’t make user to go to the files tab, in order to automation to finish the site creation.

    Could you share your knowledge in this matter?

    Liked by 1 person

    1. Hi, it looks like when my flow creates a new team, the site information can’t be found. But if I create new team by hand, then this method of yours works. I have contacted Microsoft to solve this issue. Thanks for you help.

      Liked by 1 person

      1. Sorry for the delay in answering. I am sorry for your issues there, and I hope Microsoft can help you with that. I didn’t have any extra tricks there on my part. I did all tests in Graph Explorer, not using Power Automate. Some of those calls are asynchronous but I think you have thought about that and added delays after async actions?

        Like

      2. Dont know, but it sounds like the sharepoint site has not been initialized. The sharepoint site behind a private channel is not provisioned when creating the channel. You will either have to manually access the “files” tab once to initialize, or you can run this graph request once: /teams/{id}/channels/{id}/filesFolder

        Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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