Get change notifications for membership changes in teams and channels using Microsoft Graph

Change notifications enable you to subscribe to membership changes (create, update, and delete) in a team or private channel. You can get notified whenever a member is added, removed, or updated in a team or in a private channel. You can also get the resource data in the notifications and therefore avoid calling the API to get the payload.

Continue with this article about scenarios for the conversationMember resource in the team or channel context. Or, find out about change notifications for other Microsoft Teams resources.

Note

If you request a subscription expirationDateTime that is more than 1 hour in the future, you must subscribe to lifecycle notifications by including a lifecycleNotificationUrl property in your subscription request. Otherwise your subscription request will fail with the following error message: lifecycleNotificationUrl is a required property for subscription creation on this resource when the expirationDateTime value is set to greater than 1 hour.

Subscribe to changes in membership of a particular team

To get change notifications for membership changes in a particular team, subscribe to /teams/{team-id}/members. This resource supports including resource data in the notification.

Permissions

Permission type Permissions (from least to most privileged)
Delegated (work or school account) TeamMember.Read.All, TeamMember.ReadWrite.All
Delegated (personal Microsoft account) Not supported.
Application TeamMember.Read.Group*, TeamMember.Read.All, TeamMember.ReadWrite.All

Note: Permissions marked with * are supported as part of resource-specific consent.

Example

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,deleted,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/{team-id}/members",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

Subscribe to membership changes in all teams across the tenant

To get change notifications for membership changes in all teams across the tenant, subscribe to /teams/getAllMembers. This resource supports including resource data in the notification.

Permissions

Permission type Permissions (from least to most privileged)
Delegated (work or school account) Not supported.
Delegated (personal Microsoft account) Not supported.
Application TeamMember.Read.All, TeamMember.ReadWrite.All

Example

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,deleted,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/getAllMembers",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2022-08-10T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

Subscribe to membership changes in all channels across the tenant (preview)

To get change notifications for membership changes in all channels across the tenant, subscribe to /teams/getAllChannels/getAllMembers. This resource supports including resource data in the notification. Currently, only private channels are supported. This subscription is only available in the beta endpoint.

Permissions

Permission type Permissions (from least to most privileged)
Delegated (work or school account) Not supported.
Delegated (personal Microsoft account) Not supported.
Application ChannelMember.Read.All, ChannelMember.ReadWrite.All

Example

POST https://graph.microsoft.com/beta/subscriptions
Content-Type: application/json

{
  "changeType": "created,deleted,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/getAllChannels/getAllMembers",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2022-08-10T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

Subscribe to membership changes in all private and shared channels of a particular team

To get change notifications for membership changes in all the private and shared channels in a particular team, subscribe to /teams/{team-id}/channels/getAllMembers. This resource supports including resource data in the notification.

Note: This API has licensing and payment requirements. It supports both model=A and model=B query parameters. If no model is specified, evaluation mode will be used.

Permissions

Permission type Permissions (from least to most privileged)
Delegated (work or school account) ChannelMember.Read.All.
Delegated (personal Microsoft account) Not supported.
Application ChannelMember.Read.All

Example

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

{
  "changeType": "created,deleted,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "resource": "/teams/{team-id}/channels/getAllMembers",
  "includeResourceData": true,
  "encryptionCertificate": "{base64encodedCertificate}",
  "encryptionCertificateId": "{customId}",
  "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
  "clientState": "{secretClientState}"
}

Notifications with resource data

For notifications with resource data, the payload looks like the following. This payload is for a membership change in a team.

{
    "value": [{
        "subscriptionId": "10493aa0-4d29-4df5-bc0c-ef742cc6cd7f",
        "changeType": "created",
        "clientState": "<<--SpecifiedClientState-->>",
        "subscriptionExpirationDateTime": "2021-02-02T10:30:34.9097561-08:00",
        "resource": "teams('ee0f5ae2-8bc6-4ae5-8466-7daeebbfa062')/members('ZWUwZjVhZTItOGJjNi00YWU1LTg0NjYtN2RhZWViYmZhMDYyIyM3Mzc2MWYwNi0yYWM5LTQ2OWMtOWYxMC0yNzlhOGNjMjY3Zjk=')",
        "resourceData": {
            "id": "ZWUwZjVhZTItOGJjNi00YWU1LTg0NjYtN2RhZWViYmZhMDYyIyM3Mzc2MWYwNi0yYWM5LTQ2OWMtOWYxMC0yNzlhOGNjMjY3Zjk=",
            "@odata.type": "#Microsoft.Graph.aadUserConversationMember",
            "@odata.id": "teams('ee0f5ae2-8bc6-4ae5-8466-7daeebbfa062')/members('ZWUwZjVhZTItOGJjNi00YWU1LTg0NjYtN2RhZWViYmZhMDYyIyM3Mzc2MWYwNi0yYWM5LTQ2OWMtOWYxMC0yNzlhOGNjMjY3Zjk=')"
        },
        "encryptedContent": {
            "data": "<<--EncryptedContent-->",
            "dataKey": "<<--EnryptedDataKeyUsedForEncryptingContent-->>",
            "encryptionCertificateId": "<<--IdOfTheCertificateUsedForEncryptingDataKey-->>",
            "encryptionCertificateThumbprint": "<<--ThumbprintOfTheCertificateUsedForEncryptingDataKey-->>"
        },
        "tenantId": "<<--TenantForWhichNotificationWasSent-->>"
    }],
    "validationTokens": ["<<--ValidationTokens-->>"]
}

The payload for the channel membership events is similar to the previous payload except that the resource property points to a channel member instead of a team member.

For details about how to validate tokens and decrypt the payload, see Set up change notifications that include resource data.

The decrypted notification payload looks like the following. The payload conforms to the aaduserconversationmember schema. The payload is similar to that returned by GET operations.

{
  "id": "/ZWUwZjVhZTItOGJjNi00YWU1LTg0NjYtN2RhZWViYmZhMDYyIyM3Mzc2MWYwNi0yYWM5LTQ2OWMtOWYxMC0yNzlhOGNjMjY3Zjk=",
  "roles": [
    "owner"
  ],
  "displayName": "John Doe",
  "userId": "8b081ef6-4792-4def-b2c9-c363a1bf41d5",
  "email": null
}

Notifications without resource data

Notifications without resource data give you enough information to make GET calls to get the message content. Subscriptions for notifications without resource data don't require an encryption certificate (because Microsoft Graph doesn't send the actual resource data).

For notifications without resource data, the payload looks like the following. This payload is for a membership change in a team.

{
  "subscriptionId": "9f9d1ed0-c9cc-42e7-8d80-a7fc4b0cda3c",
  "changeType": "created",
  "tenantId": "<<--TenantForWhichNotificationWasSent-->>",
  "clientState": "<<--SpecifiedClientState-->>",
  "subscriptionExpirationDateTime": "2021-02-02T11:26:41.0537895-08:00",
  "resource": "teams('ee0f5ae2-8bc6-4ae5-8466-7daeebbfa062')/members('ZWUwZjVhZTItOGJjNi00YWU1LTg0NjYtN2RhZWViYmZhMDYyIyM3Mzc2MWYwNi0yYWM5LTQ2OWMtOWYxMC0yNzlhOGNjMjY3Zjk=')",
  "resourceData": {
    "id": "ZWUwZjVhZTItOGJjNi00YWU1LTg0NjYtN2RhZWViYmZhMDYyIyM3Mzc2MWYwNi0yYWM5LTQ2OWMtOWYxMC0yNzlhOGNjMjY3Zjk",
    "@odata.type": "#Microsoft.Graph.aadUserConversationMember",
    "@odata.id": "teams('ee0f5ae2-8bc6-4ae5-8466-7daeebbfa062')/members('ZWUwZjVhZTItOGJjNi00YWU1LTg0NjYtN2RhZWViYmZhMDYyIyM3Mzc2MWYwNi0yYWM5LTQ2OWMtOWYxMC0yNzlhOGNjMjY3Zjk=')"
  }
}

The payload for the channel membership events is similar to the previous payload except that the resource property points to a channel member instead of a team member.

The resource and @odata.id properties can be used to make calls to Microsoft Graph to get the payload for the message. GET calls always return the current state of the message. If the message is changed between when the notification is sent and when the message is retrieved, the operation returns the updated message.