Useful Things to Do with Microsoft Graph Teams Operations

Useful Things to Do with Microsoft Graph Teams Operations

I’ve been working with Microsoft Graph a lot lately, and I think it’s a really fun and cool interface. Especially I’m excited about the Teams operations, which are at this moment only available in the beta version. Because I’ve had so much fun playing around with those, and also because Microsoft Teams turned 1 year old a week ago (!), I figured I’d show you a couple of examples of how you can utilize those operations.

If you have not yet set up an application registration in Azure AD for calling Microsoft Graph (required), check this blog post for instructions.

Getting the current user’s teams via Microsoft Graph is extremely simple; you just need to call me/joinedTeams and that will return all of the Teams the user belongs to. Here is an example of that in TypeScript.

var teams = await this.graphGet(`beta/me/joinedTeams`);

// A generic function you can use for Graph API calls that use GET method
protected async graphGet(url: string): Promise {
    return await this.context.graphHttpClient.get(url, GraphHttpClient.configurations.v1).then((response: HttpClientResponse) => {
        if (response.ok) {
            return response.json();
        } else {
            console.warn(response.statusText);
        }
    }).then((result: any) => {
        return result;
    });
}

So what can you do with the collection of user’s Teams? One use case is to display links to them in a SPFx web part, where clicking a link will direct the user to that Team’s General conversation.

To achieve such a feat, you need a couple of more calls to Graph API. First of all, you need information on the General channel. To get that, you need to fetch all of the Team’s channels with the /groups/{id}/channels operation. The General channel is the first one in the collection.

for (let team of teams.value) {
    var channels = await this.graphGet(`beta/groups/${team.id}/channels`);
    var general = channels.value[0];
}

A side note regarding these Teams chat channel operations: You can also get a specific Teams channel with its id if you know it, or create a new channel.

If you want the link to direct the user to the client application, you need one more piece of information: the tenant id. Luckily, you can also get this one via Graph API! Handy, huh?

var tenant = await this.graphGet(`v1.0/organization`);

Finally, the link format to open the Team’s general channel in client app is:

var url = `https://teams.microsoft.com/l/channel/19:${general.id.replace(/-/gi, "")}@thread.skype/${general.displayName}?groupId=${team.id}&tenantId=${tenant.value[0].id}`;

Alternatively, you can create a link that opens the channel in a browser tab. This will spare you from fetching the tenant id.

var url = `https://teams.microsoft.com/_#/conversations/${general.displayName}?threadId=19:${general.id.replace(/-/gi, "")}@thread.skype&ctx=channel`;

If you ever forget the link formats, you can easily check them if you go to the Teams channel and select “Get link to channel” (client app format) or look at the URL in your browser address field (web app format).

Get link to channel

Provisioning a Team for an existing Office 365 Group using C#

I’ve done quite a bit of workspace provisioning, often utilizing Graph API. There’s been Classic subsites, modern Team Sites/Groups, Communication Sites, pre-configured Planners… and it’s really cool to be able to automate yet another thing: a new Team for an existing Office 365 Group.

The Graph API documentation pretty much has all the information you need for creating a Team (or using any of the other operations), but some things are not explicitly mentioned (*).

  • The request URL format is https://graph.microsoft.com/beta/groups/{id}/team, where you need to fill in the group id. Hence, the group already needs to exist at this point; there isn’t an operation (at least yet) which would automatically create the group for you when you create a new Team.
  • You need to use PUT method.
  • The content type needs to be set as application/json.
  • The request body is required* to contain JSON. In the body, you define the settings for the Team, which you can use to limit what users can do within the Team. There is also an update operation for changing these settings for an existing Team.
  • The content length needs to be set.*

Here’s an example of fulfilling those requirements and making the call in C#. To keep this example simple enough, I’ll leave fetching the group id and access token to you. So far provisioning Teams is only possible while using delegated permissions, so you need to use user credentials, but support for app permissions is coming as well at some point.

var body = $"{{ 'memberSettings': {{ 'allowCreateUpdateChannels': true }}, 'messagingSettings': {{ 'allowUserEditMessages': true , 'allowUserDeleteMessages': true }}, 'funSettings': {{ 'allowGiphy': true, 'giphyContentRating': 'strict' }} }}";

var request = GetRequest($"https://graph.microsoft.com/beta/groups/{groupid}/team", "PUT", "application/json", new WebHeaderCollection { { "Authorization", "Bearer " + accessToken } }, body);
var response = request.GetResponse();

// A generic method you can use for constructing web requests
public HttpWebRequest GetRequest(string url, string method, WebHeaderCollection headers, string body = null, string contentType = "application/json")
{
    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = method;
    request.Headers = headers;

    if (body != null)
    {
        var bytes = Encoding.UTF8.GetBytes(body);
        request.ContentLength = bytes.Length;
        request.ContentType = contentType;
        var stream = request.GetRequestStream();
        stream.Write(bytes, 0, bytes.Length);
        stream.Close();
    }

    return request;
}

In addition to the operations mentioned in these two examples, there’s also an operation for creating a new chat thread to an existing channel. There will also be operations for reading and writing messages in chat threads, but those are not yet available.

Anyway, that’s it this time for Microsoft Teams and Microsoft Graph API! I hope you enjoyed reading this article and perhaps also got some ideas on how to take advantage of these awesome operations. If you have any use cases in mind or have any questions or comments, let me know in the comments below. Otherwise, until next time!

Laura



21 thoughts on “Useful Things to Do with Microsoft Graph Teams Operations”

  • Is there any graph api to update general channel settings ?
    I know there is one to allow to update moderation settings of channels but that doesn’t work for general channel.
    it throws an error General channel can’t be patched

  • Hello Laura, I have a requirement to list all sites connected to private channels. Then those need to be attached to retention policies. Is there any guidance?

    • Hi,

      You should be able to get a list of all sites connected to private channels via Microsoft Graph. For applying retention labels, look into the PnP PowerShell commandlets (Set-PnPLabel).

      Laura

  • Hi, Need some help. Is there any way I can hide the team in Microsoft Teams using Graph API ? Thanks. Siva

    • Hi Sivakumar,

      There’s a team level setting called “showInTeamsSearchAndSuggestions” which controls whether the team shows up in search results and suggestions to people who are not team members. You can currently adjust the setting via Graph, and it is also coming to the user interface at some point.

      Laura

  • Hello Laura,
    Unfortunately I could not find any explanation for the error from the GraphAPI using https://graph.microsoft.com/beta/app/calls. The call returns the following message:

    {
    “error”: {
    “code”: “UnknownError”,
    “message”: “{\”errorCode\”:\”7503\”,\”message\”:\”Application is not registered in our store.\”,\”instanceAnnotations\”:[]}”,
    “innerError”: {
    “request-id”: “4dc2a34b-72b2-4f08-8a3f-07ad87b2544e”,
    “date”: “2019-09-05T12:34:02”
    }
    }
    }

    The application is registered in AzureAD. Which “Store” is meant?

Leave a Reply

Your email address will not be published. Required fields are marked *

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