Microsoft Graph change notifications and webhooks
How Microsoft Graph subscriptions push notifications to your endpoints when data changes — instead of polling.
Microsoft Graph change notifications (often called webhooks in this context) push notifications to your endpoint when specific data changes — mail arrives, files are uploaded, calendar events change, users update profiles, devices report new compliance state. Instead of your app polling Graph for changes, Graph calls you.
How subscriptions work
The pattern:
-
Your app creates a subscription via Microsoft Graph specifying:
- Resource to watch (e.g.,
/users/{id}/messages,/users/{id}/drive/root,/groups/{id}/conversations). - Change types to receive (
created,updated,deleted). - Notification URL — your HTTPS endpoint that Graph will POST to.
- Expiration time — subscriptions expire and must be renewed.
- Client state — a token you set, returned in every notification to confirm authenticity.
- Resource to watch (e.g.,
-
Graph validates your endpoint by sending a one-time validation token, which your endpoint must echo back. This proves you control the endpoint.
-
Graph POSTs notifications to your endpoint when matching changes occur. Each notification includes the resource ID, change type, and minimal context.
-
Your app fetches details from Graph — the notification doesn't include the changed content itself (for security and size reasons); you call Graph to get the actual resource.
-
You acknowledge by returning 202 Accepted within ~30 seconds. Graph retries if you don't.
Why subscriptions beat polling
Polling Graph for changes is expensive and slow:
- Throttling — Graph rate-limits aggressively; polling thousands of users hits limits.
- Latency — even hourly polling means up to an hour of delay.
- Wastefulness — most polls return "no changes."
Subscriptions are event-driven: zero traffic until something changes, then sub-second latency. For any non-trivial Microsoft 365 integration, subscriptions are the right pattern.
What resources support subscriptions
The list grows over time but currently includes:
- Users — profile changes, sign-ins, password changes.
- Mail messages — new mail, mail updates, mail deletes.
- Calendar events — event creation, updates, deletes.
- Drive items — file changes in SharePoint and OneDrive.
- Teams channel messages — new posts, edits.
- Teams call records — call started, ended.
- Groups — group creation, membership changes.
- Security alerts — new alerts in Defender XDR.
- Devices — Intune device compliance changes.
Each resource type has specific scoping options — single user vs all users vs specific group.
Operational considerations
Subscription lifecycle
Subscriptions expire — typically 3 days to 30 days depending on resource. Your app must renew before expiration. Best practice: a scheduled task that renews 24 hours before expiration.
Endpoint reliability
If your endpoint fails to respond to notifications consistently, Graph disables the subscription to avoid retrying indefinitely. Build for reliability — load balancers, queues, error handling.
Encryption for sensitive content
For change notifications on sensitive resources (mail body, file content), Graph supports rich notifications with encryption. You provide a certificate; Graph encrypts the payload to your certificate's public key. Your app decrypts with the private key. The notification then includes content directly, removing the need to fetch from Graph.
Throttling on subscription creation
Creating many subscriptions in burst is throttled. Spread out subscription creation over time, or batch via Graph's batch endpoint.
Permission scopes
Subscriptions require the same Graph permissions as reading the underlying resource. Subscribing to /users/{id}/mail/messages requires Mail.Read at minimum (delegated or application).
A worked example
A custom Help desk app wants to file every incoming email to support@yourcompany.com as a ticket:
- Create a subscription on
/users/{support-mailbox-id}/messageswith change typecreated, notification URL pointing at the app's webhook. - Graph validates the endpoint.
- When mail arrives at the shared mailbox, Graph POSTs a notification.
- The app fetches the message via Graph using the resource ID.
- The app creates a ticket in the help desk system.
- The app processes the message (forwards, tags, etc.).
- Repeat for every incoming message, in near real time.
For any Microsoft 365 integration involving change-driven workflows, change notifications are the right foundation. They're efficient, low-latency, and reliable when built carefully.