Receive change notifications through webhooks

A webhook is an HTTP-based user-defined callback API that you can set up in your infrastructure to receive change notifications and events from a service, such as Microsoft Graph. To use webhooks, you need to define a publicly accessible HTTPS-secured endpoint that receives the notifications.

You can create a subscription to the resource for which you want to be notified of changes. While the subscription is valid, Microsoft Graph sends a notification to your endpoint whenever it detects a change in the resource.

The article guides you through the process of implementing your webhook endpoint, subscribing to and managing Microsoft Graph subscriptions, and how to receive change notifications through webhooks.

For details about how to create change notifications, see Microsoft Graph API change notifications.

Considerations for a webhook endpoint

Before you can receive a notification via webhooks, you must create a publicly accessible, HTTPS-secured endpoint that is addressable via URL. If your endpoint isn't publicly accessible, Microsoft Graph doesn't send notifications to your endpoint.

Your endpoint must provide correct, consistent, and timely HTTP responses in order to reliably receive notifications. If an endpoint doesn't respond in a timely manner, the change notification service may begin to drop notifications. Dropped notifications can't be recovered.

Your endpoint must also continue to remain authenticated to Microsoft Graph, either by continually renewing your subscription or by responding to lifecycle notifications.

HTTP codes and retry logic

Once the Microsoft Graph change notifications service receives a 2xx class code from your endpoint, the notification is considered sent. As long as the change notifications service receives any other HTML response (even an error code) within 10 seconds, the service continues to try to deliver the notification for up to 4 hours.

  • If you're able to process the notification within a 3-second window, you should return a 200 - OK status code to Microsoft Graph
  • If your service may take more than 10 seconds to process the notification, then you may choose to persist the notification in a queue on your endpoint and return 202 - Accepted status code to Microsoft Graph.
  • If the notification isn't processed or queued, return a 5xx class code to indicate an error so that Microsoft Graph can retry the notification.

Notifications that fail to deliver are retried at exponential backoff intervals. Missed notifications may take up to 4 hours to resend once your endpoint comes online.

Throttling

For security and performance reasons, Microsoft Graph throttles notifications sent to endpoints that become slow or unresponsive. It may include dropping notifications in a way that they can't be recovered.

  1. An endpoint is marked "slow" once more than 10% of responses take longer than 10 seconds in a 10-minute window.

    • Once an endpoint is marked "slow", any new notifications are sent on a 10-second delay.
    • An endpoint exits the "slow" state once less than 10% of responses take longer than 10 seconds in a 10-minute window.
  2. An endpoint is marked "drop" once more than 15% of responses take longer than 10 seconds in a 10-minute window.

    • Once an endpoint is marked "drop", any new notifications are dropped, for up to 10 minutes
    • An endpoint exits the "drop" state once less than 15% of responses take longer than 10 seconds in a 10-minute window.

If your endpoint is unable to meet these performance characteristics, consider using Event Hubs or Event Grid as a target for receiving notifications.

Authentication

When you create your subscription, an access token is sent to your endpoint. This access token is used only to check the validity of your endpoint and has a lifecycle different from that of your change notification subscription. This access token generally expires within 1 hour.

Your endpoint must be prepared to be regularly reauthorized by Microsoft Graph to ensure that Microsoft Graph can continue to deliver notifications to your endpoint.

If an access token expires, notifications aren't delivered. However, it doesn't trigger endpoint throttling behavior and Microsoft Graph continues to retry sending each notification for up to 4 hours. So if the access token is refreshed within 4 hours of expiration, unsent notifications are delivered.

It's recommended that you add lifecycle notifications to your subscription to receive a warning about token expiration so you can reauthorize your endpoint in a timely manner.

When you renew your subscription, your access token is also refreshed.

Firewall configuration

You can configure the firewall that protects your endpoint to allow inbound connections only from Microsoft Graph, reducing further exposure to invalid change notifications. For a complete list of IP addresses used by Microsoft Graph to deliver change notifications, see additional endpoints for Microsoft 365.

Note

The listed IP addresses that are used to deliver change notifications can be updated at any time without notice.

Create a subscription

Important

Multiple steps are required to ensure a secure communication channel is established and maintained between the Microsoft Graph change notifications service and your endpoint.

To start receiving Microsoft Graph change notifications, you must create a subscription using the URL of your endpoint (notification URL) to establish the subscription. The pattern of establishing a subscription is as follows:

  1. The client app sends a subscription request to subscribe to changes on a specific resource.

  2. Microsoft Graph checks the request.

    • If the request is valid, Microsoft Graph sends a validation token to the notification URL for the client app to validate the notification URL.
    • If the request is invalid, Microsoft Graph sends an error response with an error code and details.
  3. When the client receives the notification URL validation request, the client responds with the validation token in plain text.

  4. Microsoft Graph validates the client's validation token response and if the validation token is valid, responds with a subscription ID.

Subscription request

The client app sends a POST request to the /subscriptions endpoint. The following example shows a basic request to subscribe to changes to a specific mail folder on behalf of the signed-in user. For more information about other Microsoft Graph resources that support change notifications, see supported resources.

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

{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/notificationClient",
  "lifecycleNotificationUrl": "https://webhook.azurewebsites.net/api/lifecycleNotifications",
  "resource": "/me/mailfolders('inbox')/messages",
  "expirationDateTime": "2016-03-20T11:00:00.0000000Z",
  "clientState": "SecretClientState"
}

The clientState property is required. Setting it property allows your service to confirm that change notifications you receive originate from Microsoft Graph. For this reason, the value of the property should remain secret and known only to your application and the Microsoft Graph service.

If successful, Microsoft Graph returns a 201 Created code and a subscription object in the body.

Each subscription has a unique subscriptionId, even if you have multiple subscriptions that monitor the same resource and use the same notification URL.

Note

Any query string parameter included in the notificationUrl property is included in the HTTP POST request when notifications are being delivered to your service.

Duplicate subscriptions are not allowed. When a subscription request contains the same values for changeType and resource as an existing subscription, the request fails with an HTTP error code 409 Conflict, and the error message Subscription Id <> already exists for the requested combination.

notificationUrl validation

When you send a request to create a subscription to get change notifications through webhooks, the subscription service checks if the notificationUrl property in your subscription request is valid. The validation process works as follows:

Note

If you're subscribing to lifecycle notifications as well, the subscription service also validates the lifecycleNotificationUrl.

  1. When a subscription is requested, Microsoft Graph encodes a validation token and includes it in a POST request to the notification URL as follows.

    Content-Type: text/plain; charset=utf-8
    POST https://{notificationUrl}?validationToken={opaqueTokenCreatedByMicrosoftGraph}
    
  2. The client must properly decode the URL to get the plain text validation token from Microsoft Graph.

    Escaping any HTML or JavaScript is a good practice because malicious actors can use the notification endpoint for cross-site scripting type of attacks. Microsoft Graph never sends any value containing HTML or JavaScript code.

    In general, treat the validation token value as opaque, as the token format can change without notice.

  3. The client must respond with the following characteristics within 10 seconds of step 1:

    • A status code of HTTP 200 OK.
    • A content type of text/plain.
    • A body that includes the URL decoded plain text validation token.

    Important

    The validation token must be returned in plain text. If the client returns an encoded validation token, the validation fails.

  4. If the endpoint validation fails, Microsoft Graph doesn't create the subscription.

Receive notifications

While the subscription is valid and there are changes to the resource that you subscribed to, Microsoft Graph sends a POST request to the notificationUrl with details of the changes. This payload is the change notification.

For most subscriptions, Microsoft Graph doesn't delay sending notifications but delivers all notifications within the SLA unless the service is experiencing an incident.

A change notification payload sent to your endpoint can contain a collection of change notifications relating to your subscriptions.

Change notification example

When the user receives an email, Microsoft Graph sends a change notification object to the client app as shown in the following example. See changeNotificationCollection and the related changeNotification for details of the notification payload.

When many changes occur, Microsoft Graph may send multiple notifications that correspond to different subscriptions in the same POST request.

{
  "value": [
    {
      "id": "lsgTZMr9KwAAA",
      "subscriptionId":"{subscription_guid}",
      "subscriptionExpirationDateTime":"2016-03-19T22:11:09.952Z",
      "clientState":"secretClientValue",
      "changeType":"created",
      "resource":"users/{user_guid}@{tenant_guid}/messages/{long_id_string}",
      "tenantId": "84bd8158-6d4d-4958-8b9f-9d6445542f95",
      "resourceData":
      {
        "@odata.type":"#Microsoft.Graph.Message",
        "@odata.id":"Users/{user_guid}@{tenant_guid}/Messages/{long_id_string}",
        "@odata.etag":"W/\"CQAAABYAAADkrWGo7bouTKlsgTZMr9KwAAAUWRHf\"",
        "id":"{long_id_string}"
      }
    }
  ]
}

Processing the change notification

When you receive a change notification:

  1. Validate the clientState property. It must match the value originally submitted with the subscription creation request.

    If there's a mismatch, don't consider the change notification as valid. It's possible that the change notification isn't originated from Microsoft Graph and may have been sent by a rogue actor. You should also investigate where the change notification comes from and take appropriate action.

  2. Update your client app based on your business logic.

Subscription lifecycle

When they're no longer needed, subscriptions may be deleted or expire. When you create your subscription, you set an expiration date using the expirationDateTime property. Once this time passes, Microsoft Graph deletes the subscription and doesn't send notifications to your endpoint. You may also explicitly delete your subscription.

The simplest way to continue receiving notifications is to continue renewing your subscription request. Each notification includes a subscriptionExpirationDateTime property. You can use it to guide you when to renew your subscription.

Each subscription also includes an access token granted to the endpoint. The expiration time of this access token may occur before the subscription expiration. You can manage access token expiration using lifecycle notifications for your subscription.

Renew a subscription

PATCH https://graph.microsoft.com/v1.0/subscriptions/{id}
Content-Type: application/json

{
  "expirationDateTime": "2016-03-22T11:00:00.0000000Z"
}

If the subscription renewal request is successful, Microsoft Graph returns a 200 OK response code and a subscription object in the response body. The subscription object includes the new expirationDateTime value.

Delete a subscription

If the client app no longer wants change notifications, it can delete the subscription using its subscriptionId as follows:

DELETE https://graph.microsoft.com/v1.0/subscriptions/{id}

If successful, Microsoft Graph returns a 204 No Content code.

Lifecycle notifications for your subscription

For increased flexibility and reliability, when you create a subscription, you may also subscribe to the lifecycle notifications for that subscription by providing a lifecycleNotificationUrl endpoint that receives, processes, and responds to lifecycle notifications.

When you subscribe to lifecycle notifications, Microsoft Graph alerts you:

  • When the access token is about to expire.
  • When a subscription is about to expire.
  • When a tenant administrator revokes your app's permissions to read a resource.

Note

If an access token expires, notifications are not delivered to the endpoint. But Microsoft Graph continues to retry sending each notification for up to 4 hours. So if the access token is refreshed within 4 hours of expiration, unsent notifications are delivered.

For more information on how to utilize lifecycle notifications for your subscription, see lifecycle notifications.

Summary

In this article, you learned how to receive change notifications through webhooks.

  1. Create a subscription by sending a POST request to the /subscriptions endpoint.
  2. Microsoft Graph validates the webhook notification endpoint before it completes the subscription creation process. A unique subscriptionID is linked to the subscription.
  3. As long as the subscription is still valid and changes occur to the subscribed resource, Microsoft Graph sends change notifications to the notificationUrl endpoint.
  4. Regularly renew the subscription to maintain its validity and continue receiving updates on the subscribed changes.