Provisioning Teams with a SharePoint Site Template, Power Automate and Microsoft Graph
Last updated on September 3, 2023
Microsoft recently added an option to create a team for an Office 365 group via its modern team site. There is a a button at the bottom of the left-hand side navigation that allows you to create a Team with a single click. This is a great change and makes it easier to create a team for a particular group — especially if you are already browsing its site.
But could things be made even easier? Why can’t we just have an option during team site creation to have the team created straight away, automatically? Actually, we can, and in this blog post, I’ll show you how we can make that happen.
To achieve this, we are taking advantage of SharePoint site templates, Microsoft Power Automate and Microsoft Graph. The target is that when a user creates a new modern team site via the SharePoint Online UI, a team will get created for it automatically. The site is created using a custom site template, which will trigger a Power Automate flow, where we’ll call Microsoft Graph to provision the team.
Table of Contents
- The Power Automate flow
- Creating a SharePoint Site Template to trigger our Power Automate flow
- Afterword
The Power Automate flow
Let’s create the Power Automate flow first. We’ll start by adding a When HTTP request is received trigger and inserting the schema below into it. We use this trigger, because the site template triggerFlow action makes a HTTP request to our Power Automate flow. The schema matches the body of the request.
{ "type": "object", "properties": { "webUrl": { "type": "string" }, "parameters": { "type": "object", "properties": { "event": { "type": "string" }, "product": { "type": "string" } } } } }
After that, add a Compose action and use the expression below to extract the last bit of the site URL, so we can use it in other actions.
last(split(triggerBody()?['webUrl'], '/'))
Now save the flow and note down the URL that appeared in the trigger. We’ll need it later when we create our site script.
Calling Microsoft Graph from Power Automate
Before you can call Microsoft Graph from Power Automate, you need to set up an application registration in your Azure Active Directory. To do that, follow the instructions I’ve given in my other blog post: How to set up an Azure AD application registration for calling Microsoft Graph. We are going to use client credentials for authentication, so just follow the instructions under the application identity chapter. When setting the permissions, select Sites.Read.All and Group.ReadWrite.All permissions.
After your app registration is set up, note down the tenant ID, client ID and client secret as described in the Information required for authentication chapter. In Power Automate, add three Initialize variable actions and insert those values into them. We will need to use these values in three different places, so it will be a lot faster to configure those actions when you can just select them from dynamic content. Also, if you later want to copy this flow to a different tenant, you only need to update the values in these three variables to get your flow working against a new application registration.
Getting the group ID
Before we can create a Team for an Office 365 group, we need to know its group ID. When a user creates a new Office 365 group enabled team site using our site template, the group gets created automatically, but the only information we get in Power Automate about the created site is the site URL we extracted earlier. Quite often the site name in the URL matches the group mailNickname, but not always. Because of this, we can’t simply fetch the group information from Graph with query $filter=mailNickname eq ‘siteurl’. Instead, we need to take a little detour.
We first need to get the site object from Graph using the site URL we extracted earlier (Output in the image below), and parse the response, so we can use the response content in other actions.
Schema:
{ "type": "object", "properties": { "@@odata.context": { "type": "string" }, "createdDateTime": { "type": "string" }, "description": { "type": "string" }, "id": { "type": "string" }, "lastModifiedDateTime": { "type": "string" }, "name": { "type": "string" }, "webUrl": { "type": "string" }, "displayName": { "type": "string" }, "root": { "type": "object", "properties": {} }, "siteCollection": { "type": "object", "properties": { "hostname": { "type": "string" } } } } }
The response includes the site ID, which we can use to get the Documents library of the site, also known as the drive. The drive is shared by both the site and the Office 365 group objects, and as you can see from the response schema, the information we receive includes information about the owner > group > id. Right there is the group ID we need.
{ "type": "object", "properties": { "@@odata.context": { "type": "string" }, "createdDateTime": { "type": "string" }, "description": { "type": "string" }, "id": { "type": "string" }, "lastModifiedDateTime": { "type": "string" }, "name": { "type": "string" }, "webUrl": { "type": "string" }, "driveType": { "type": "string" }, "createdBy": { "type": "object", "properties": { "user": { "type": "object", "properties": { "displayName": { "type": "string" } } } } }, "owner": { "type": "object", "properties": { "group": { "type": "object", "properties": { "email": { "type": "string" }, "id": { "type": "string" }, "displayName": { "type": "string" } } } } }, "quota": { "type": "object", "properties": { "deleted": { "type": "integer" }, "remaining": { "type": "integer" }, "state": { "type": "string" }, "total": { "type": "integer" }, "used": { "type": "integer" } } } } }
Creating the team
During Ignite, Microsoft added support for application permissions for the Create team operation. Until then, you were required to authenticate to Graph using a set of user credentials with a Teams license to be able to utilize the operation. When a set of service credentials were used to take care of the automatic provisioning, it could become a problem in large organizations, because a single user is allowed to create only 250 teams. But luckily that is no longer the case and we are able to use application permissions for this operation as well.
Here is an example of the body, but you can of course alter the team settings to fit your purpose.
{ "memberSettings": { "allowCreateUpdateChannels": true }, "messagingSettings": { "allowUserEditMessages": true, "allowUserDeleteMessages": true }, "funSettings": { "allowGiphy": true, "giphyContentRating": "strict" } }
Now our Power Automate flow is ready and overall it should look like this. Make sure you’ve saved it, and let’s move on to create a site script for our site template.
Creating a SharePoint Site Template to trigger our Power Automate flow
Create a site script (JSON file) with the following content. Replace the URL with the one from your flow trigger.
{ "$schema": "schema.json", "actions": [ { "verb": "triggerFlow", "url": "https://prod-57.westeurope.logic.azure.com:443/workflows/9bb732 ...", "name": "Team site + Teams", "parameters": { "event": "Microsoft Event", "product": "SharePoint" } } ], "bindata": { }, "version": 1 };
You might also want to include some other configurations in the site script while at it, such as activating a company branded theme for the site. If you are interested in doing that or want to know more about site templates and site scripts in general, check out my Ultimate Guide to SharePoint Site Templates and Site Scripts. It has been very popular among readers.
When your site script is finished, deploy it with this PowerShell script. You’ll also create the site template for it at the same time. If you have not yet installed the SharePoint Online Management Shell, check this other blog post for instructions.
$adminSiteUrl = "https://laurakokkarinen-admin.sharepoint.com" $siteScriptFile = "C:\site-script.json" # path to site script file $webTemplate = "64" # 64 = Office 365 group connected team site $siteScriptTitle = "Team site + Teams" $siteDesignTitle = "Team site + Teams" $siteDesignDescription = "Custom team site template which provisions a Team via Power Automate." $previewImageUrl = "" # if left empty, the default preview image will be used. Connect-SPOService $adminSiteUrl $siteScript = (Get-Content $siteScriptFile -Raw | Add-SPOSiteScript -Title $siteScriptTitle) | Select -First 1 Id Add-SPOSiteDesign -SiteScripts $siteScript.Id -Title $siteDesignTitle -WebTemplate $webTemplate -Description $siteDesignDescription -PreviewImageUrl $previewImageUrl
Now you should be able to see your site template listed in the drop-down menu when creating a new modern team site in SharePoint Online. When you use it, you’ll get a team site and a Teams team for it automatically. You also retain the default Team Site template, which you can still use when you just want a team site but don’t want a team for it. Note that if your tenant has restrictions regarding who are allowed to create Office 365 groups, the custom site template is only visible to those users who can.
Afterword
Workspace provisioning is always interesting. The more we can automate and optimize, the better! I hope you enjoyed reading this article and found it useful. Or perhaps it sparked up your imagination? Let me know in the comments below if you have an interesting idea or if you’ve already built some useful provisioning solutions utilizing the site template -> Power Automate pipeline.
Also, feel free to take a look at my other articles, and follow me on Twitter if you’d like to get a tweet from me when I publish new content. Thank you for reading and until next time!
Laura
Hi Laura,
Great article and thanks for sharing! I am having an issue with the last item in the Flow HTTP PUT to create the Team from the Group GUID. It comes with the following error: “groupId needs to be a valid GUID.”
Any help would be appreciated! Thanks again! 🙂
“error”: {
“code”: “BadRequest”,
“message”: “groupId needs to be a valid GUID.”,
“innerError”: {
“date”: “2020-10-01T10:33:16”,
Hi Alan,
Make sure the group ID matches the GUID format and no additional characters have slipped in the URL.
Laura
Thank you so much for documenting! I had to do a bit of a variation and create a custom connector as I do not have access to premium connectors but I was able to get a team created from a Site creation!
Excellent, Kathy!
Hi Laura
This is really helpful, The flow runs successfully, Call it from Site Script, and the run was successful.
But a small hitch, The notification in new Team site – .[Create a Team with a single click. This is a great change and makes it easier to create a team for a particular group — especially if you are already browsing its site.], want to hide that as well, Is it possible? From where it’s coming?
Thank you
ananda
Hi Ananda,
The “Create a team” link will disappear automatically soon — but not immediately — from the team site after the team has been created.
Laura
Hello Laura
Thank you for another wonderful post, But I’m getting error at last step – Create Team.
{
“error”: {
“code”: “Request_BadRequest”,
“message”: “Specified HTTP method is not allowed for the request target.”,
“innerError”: {
“date”: “2020-07-19T16:01:07”,
“request-id”: “66834978-50ea-44f1-9d79-9afffc69b1ff”
}
}
}
I’ve set up the API Permission like following. Still no luck.
Directory.ReadWrite.All, – Delegated
Directory.ReadWrite.All – Application
Group.ReadWrite.All – Delegated
Group.ReadWrite.All – Application
Sites.Read.All – Application
Team.Create – Delegated
Team.Create – Application
Team.ReadBasic.All -Delegated
Team.ReadBasic.All – Application
Could you please help,
Thank you
ananda
Hi Ananda,
Sounds like you have a wrong HTTP method selected for that action. Please make sure it is “PUT”.
Laura