How to create Microsoft 365/O365 Group with Teams using Graph API.
Published Nov 25 2020 06:40 PM 15.7K Views

Seems creating Microsoft 365/O365 Group via CSOM not working. If you try to use SharePoint Client Side Object Model(CSOM) you might run into following exception:


Message=The web template GROUP#0 is not available for sites on this tenant.
at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream)
at Microsoft.SharePoint.Client.ClientRequest.ProcessResponse()
at Microsoft.SharePoint.Client.ClientRequest.ExecuteQueryToServer(ChunkStringBuilder sb)
at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()



We have to use Graph API and this sample should help get started. ROPC authentication is used. Delegated authentication should also work but not tested.


Setup Steps:
1] Setup Native App in AAD.
2] Copy the App Id as you will need to provide it later in the code.
3] Provide following Delegated Graph API permissions.

Groups.ReadWite.All, Directory.ReadWrite.All, openid, Team.Create, User.Read 
4] Grant Admin consent.
5] See screenshot below:



6] Sample C# code to Create Microsoft 365/O365 Group with Teams:



using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;

namespace CreateGroupMultiGeo
    class Program
        static async Task Main(string[] args)
            string clientId = "50168119-04dd-0000-0000-000000000000";
            string email = "";
            string passwordStr = "password";

            var req = new HttpRequestMessage(HttpMethod.Post, "")
                Content = new FormUrlEncodedContent(new Dictionary<string, string>
                    ["resource"] = "",
                    ["grant_type"] = "password",
                    ["client_id"] = clientId,
                    ["username"] = email,
                    ["password"] = passwordStr,
                    ["scope"] = "openid"

            HttpClient httpClient = new HttpClient();

            var res = await httpClient.SendAsync(req);

            string json = await res.Content.ReadAsStringAsync();

            if (!res.IsSuccessStatusCode)
                throw new Exception("Failed to acquire token: " + json);
            var result = (JObject)JsonConvert.DeserializeObject(json);
            //create a group

            HttpClient httpClientGroup = new HttpClient();

            httpClientGroup.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.Value<string>("access_token"));

            // Create a string variable and get user input from the keyboard and store it in the variable
            string grpName = "MultiGeoGraphAPIGrp1";

            string contentGroup = @"{
              'displayName': '" + grpName + @"',"
              + @"'groupTypes': ['Unified'],
              'mailEnabled': true,
              'mailNickname': '" + grpName + @"',"
              + @"'securityEnabled': false,
              'owners@odata.bind': ['']

            var httpContentGroup = new StringContent(contentGroup, Encoding.GetEncoding("utf-8"), "application/json");

            var responseGroup = httpClientGroup.PostAsync("", httpContentGroup).Result;

            var content = await responseGroup.Content.ReadAsStringAsync();

            dynamic grp = JsonConvert.DeserializeObject<object>(content);



            //create a Team

            HttpClient httpClientTeam = new HttpClient();

            httpClientTeam.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.Value<string>("access_token"));

            //create a team

            string contentTeam = @"{ 
                'memberSettings': { 
                    'allowCreateUpdateChannels': true
                'messagingSettings': { 
                    'allowUserEditMessages': true, 
                    'allowUserDeleteMessages': true 
                'funSettings': { 
                    'allowGiphy': true, 
                    'giphyContentRating': 'strict' 

            var httpContentTeam = new StringContent(contentTeam, Encoding.GetEncoding("utf-8"), "application/json");

            var responseTeam = httpClientTeam.PutAsync(@"" + + @"/team", httpContentTeam).Result;





Version history
Last update:
‎Dec 14 2020 09:59 AM
Updated by: