Msg.Groups (msg v0.3.8)

Provides functions for interacting with Microsoft 365 Groups via the Graph API.

This module supports creating, reading, updating, and managing Microsoft 365 Groups (also known as Unified Groups), which provide shared workspaces with email, calendar, files, and other collaborative features.

Required Application Permissions

  • Group.ReadWrite.All - application permission to read and write all groups

Note: This is an application permission, not a delegated permission. The app accesses groups on behalf of itself using app-only authentication.

Examples

# Create a client (application-only authentication)
client = Msg.Client.new(%{
  client_id: "...",
  client_secret: "...",
  tenant_id: "..."
})

# Create a new M365 Group
{:ok, group} = Msg.Groups.create(client, %{
  display_name: "Matter: Smith v. Jones",
  mail_enabled: true,
  mail_nickname: "matter-smith-jones",
  security_enabled: false,
  group_types: ["Unified"],
  description: "Legal matter workspace",
  visibility: "Private"
})

# List all groups
{:ok, groups} = Msg.Groups.list(client)

# Get a specific group
{:ok, group} = Msg.Groups.get(client, group_id)

# Add a member to the group
:ok = Msg.Groups.add_member(client, group_id, user_id)

References

Summary

Functions

Adds a member to a group.

Adds an owner to a group.

Creates a new Microsoft 365 Group.

Deletes a Microsoft 365 Group.

Gets a specific group by ID.

Gets a group by mailNickname.

Lists all groups in the organization.

Lists all members of a group.

Removes a member from a group.

Functions

add_member(client, group_id, user_id)

@spec add_member(Req.Request.t(), String.t(), String.t()) :: :ok | {:error, term()}

Adds a member to a group.

Parameters

  • client - Authenticated Req.Request client
  • group_id - ID of the group
  • user_id - ID of the user to add as member

Returns

  • :ok - Member added successfully
  • {:error, term} - Error

Examples

:ok = Msg.Groups.add_member(client, group_id, user_id)

add_owner(client, group_id, user_id)

@spec add_owner(Req.Request.t(), String.t(), String.t()) :: :ok | {:error, term()}

Adds an owner to a group.

Parameters

  • client - Authenticated Req.Request client
  • group_id - ID of the group
  • user_id - ID of the user to add as owner

Returns

  • :ok - Owner added successfully
  • {:error, term} - Error

Examples

:ok = Msg.Groups.add_owner(client, group_id, user_id)

create(client, attrs)

@spec create(Req.Request.t(), map()) :: {:ok, map()} | {:error, term()}

Creates a new Microsoft 365 Group.

Parameters

  • client - Authenticated Req.Request client
  • attrs - Map with group properties:
    • :display_name (required) - Group name
    • :mail_enabled (required) - Boolean (true for groups with email)
    • :mail_nickname (required) - Email alias
    • :security_enabled (required) - Boolean (true for security groups)
    • :group_types (required) - List, include ["Unified"] for M365 Groups
    • :description (optional) - Group description
    • :visibility (optional) - "Public" or "Private"
    • :owners_odata_bind (optional) - List of user IDs to set as owners
    • :members_odata_bind (optional) - List of user IDs to set as members

Returns

  • {:ok, group} - Created group with generated ID
  • {:error, :unauthorized} - Invalid or expired token
  • {:error, {:invalid_request, message}} - Validation error
  • {:error, term} - Other errors

Examples

{:ok, group} = Msg.Groups.create(client, %{
  display_name: "Project Team",
  mail_enabled: true,
  mail_nickname: "project-team",
  security_enabled: false,
  group_types: ["Unified"],
  description: "Team workspace",
  visibility: "Private"
})

See Also

delete(client, group_id)

@spec delete(Req.Request.t(), String.t()) :: :ok | {:error, term()}

Deletes a Microsoft 365 Group.

Warning: This is a destructive operation that permanently removes the group and all associated resources including the group mailbox, SharePoint site, Planner plans, calendar, and Teams (if connected). Deleted groups may be recoverable from the recycle bin for up to 30 days.

Parameters

  • client - Authenticated Req.Request client
  • group_id - ID of the group to delete

Returns

  • :ok - Group deleted successfully (204 status)
  • {:error, :not_found} - Group doesn't exist
  • {:error, :forbidden} - Insufficient permissions
  • {:error, term} - Other errors

Required Permissions

  • Group.ReadWrite.All (application permission)

Examples

:ok = Msg.Groups.delete(client, "group-id-123")

See Also

get(client, group_id)

@spec get(Req.Request.t(), String.t()) :: {:ok, map()} | {:error, term()}

Gets a specific group by ID.

Parameters

  • client - Authenticated Req.Request client
  • group_id - ID of the group to retrieve

Returns

  • {:ok, group} - Group details
  • {:error, :not_found} - Group doesn't exist
  • {:error, term} - Other errors

Examples

{:ok, group} = Msg.Groups.get(client, "group-id-here")

get_by_mail_nickname(client, mail_nickname)

@spec get_by_mail_nickname(Req.Request.t(), String.t()) ::
  {:ok, map()} | {:error, term()}

Gets a group by mailNickname.

Parameters

  • client - Authenticated Req.Request client
  • mail_nickname - The mailNickname of the group to find

Returns

  • {:ok, group} - Group details
  • {:error, :not_found} - Group doesn't exist
  • {:error, term} - Other errors

Examples

{:ok, group} = Msg.Groups.get_by_mail_nickname(client, "matter-smith-jones")

list(client, opts \\ [])

@spec list(
  Req.Request.t(),
  keyword()
) :: {:ok, [map()]} | {:ok, map()} | {:error, term()}

Lists all groups in the organization.

Parameters

  • client - Authenticated Req.Request client
  • opts - Keyword list of options:
    • :auto_paginate - Boolean, default true (fetch all pages)
    • :filter - OData filter string

Returns

  • {:ok, [group]} - List of groups (when auto_paginate: true)
  • {:ok, %{items: [group], next_link: url}} - First page with next link (when auto_paginate: false)
  • {:error, term} - Error

Examples

# Get all groups
{:ok, groups} = Msg.Groups.list(client)

# Get first page only
{:ok, %{items: groups, next_link: next}} = Msg.Groups.list(client, auto_paginate: false)

# Filter groups
{:ok, groups} = Msg.Groups.list(client, filter: "startswith(displayName,'Matter:')")

list_members(client, group_id, opts \\ [])

@spec list_members(Req.Request.t(), String.t(), keyword()) ::
  {:ok, [map()]} | {:ok, map()} | {:error, term()}

Lists all members of a group.

Parameters

  • client - Authenticated Req.Request client
  • group_id - ID of the group
  • opts - Keyword list of options:
    • :auto_paginate - Boolean, default true (fetch all pages)

Returns

  • {:ok, [user]} - List of user objects
  • {:error, term} - Error

Examples

{:ok, members} = Msg.Groups.list_members(client, group_id)

remove_member(client, group_id, user_id)

@spec remove_member(Req.Request.t(), String.t(), String.t()) :: :ok | {:error, term()}

Removes a member from a group.

Parameters

  • client - Authenticated Req.Request client
  • group_id - ID of the group
  • user_id - ID of the user to remove

Returns

  • :ok - Member removed successfully
  • {:error, term} - Error

Examples

:ok = Msg.Groups.remove_member(client, group_id, user_id)