Teams templates allow creating teams with pre-defined channels, applications, and tabs. The goal of templates is to standardize team deployment across the organization and for rapidly deploying teams for specific reasons, such as project management or retail stores. Microsoft has several pre-defined templates for the healthcare, education, and retail sectors.

Just recently, Microsoft released the ability to create your own custom templates in the Teams admin center. This allows for defining your own templates to match your organization’s specific requirements.

In this post, I’m going to cover how to create your first custom Teams template. I’ll then show you how to create a team using a template with the Graph API.

If you are new to the Graph API, you can check out my other two articles on getting started with Graph API:

Getting Started with Microsoft Teams and Graph API
Creating Microsoft Teams and Channels with Graph API and PowerShell

Create a Teams Template

First, let’s create a Teams template we’ll later use with our Graph API calls. Navigate out to the Teams admin center at In the menu on the left, select Teams, then Teams templates. Here is a list of current templates available for help desk, patient care, or organizing a retail store. From here, go ahead and select the + Add button.

In the Create a template wizard, we have the option to create our template from scratch, from an existing team, or from an existing template. For our demo, let’s create a brand new template.

Selecting team template starting point
Selecting the template starting point

The next page contains more information about the template, including a name, a short and long description, and the locale for the template. The template we’re building is going to be specifically for managing projects in the IT department.

Filling out the team descriptions
Filling out the team descriptions

Next we set up how we want the team to be structured on the next screen. We can create what channels should appear in the team along with any applications for the channel. We can also configure the channel to be shown by default. For our IT Projects template, there will be 4 channels:

  • General
  • Announcements
  • Project Planning with Planner and OneNote tabs
  • Code Talk with the Azure DevOps tab

When adding an app, it will appear as a tab in the channel. The app name will appear as the tab name but this is also customizable. You can also install apps for the entire team instead of just adding as a tab. I’m going to add the Praise app into the team as well.

Adding channels to a template

When we submit the template, it will appear in the list of our templates. Select the template to view the information for the template, including the template ID, which we’ll need later on.

Viewing custom template information
Viewing custom template information

Creating a Team from a Template

Back in the Teams client, navigate to the teams app, select Join or create a team, then Create a team. When creating a team, you can select From scratch or From a group or team. Now there is a new option for selecting a template. Our new IT Projects template is available:

When creating the team, you can select whether it is Private or Public, then give the team a name and a description. The team does take a few minutes to create, and we’ll see why when we create a team using the Graph API.

Using Teams Templates with Graph API

Now that we have a custom template to create teams, let’s jump over to how to do this in Graph API. The beta version of the Graph API can create teams from templates. Since these are beta, Microsoft can make changes to them at any time and are not supported in production.

First, we’ll need headers with a Graph API authorization access token using an application client ID and client secret. I’ve blogged about how to do this previously, so I’m not going to cover it again here. Instead, I’m going to go straight into the code and what Graph API calls to make.

First I need to create my request body. This is going to contain details on how I want my team to be made in JSON formatting. The template@odata.bind value is going to reference the template we made previously in this post. Note that the end of the URI is the template GUID I said we would need later.

Next, I give the team a display name, a description, and a visibility value. Since I am using application permissions to create the team, I need to specify an owner for the team. I tried using the format found here in the Microsoft Docs for specifying the owner, but this did not work for me. Instead, I used owners@odata.bind property and specified my user profile using my object ID. Here is the full value for the $requestBody variable:

$requestBody =
    "template@odata.bind": "''909e628b-dcc5-4b92-8208-64fe15beb1ae'')",
    "displayName": "Team from Template Graph API",
    "description": "Creating a team using a template and Graph API",
    "visibility": "Public",
    "owners@odata.bind": [

With the team information saved, I can now make the HTTP request to the Graph API to make the team using the template. My URI will be using the beta Graph API URI

One thing I found out is I need to use Invoke-WebRequest instead of my usual Invoke-RestMethod. The WebRequest allows viewing the response headers whereas the RestMethod does not. I found this while researching this blog post, so if you know of a way to use RestMethod to get the response headers, please leave a comment below.

I’m going to make the request and save the results to the variable $responseData:

$responseData = Invoke-WebRequest -Method POST -Uri "" -Body $requestBody -Headers $headers

After publishing this post, I found a way to get the response headers using Invoke-RestMethod. I wanted to post this for anyone reading later. I’ll leave the remainder of the post unchanged for reference as it is a valid way to get the information as well.

Use the -ResponseHeadersVariable parameter to save the response headers to a variable, like this:

Invoke-RestMethod -Method POST -Uri "" -Body $requestBody -Headers $headers -ResponseHeadersVariable responseHeaders

I can then view the Location value used in the next section like this:


View Status of Teams Template Creation

I saved the response to a variable as I need to view the response headers. The headers contain a Location value returned by the request. The Location value will return a partial URI:


When we create a request to create a team using a template, it is called a teamsAsyncOperation. This means we’ll get a response back but the requested action may take some time to complete. This Location value is a URI endpoint we can check to see when the team has finished provisioning. We see this same behavior in the Teams client when we created a team using a template. The Teams client displayed a message that the team will take a few minutes to get created, and this is the same async operation happening.

We can take this location value and prepend it with the Graph API value of in order to view the operation status. I need to specify the GET method and headers with the authorizing access token:

Invoke-RestMethod -Method GET -Uri "'c423d9d5-d9ec-472d-9d6e-f09be75e12c9')/operations('be7fb68d-2bef-42b6-b782-db509602fd74')" -Headers $headers

I checked this immediately after completing the initial request to create the team, so the status is inProgress. To verify the team has been created successfully, continue making GET requests every 30 seconds until the status shows success (or maybe failure!). After waiting a few minutes, I made another HTTP request to see the status is succeeded and my team is created.

Summary and Additional Resources

The ability to create templates to build teams from is a welcomed featured. It further extends the functionality of Microsoft Teams to allow administrators and users to customize their teams to get the most value.

One quirk I have noticed is the Teams client does not show the channels I configure to appear for all team members. When I manage the team and view the channels, they are configured to show for everyone. Perhaps this is a delay in the Teams client in showing them by default or just an issue with this being in beta.

Questions or comments? If so, drop me a note below or find me on Twitter or LinkedIn to discuss further.

Microsoft Docs: Create team
Microsoft Docs: teamsAsyncOperation resource type
Getting Started with Microsoft Teams and Graph API
Creating Microsoft Teams and Channels with Graph API and PowerShell

This Post Has One Comment

Leave a Reply