Skip to main content

Overview

The Groups API provides operations to manage group entities in Azure Active Directory and Microsoft 365. Access through graphClient.Groups.

Request Builder

public GroupsRequestBuilder Groups { get; }
Accessed via: graphClient.Groups

Operations

List Groups

Retrieve a list of group objects.
public async Task<GroupCollectionResponse> GetAsync(
    Action<RequestConfiguration<GroupsRequestBuilderGetQueryParameters>> requestConfiguration = default,
    CancellationToken cancellationToken = default
)
Query Parameters:
$select
string[]
Properties to include (e.g., ["id", "displayName", "mail"])
$filter
string
Filter expression (e.g., "mailEnabled eq true")
$orderby
string[]
Sort order (e.g., ["displayName"])
$top
int
Number of items to return
$skip
int
Number of items to skip
Search query (requires ConsistencyLevel header)
$count
bool
Include count of items
$expand
string[]
Related entities to expand (e.g., ["members"])
Response:
value
Group[]
Array of group objects
URL for next page of results
Example:
// Get all groups
var groups = await graphClient.Groups.GetAsync();

foreach (var group in groups.Value)
{
    Console.WriteLine($"{group.DisplayName} - {group.Mail}");
}

// Filter mail-enabled security groups
var mailGroups = await graphClient.Groups.GetAsync(config =>
{
    config.QueryParameters.Filter = "mailEnabled eq true and securityEnabled eq true";
    config.QueryParameters.Select = new[] { "id", "displayName", "mail" };
});

// Search groups
var searchResults = await graphClient.Groups.GetAsync(config =>
{
    config.QueryParameters.Search = "\"displayName:Engineering\"";
    config.Headers.Add("ConsistencyLevel", "eventual");
});

Create Group

Create a new group.
public async Task<Group> PostAsync(
    Group body,
    Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default,
    CancellationToken cancellationToken = default
)
body
Group
required
Group object with required properties
Required Properties:
  • DisplayName - Group display name
  • MailNickname - Email alias
  • MailEnabled - Whether group is mail-enabled
  • SecurityEnabled - Whether group is security-enabled
Example:
// Create Microsoft 365 group
var newGroup = new Group
{
    DisplayName = "Engineering Team",
    MailNickname = "engineering",
    Description = "Engineering department group",
    MailEnabled = true,
    SecurityEnabled = false,
    GroupTypes = new[] { "Unified" },
    Visibility = "Private"
};

var group = await graphClient.Groups.PostAsync(newGroup);

// Create security group
var securityGroup = new Group
{
    DisplayName = "IT Security",
    MailNickname = "itsecurity",
    MailEnabled = false,
    SecurityEnabled = true
};

var group = await graphClient.Groups.PostAsync(securityGroup);

// Create mail-enabled security group
var mailSecGroup = new Group
{
    DisplayName = "Marketing Team",
    MailNickname = "marketing",
    MailEnabled = true,
    SecurityEnabled = true
};

var group = await graphClient.Groups.PostAsync(mailSecGroup);

Get Group by ID

Retrieve a specific group.
var group = await graphClient.Groups["group-id"].GetAsync();

// Select specific properties
var group = await graphClient.Groups["group-id"].GetAsync(config =>
{
    config.QueryParameters.Select = new[] { "id", "displayName", "description" };
});

// Expand members
var group = await graphClient.Groups["group-id"].GetAsync(config =>
{
    config.QueryParameters.Expand = new[] { "members" };
});

Update Group

Update group properties.
var groupToUpdate = new Group
{
    Description = "Updated description",
    Visibility = "Public"
};

await graphClient.Groups["group-id"].PatchAsync(groupToUpdate);

Delete Group

Delete a group.
await graphClient.Groups["group-id"].DeleteAsync();

Member Management

List Members

var members = await graphClient.Groups["group-id"].Members.GetAsync();

foreach (var member in members.Value)
{
    if (member is User user)
    {
        Console.WriteLine($"User: {user.DisplayName}");
    }
    else if (member is Group group)
    {
        Console.WriteLine($"Group: {group.DisplayName}");
    }
}

Add Member

var directoryObject = new ReferenceCreate
{
    OdataId = $"https://graph.microsoft.com/v1.0/users/{userId}"
};

await graphClient.Groups["group-id"].Members.Ref.PostAsync(directoryObject);

Remove Member

await graphClient.Groups["group-id"].Members["user-id"].Ref.DeleteAsync();

Check Membership

var requestBody = new CheckMemberGroupsPostRequestBody
{
    GroupIds = new[] { "group-id-1", "group-id-2" }
};

var memberGroups = await graphClient.Users["user-id"].CheckMemberGroups.PostAsync(requestBody);

Owner Management

List Owners

var owners = await graphClient.Groups["group-id"].Owners.GetAsync();

Add Owner

var directoryObject = new ReferenceCreate
{
    OdataId = $"https://graph.microsoft.com/v1.0/users/{userId}"
};

await graphClient.Groups["group-id"].Owners.Ref.PostAsync(directoryObject);

Remove Owner

await graphClient.Groups["group-id"].Owners["user-id"].Ref.DeleteAsync();

Additional Methods

Delta Query

Get incremental changes.
var deltaResponse = await graphClient.Groups.Delta.GetAsync();

foreach (var group in deltaResponse.Value)
{
    Console.WriteLine($"Changed group: {group.DisplayName}");
}

Get by IDs

var requestBody = new GetByIdsPostRequestBody
{
    Ids = new List<string> { "group-id-1", "group-id-2" },
    Types = new List<string> { "group" }
};

var groups = await graphClient.DirectoryObjects.GetByIds.PostAsync(requestBody);

Count Groups

var count = await graphClient.Groups.Count.GetAsync();

Group-Specific Operations

List Conversations (Microsoft 365 Groups)

var conversations = await graphClient.Groups["group-id"].Conversations.GetAsync();

List Threads

var threads = await graphClient.Groups["group-id"]
    .Conversations["conversation-id"]
    .Threads.GetAsync();

Access Team (for Teams-enabled groups)

var team = await graphClient.Groups["group-id"].Team.GetAsync();

Access Drive

var drive = await graphClient.Groups["group-id"].Drive.GetAsync();

List Sites

var sites = await graphClient.Groups["group-id"].Sites.GetAsync();

Calendar and Events

// Get group calendar
var calendar = await graphClient.Groups["group-id"].Calendar.GetAsync();

// List events
var events = await graphClient.Groups["group-id"].Events.GetAsync();

// Create event
var newEvent = new Event
{
    Subject = "Team Meeting",
    Start = new DateTimeTimeZone { DateTime = "2024-03-15T14:00:00", TimeZone = "UTC" },
    End = new DateTimeTimeZone { DateTime = "2024-03-15T15:00:00", TimeZone = "UTC" }
};

await graphClient.Groups["group-id"].Events.PostAsync(newEvent);

Common Filtering Examples

// Microsoft 365 groups only
config.QueryParameters.Filter = "groupTypes/any(c:c eq 'Unified')";

// Security groups only
config.QueryParameters.Filter = "securityEnabled eq true and mailEnabled eq false";

// Mail-enabled groups
config.QueryParameters.Filter = "mailEnabled eq true";

// Groups created after date
config.QueryParameters.Filter = "createdDateTime ge 2024-01-01T00:00:00Z";

// Dynamic groups
config.QueryParameters.Filter = "groupTypes/any(c:c eq 'DynamicMembership')";

Group Types

Microsoft 365 Group (Unified)

GroupTypes = new[] { "Unified" },
MailEnabled = true,
SecurityEnabled = false

Security Group

MailEnabled = false,
SecurityEnabled = true

Mail-Enabled Security Group

MailEnabled = true,
SecurityEnabled = true

Dynamic Group

GroupTypes = new[] { "DynamicMembership" },
MembershipRule = "(user.department -eq \"Engineering\")",
MembershipRuleProcessingState = "On"

Pagination

var allGroups = new List<Group>();
var response = await graphClient.Groups.GetAsync(config =>
{
    config.QueryParameters.Top = 100;
});

allGroups.AddRange(response.Value);

while (response.OdataNextLink != null)
{
    response = await graphClient.Groups
        .WithUrl(response.OdataNextLink)
        .GetAsync();
    allGroups.AddRange(response.Value);
}

Error Handling

using Microsoft.Graph.Models.ODataErrors;

try
{
    var group = await graphClient.Groups["invalid-id"].GetAsync();
}
catch (ODataError error)
{
    Console.WriteLine($"Error: {error.Error.Code}");
    Console.WriteLine($"Message: {error.Error.Message}");
}

See Also

Group Model

Group resource properties

Users API

User management

Teams API

Teams operations

Directory Objects

Base directory operations

Build docs developers (and LLMs) love