Outlooh Webhook subscription send multiple triggers for webhook receiver when i do one action

Venujan v 0 Reputation points

Hi Microsoft Team,

We are using Microsoft Graph webhook subscriptions for Outlook room calendar events.

When we create or update only one room calendar event, our webhook receiver is triggered multiple times for the same action.

For example, for one booking create or update, we receive multiple webhook calls like:

created

updated

updated

updated

Sometimes, when we update one existing event, the webhook first sends created and then updated.

Because of this, our system may process the same booking multiple times and create duplicate records.

We want to understand the expected behavior of Microsoft Graph webhooks for Outlook room calendars.

Our questions are:

  1. Is it expected that one Outlook room calendar event can trigger multiple webhook notifications?
  2. Why does one event creation trigger both created and updated notifications?
  3. Why does an event update sometimes trigger created first and then updated?
  4. Is there any way to receive only one final notification for the actual user action?
  5. Is there any way to avoid internal Outlook/Exchange update notifications?
  6. What is the recommended way to identify and ignore duplicate webhook notifications?
  7. Should we use event id, change key, iCalUId, or last modified time to detect duplicate notifications?
  8. For room calendars, what is the best practice to process only the final real event change?
  9. Can Microsoft Graph guarantee that only one webhook notification will be sent for one user action?
  10. If duplicate notifications are expected, what is Microsoft’s recommended design pattern to prevent duplicate processing?

We need guidance because duplicate webhook triggers are causing duplicate booking creation/update in our application.

Example issue:

User creates one Outlook room event.

But webhook receiver receives multiple calls:

1st call: created

2nd call: updated

3rd call: updated

4th call: updated

Expected:

Only one notification for the actual event creation.

Actual:

Multiple notifications are received for the same event.

0 comments No comments

Sign in to comment

1 answer

  1. Pravallika KV 17,025 Reputation points Microsoft External Staff Moderator

    Hi @Venujan v ,

    Graph webhooks for Outlook room calendars can indeed fire multiple times for what looks like “one” user action. Here’s what’s happening and how to handle it:

    1. Why you see multiple notifications
    • Internal system updates: when you create an event, Exchange makes a series of internal changes to the mailbox (mailbox store, resource mailbox, etc.), so you see a “created” plus one or more “updated” notifications. The same goes for an update it may write the change in stages, bumping the changeKey multiple times.
    • No single “final” notification: Graph can’t collapse all of those internal writes into one “final” call for you. There’s no Graph guarantee of exactly one callback per user action.
    1. Can you suppress internal updates? Unfortunately, no. There’s no Graph subscription flag to “only give me the last update” or to filter out Exchange’s internal mailbox writes.
    2. How to avoid duplicate processing Design your webhook receiver to be idempotent. Common patterns are:
    • Persist the combination of event id + changeKey (the @odata.etag in the resourceData). Only process when you see a new changeKey.
    • You can also use the iCalUId (same across series of related updates) and the lastModifiedDateTime.
    • On each notification, look up the stored latest changeKey/timestamp. If the incoming changeKey is identical or older, skip it.
    1. Best practice for room calendars
    • Store for each event: event id + latest changeKey.
    • When you get a notification, fetch the event from Graph (GET /users/{roomMailbox}/events/{id}) and compare its lastModifiedDateTime or ETag to what you’ve stored. Only act if it’s newer.
    • This way, even if you get created→updated→updated, only your first “new” changeKey triggers business logic.
    1. Design pattern recap
    • Assume Graph notifications are “at least once,” not “exactly once.”
    • Make your processing idempotent using event id + changeKey or timestamp.
    • Optionally poll the single event after debouncing your notification stream, e.g. queue notifications for 1–2 seconds, then fetch once.
    1. Below are the answers to your questions
      1. Yes, one user action can generate multiple internals that fire separate Graph notifications.
      2/3. Creation writes and updates under‐the‐covers, so you see both. 4/5. There is no subscription setting to collapse or filter out those internal updates. 6/7/8. Dedupe by tracking id + changeKey (ETag) or lastModifiedDateTime (and/or iCalUId).
      1. No, Microsoft Graph can’t guarantee a single callback per action.
      2. Build your consumer to handle duplicates as described above.

    Hope that helps you avoid duplicate bookings!

    References:

    Hope this helps!


    If the resolution was helpful, kindly take a moment to click on 👁 User's image
    and click on Yes for was this answer helpful. And, if you have any further query do let us know.

    1. Venujan v 0 Reputation points

      hi @Pravallika KV
      Microsoft Graph Outlook room calendar subscription returns duplicate/unstable event IDs and recurring event details are unclear

      Hi Microsoft Team,

      We are using Microsoft Graph change notifications for Outlook room calendar events.

      Our subscription resource is:

      /users/{roomMailbox}/events

      The subscription changeType is:

      created,updated,deleted

      Our webhook receiver is an Azure Logic App.

      We are facing issues with event IDs and recurring room bookings.

      Issue 1: Same or duplicate event IDs from subscription

      Sometimes, when different Outlook room events are created or updated, the subscription notification returns the same or very similar event ID.

      When we try to call the event using:

      GET /users/{roomMailbox}/events/{eventId}

      we sometimes receive this error:

      { "error": { "code": "ErrorItemNotFound", "message": "The specified object was not found in the store." } }

      Because of this, we cannot always use the event ID from the subscription notification to get the actual event details.

      Issue 2: Duplicate webhook triggers for one booking

      For one Outlook room event create/update, the webhook receiver is triggered multiple times.

      Example:

      created updated updated

      Sometimes, when updating an existing event, the first notification comes as created and then later updated.

      This causes duplicate processing in our system if we depend only on changeType and eventId.

      Issue 3: Recurring booking works differently from single booking

      When we create a recurring booking in Outlook, the subscription webhook is triggered.

      But the event ID from the subscription notification cannot always be used with:

      GET /users/{roomMailbox}/events/{eventId}

      Also, in some recurring booking responses, seriesMasterId is null.

      We understand that recurring events may have different types such as:

      singleInstance seriesMaster occurrence exception

      But in our case, when a recurring booking is created, it is not clear which ID should be used as the main identity of the recurring series.

      Questions:

      Is it expected that the event ID from a Microsoft Graph subscription notification may not always be retrievable using GET /users/{room}/events/{eventId}?

      Why does GET /events/{eventId} return ErrorItemNotFound even though the Outlook room booking exists?

      Is it expected that room calendar webhook notifications can send duplicate or unstable event IDs?

      For recurring room bookings, why is seriesMasterId sometimes null?

      If seriesMasterId is null for a recurring booking, should we treat the event’s own id as the series master id?

      For recurring bookings, what is the recommended way to identify the original recurring series and its occurrences?

      Should we use /events/{id}, /calendarView, or /events/{seriesMasterId}/instances to process recurring room bookings?

      For duplicate webhook triggers, what is the recommended deduplication key?

      We are considering using:

      roomEmail + iCalUId + startDateTime + changeKey

      instead of only:

      eventId + changeKey

      Is this the recommended approach for Outlook room calendar synchronization?

      Our goal is:

      • Avoid duplicate booking creation

      Correctly identify single bookings

      Correctly identify recurring series and occurrences

      Handle updates and cancellations reliably

      Please advise the recommended Microsoft Graph approach for syncing Outlook room calendar events, especially for recurring bookings and duplicate webhook notifications.Title:

      Microsoft Graph Outlook room calendar subscription returns duplicate/unstable event IDs and recurring event details are unclear

      Hi Microsoft Team,

      We are using Microsoft Graph change notifications for Outlook room calendar events.

      Our subscription resource is:

      /users/{roomMailbox}/events

      The subscription changeType is:

      created,updated,deleted

      Our webhook receiver is an Azure Logic App.

      We are facing issues with event IDs and recurring room bookings.

      Issue 1: Same or duplicate event IDs from subscription

      Sometimes, when different Outlook room events are created or updated, the subscription notification returns the same or very similar event ID.

      When we try to call the event using:

      GET /users/{roomMailbox}/events/{eventId}

      we sometimes receive this error:

      {
      "error": {
      "code": "ErrorItemNotFound",
      "message": "The specified object was not found in the store."
      }
      }

      Because of this, we cannot always use the event ID from the subscription notification to get the actual event details.

      Issue 2: Duplicate webhook triggers for one booking

      For one Outlook room event create/update, the webhook receiver is triggered multiple times.

      Example:

      created
      updated
      updated

      Sometimes, when updating an existing event, the first notification comes as created and then later updated.

      This causes duplicate processing in our system if we depend only on changeType and eventId.

      Issue 3: Recurring booking works differently from single booking

      When we create a recurring booking in Outlook, the subscription webhook is triggered.

      But the event ID from the subscription notification cannot always be used with:

      GET /users/{roomMailbox}/events/{eventId}

      Also, in some recurring booking responses, seriesMasterId is null.

      We understand that recurring events may have different types such as:

      singleInstance
      seriesMaster
      occurrence
      exception

      But in our case, when a recurring booking is created, it is not clear which ID should be used as the main identity of the recurring series.

      Questions:

      Is it expected that the event ID from a Microsoft Graph subscription notification may not always be retrievable using GET /users/{room}/events/{eventId}?

      Why does GET /events/{eventId} return ErrorItemNotFound even though the Outlook room booking exists?

      Is it expected that room calendar webhook notifications can send duplicate or unstable event IDs?

      For recurring room bookings, why is seriesMasterId sometimes null?

      If seriesMasterId is null for a recurring booking, should we treat the event’s own id as the series master id?

      For recurring bookings, what is the recommended way to identify the original recurring series and its occurrences?

      Should we use /events/{id}, /calendarView, or /events/{seriesMasterId}/instances to process recurring room bookings?

      For duplicate webhook triggers, what is the recommended deduplication key?

      We are considering using:

      roomEmail + iCalUId + startDateTime + changeKey

      instead of only:

      eventId + changeKey

      Is this the recommended approach for Outlook room calendar synchronization?

      Our goal is:

      Avoid duplicate booking creation

      Correctly identify single bookings

      Correctly identify recurring series and occurrences

      Handle updates and cancellations reliably

      Please advise the recommended Microsoft Graph approach for syncing Outlook room calendar events, especially for recurring bookings and duplicate webhook notifications.

    2. Venujan v 0 Reputation points

      hi @Pravallika KV
      Microsoft Graph Outlook room calendar subscription returns duplicate/unstable event IDs and recurring event details are unclear

      Hi Microsoft Team,

      We are using Microsoft Graph change notifications for Outlook room calendar events.

      Our subscription resource is:

      /users/{roomMailbox}/events

      The subscription changeType is:

      created,updated,deleted

      Our webhook receiver is an Azure Logic App.

      We are facing issues with event IDs and recurring room bookings.

      Issue 1: Same or duplicate event IDs from subscription

      Sometimes, when different Outlook room events are created or updated, the subscription notification returns the same or very similar event ID.

      When we try to call the event using:

      GET /users/{roomMailbox}/events/{eventId}

      we sometimes receive this error:

      { "error": { "code": "ErrorItemNotFound", "message": "The specified object was not found in the store." } }

      Because of this, we cannot always use the event ID from the subscription notification to get the actual event details.

      Issue 2: Duplicate webhook triggers for one booking

      For one Outlook room event create/update, the webhook receiver is triggered multiple times.

      Example:

      created updated updated

      Sometimes, when updating an existing event, the first notification comes as created and then later updated.

      This causes duplicate processing in our system if we depend only on changeType and eventId.

      Issue 3: Recurring booking works differently from single booking

      When we create a recurring booking in Outlook, the subscription webhook is triggered.

      But the event ID from the subscription notification cannot always be used with:

      GET /users/{roomMailbox}/events/{eventId}

      Also, in some recurring booking responses, seriesMasterId is null.

      We understand that recurring events may have different types such as:

      singleInstance seriesMaster occurrence exception

      But in our case, when a recurring booking is created, it is not clear which ID should be used as the main identity of the recurring series.

      Questions:

      Is it expected that the event ID from a Microsoft Graph subscription notification may not always be retrievable using GET /users/{room}/events/{eventId}?

      Why does GET /events/{eventId} return ErrorItemNotFound even though the Outlook room booking exists?

      Is it expected that room calendar webhook notifications can send duplicate or unstable event IDs?

      For recurring room bookings, why is seriesMasterId sometimes null?

      If seriesMasterId is null for a recurring booking, should we treat the event’s own id as the series master id?

      For recurring bookings, what is the recommended way to identify the original recurring series and its occurrences?

      Should we use /events/{id}, /calendarView, or /events/{seriesMasterId}/instances to process recurring room bookings?

      For duplicate webhook triggers, what is the recommended deduplication key?

      We are considering using:

      roomEmail + iCalUId + startDateTime + changeKey

      instead of only:

      eventId + changeKey

      Is this the recommended approach for Outlook room calendar synchronization?

      Our goal is:

      • Avoid duplicate booking creation

      Correctly identify single bookings

      Correctly identify recurring series and occurrences

      Handle updates and cancellations reliably

      Please advise the recommended Microsoft Graph approach for syncing Outlook room calendar events, especially for recurring bookings and duplicate webhook notifications.Title:

      Microsoft Graph Outlook room calendar subscription returns duplicate/unstable event IDs and recurring event details are unclear

      Hi Microsoft Team,

      We are using Microsoft Graph change notifications for Outlook room calendar events.

      Our subscription resource is:

      /users/{roomMailbox}/events

      The subscription changeType is:

      created,updated,deleted

      Our webhook receiver is an Azure Logic App.

      We are facing issues with event IDs and recurring room bookings.

      Issue 1: Same or duplicate event IDs from subscription

      Sometimes, when different Outlook room events are created or updated, the subscription notification returns the same or very similar event ID.

      When we try to call the event using:

      GET /users/{roomMailbox}/events/{eventId}

      we sometimes receive this error:

      {
      "error": {
      "code": "ErrorItemNotFound",
      "message": "The specified object was not found in the store."
      }
      }

      Because of this, we cannot always use the event ID from the subscription notification to get the actual event details.

      Issue 2: Duplicate webhook triggers for one booking

      For one Outlook room event create/update, the webhook receiver is triggered multiple times.

      Example:

      created
      updated
      updated

      Sometimes, when updating an existing event, the first notification comes as created and then later updated.

      This causes duplicate processing in our system if we depend only on changeType and eventId.

      Issue 3: Recurring booking works differently from single booking

      When we create a recurring booking in Outlook, the subscription webhook is triggered.

      But the event ID from the subscription notification cannot always be used with:

      GET /users/{roomMailbox}/events/{eventId}

      Also, in some recurring booking responses, seriesMasterId is null.

      We understand that recurring events may have different types such as:

      singleInstance
      seriesMaster
      occurrence
      exception

      But in our case, when a recurring booking is created, it is not clear which ID should be used as the main identity of the recurring series.

      Questions:

      Is it expected that the event ID from a Microsoft Graph subscription notification may not always be retrievable using GET /users/{room}/events/{eventId}?

      Why does GET /events/{eventId} return ErrorItemNotFound even though the Outlook room booking exists?

      Is it expected that room calendar webhook notifications can send duplicate or unstable event IDs?

      For recurring room bookings, why is seriesMasterId sometimes null?

      If seriesMasterId is null for a recurring booking, should we treat the event’s own id as the series master id?

      For recurring bookings, what is the recommended way to identify the original recurring series and its occurrences?

      Should we use /events/{id}, /calendarView, or /events/{seriesMasterId}/instances to process recurring room bookings?

      For duplicate webhook triggers, what is the recommended deduplication key?

      We are considering using:

      roomEmail + iCalUId + startDateTime + changeKey

      instead of only:

      eventId + changeKey

      Is this the recommended approach for Outlook room calendar synchronization?

      Our goal is:

      Avoid duplicate booking creation

      Correctly identify single bookings

      Correctly identify recurring series and occurrences

      Handle updates and cancellations reliably

      Please advise the recommended Microsoft Graph approach for syncing Outlook room calendar events, especially for recurring bookings and duplicate webhook notifications.

    3. Pravallika KV 17,025 Reputation points Microsoft External Staff Moderator

      @Venujan v ,Thank you for the detailed information.

      Based on the behavior you described, the issues you are observing are generally consistent with how Microsoft Graph change notifications and Exchange Online calendar processing work for Outlook room mailboxes.

      1. Event IDs returned in change notifications

      The id included in a Microsoft Graph change notification identifies the calendar item that triggered the notification at the time the notification was generated. However, applications should not assume that every notification ID can always be successfully retrieved later using:

      GET /users/{roomMailbox}/events/{eventId}

      Receiving an ErrorItemNotFound response can occur in several scenarios, including:

      • The event was modified again immediately after the notification was generated.
      • The event was deleted, cancelled, or moved.
      • Notifications were delivered out of order.
      • Exchange processing had not fully completed when the GET request was issued.
      • The event represents part of a recurring series whose underlying occurrence representation changed.

      For these reasons, applications should treat change notifications as signals that a change occurred rather than as a guarantee that the exact item version referenced by the notification will always be available.

      1. Multiple notifications for a single booking

      Yes, it is expected that a single user action can generate multiple Microsoft Graph notifications.

      For example, creating or updating a room booking may produce notifications such as:

      • created
      • updated
      • updated

      or

      • created
      • updated

      Exchange Online performs multiple internal mailbox updates when processing calendar events, including organizer updates, room mailbox processing, attendee updates, recurrence processing, and metadata updates.

      Microsoft Graph change notifications provide an at-least-once delivery model and do not guarantee a one-to-one mapping between a user action and a notification.

      Therefore, applications should be designed to handle duplicate and repeated notifications.

      1. Recurring meetings and seriesMasterId

      For recurring meetings, the event type is important.

      Possible values include:

      • singleInstance
      • seriesMaster
      • occurrence
      • exception

      The behavior of seriesMasterId depends on the event type:

      Event Type seriesMasterId
      singleInstance null
      -------- --------
      singleInstance null
      seriesMaster null
      occurrence populated
      exception populated

      Therefore, a null seriesMasterId does not necessarily indicate a problem.

      If the event type is seriesMaster, the event's own id represents the recurring series master.

      If the event type is singleInstance, the event is not part of a recurring series.

      We do not recommend assuming that every event with a null seriesMasterId belongs to a recurring series.

      1. Recommended approach for recurring bookings

      When processing recurring room bookings:

      1. Receive the notification.
      2. Retrieve the latest event state from Microsoft Graph.
      3. Inspect the event type.
      4. Process according to the event type:
        • singleInstance → process as an individual booking.
        • seriesMaster → process as the recurring series definition.
        • occurrence or exception → associate with the corresponding seriesMasterId.

      For retrieving occurrences of a recurring meeting, the following endpoint is typically recommended:

      GET /users/{roomMailbox}/events/{seriesMasterId}/instances

      For synchronization or reconciliation across a date range, calendarView is often more suitable than querying individual events.

      1. Recommended deduplication strategy

      Because duplicate notifications are expected, webhook consumers should implement idempotent processing.

      Using only:

      eventId + changeKey

      may not always be sufficient for long-term synchronization scenarios.

      A more robust correlation strategy is:

      • Room mailbox identifier
      • iCalUId
      • Event ID
      • ChangeKey
      • LastModifiedDateTime (optional)

      General guidance:

      • Treat changeKey as the version identifier of an event.
      • If the same event ID and changeKey combination has already been processed, ignore the notification.
      • Only process when a newer changeKey is observed.
      • Use iCalUId to correlate related copies of the same meeting and recurring series members.
      1. Recommended synchronization architecture

      For room mailbox synchronization, we typically recommend:

      Notification received → Queue notification → Deduplicate using event ID and changeKey → Retrieve latest event state → Process event type → Persist latest state → Periodically reconcile using calendarView

      This approach helps handle:

      • Duplicate notifications
      • Out-of-order notifications
      • Recurring meetings
      • Room mailbox processing updates
      • Temporary retrieval failures
      1. Notification guarantees

      Microsoft Graph does not guarantee that a single user action results in only one notification.

      Applications should expect:

      • Duplicate notifications
      • Multiple notifications for a single user action
      • Out-of-order delivery
      • Retry deliveries

      and should implement idempotent processing accordingly.

      If you continue to see ErrorItemNotFound for active bookings after implementing retries and fetching the latest event state, please provide:

      • Sample notification payloads (with sensitive information removed)
      • The event type (singleInstance, seriesMaster, occurrence, or exception)
      • Whether the notification includes resource data
      • The approximate timing between the notification and the GET request
    4. Pravallika KV 17,025 Reputation points Microsoft External Staff Moderator

      @Venujan v , Following up to see if the provided answer was helpful. If this answers your query, do click Accept Answer =>Yes, and upvote it. If you have any further queries do let us know.


    Sign in to comment
Sign in to answer

Your answer