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!
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?
LikeLike
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.
LikeLike
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?
LikeLike
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?
LikeLiked by 1 person
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.
LikeLiked by 1 person
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?
LikeLike
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
LikeLiked by 1 person