Subscription and notification schema changes in beta REST API


I wanted to update you all on some more breaking changes that we are making to the Outlook REST API beta endpoint. These changes impact Notifications and Webhooks. They are going to be deployed worldwide in phases over the next few weeks.

Since this deployment is going in phases, you may see up to two breaking changes for some of the APIs. In this blog, I’ll provide the final state of every change as well as its corresponding interim state (if applicable) during the phased rollout.

There are two type of changes; schema changes and functional changes. Refer to the notification reference documentation for the current schema and functional behavior. Below are the details of each one.

Schema changes

Schema changes apply to both subscription requests and notification payloads as follows. Also they apply to both https://outlook.office.com/api/beta and https://outlook.office365.com/api/beta endpoints.

Subscription request

The following subscription properties were updated as part of the breaking change. The table below shows the current property name, interim name and final name.

Current Interim Final
ResourceURL resource Resource
CallbackURL notificationURL NotificationURL
ClientState context ClientState
ExpirationTime subscriptionExpirationDateTime SubscriptionExpirationDateTime
ChangeType changeType ChangeType

Subscription sample

Final version (changes highlighted)

 {
   @odata.type:"#Microsoft.OutlookServices.PushSubscription",
   Resource: "https://outlook.office.com/api/beta/me/folders('Inbox')/messages",
   NotificationURL: "https://webhook.azurewebsites.net/api/send/rest_notify",
   ChangeType: "Created, Updated, Deleted",
   SubscriptionExpirationDateTime: "2015-10-24T18:40:00.0Z",
   ClientState: "Client information"
 } 

Interim version (changes highlighted)

 {   @odata.type:"#Microsoft.OutlookServices.PushSubscription",
   resource: "https://outlook.office.com/api/beta/me/folders('Inbox')/messages",
   notificationURL: "https://webhook.azurewebsites.net/api/send/rest_notify",
   changeType: "Created, Updated, Deleted",
   subscriptionExpirationDateTime: "2015-10-24T18:40:00.0Z",
   context: "Client information"
 } 

Notification payload

The following property was added to the notification body.

Interim Final
resource Resource

The following notification properties were updated as part of the breaking change. The table below shows the current property name, interim name and final name.

Header

Current name Interim name Final name
x-ClientState x-context ClientState

Body

Current name Interim name Final name
Entity resourceData ResourceData
SubscriptionExpirationTime subscriptionExpirationDateTime SubscriptionExpirationDateTime
SubscriptionId* subscriptionId SubscriptionId
SequenceNumber* sequenceNumber SequenceNumber
ChangeType* changeType ChangeType

* indicates lowerCamelCase type change in the interim version

Notification sample

Final version (changes highlighted)

 ClientState: Client information
 OData-Version: 4.0
 
 {
   "value": [
     {
       "@odata.type": "#Microsoft.OutlookServices.Notification",
       "Id": null,
       "SubscriptionId": "Y3BENzI2MEMtODNDOS00OTgwLUI4MzYtRkU0RkJFQ0QwNDA0XzI0MjlFMDM3LTIyODAtNDI5QS05RTI5LTQ2ODJEMjUxNDFENg==",
       "SubscriptionExpirationDateTime": "2015-10-24T18:40:00Z",
       "SequenceNumber": 1,
       "ChangeType": "Created",
       "Resource": "https://outlook.office.com/api/beta/Users('user@contoso.com')/Messages('AQMkADI0MjllMDM3LTIyADgwLTQyOWEtOWUyOS00NjgyZDI1MTQxZDYARgAAA8rN0_5DrtJIjeiZuFmXzhwHAMS1HuBHgjpCsMTk7B3DDOIAAAIBDAAAAMS1HuBHgjpCsMTk7B3DDOIAAAIFeQAAAA==')",
       "ResourceData": {
         "@odata.type": "#Microsoft.OutlookServices.Message",
         "@odata.id": "https://outlook.office.com/api/beta/Users('user@contoso.com')/Messages('AQMkADI0MjllMDM3LTIyADgwLTQyOWEtOWUyOS00NjgyZDI1MTQxZDYARgAAA8rN0_5DrtJIjeiZuFmXzhwHAMS1HuBHgjpCsMTk7B3DDOIAAAIBDAAAAMS1HuBHgjpCsMTk7B3DDOIAAAIFeQAAAA==')",
         "@odata.etag": "W/\"CQAAABYAAADEtR7gR4I6QrDE5OwdwwziAAAAAAT1\"",
         "Id": "AQMkADI0MjllMDM3LTIyADgwLTQyOWEtOWUyOS00NjgyZDI1MTQxZDYARgAAA8rN0_5DrtJIjeiZuFmXzhwHAMS1HuBHgjpCsMTk7B3DDOIAAAIBDAAAAMS1HuBHgjpCsMTk7B3DDOIAAAIFeQAAAA=="
       }
     }
   ]
 } 

Interim version (changes highlighted)

 x-context: Client information
 OData-Version: 4.0
 
 {
   "value": [
     {
       "@odata.type": "#Microsoft.OutlookServices.Notification",
       "Id": null,
       "subscriptionId": "Y3BENzI2MEMtODNDOS00OTgwLUI4MzYtRkU0RkJFQ0QwNDA0XzI0MjlFMDM3LTIyODAtNDI5QS05RTI5LTQ2ODJEMjUxNDFENg==",
       "subscriptionExpirationDateTime": "2015-10-24T18:40:00Z",
       "sequenceNumber": 1,
       "changeType": "Created",
       "resource": "https://outlook.office.com/api/beta/Users('user@contoso.com')/Messages('AQMkADI0MjllMDM3LTIyADgwLTQyOWEtOWUyOS00NjgyZDI1MTQxZDYARgAAA8rN0_5DrtJIjeiZuFmXzhwHAMS1HuBHgjpCsMTk7B3DDOIAAAIBDAAAAMS1HuBHgjpCsMTk7B3DDOIAAAIFeQAAAA==')",
       "resourceData": {
         "@odata.type": "#Microsoft.OutlookServices.Message",
         "@odata.id": "https://outlook.office.com/api/beta/Users('user@contoso.com')/Messages('AQMkADI0MjllMDM3LTIyADgwLTQyOWEtOWUyOS00NjgyZDI1MTQxZDYARgAAA8rN0_5DrtJIjeiZuFmXzhwHAMS1HuBHgjpCsMTk7B3DDOIAAAIBDAAAAMS1HuBHgjpCsMTk7B3DDOIAAAIFeQAAAA==')",
         "@odata.etag": "W/\"CQAAABYAAADEtR7gR4I6QrDE5OwdwwziAAAAAAT1\"",
         "Id": "AQMkADI0MjllMDM3LTIyADgwLTQyOWEtOWUyOS00NjgyZDI1MTQxZDYARgAAA8rN0_5DrtJIjeiZuFmXzhwHAMS1HuBHgjpCsMTk7B3DDOIAAAIBDAAAAMS1HuBHgjpCsMTk7B3DDOIAAAIFeQAAAA=="
       }
     }
   ]
 } 

Functional changes

There are four breaking functional changes in Beta. These changes are:

  1. Changes in Renew subscription API
  2. Addition of Notification URL validation
  3. Retiring Acknowledgement notification
  4. No ClientState in Subscription query response

Not all changes apply to the interim. Here is the functional change applicability matrix (final versus interim):

Functional change Interim Final
Changes in Renew subscription API Yes Yes
Addition of Notification URL validation No Yes
Retiring Acknowledgement notification No Yes
No ClientState in Subscription query response Yes Yes

Changes in Renew subscription API

The renew subscription mechanism changed from POST to PATCH with payload like the following.

Final version

 {
   @odata.type:"#Microsoft.OutlookServices.PushSubscription",
   SubscriptionExpirationDateTime: "2015-10-24T20:00:00.0Z"
 } 

Interim version

 {
     @odata.type:"#Microsoft.OutlookServices.PushSubscription",
     subscriptionExpirationDateTime: "2015-10-24T20:00:00.0Z"
 } 

Addition of Notification URL validation

Outlook REST APIs added validation for notification (callback) URL as part of creating a new subscription. Validation occurs as follows:

  1. Outlook service post the following to webhook service:
     POST https://<notificationUrl>?validationtoken=<TokenDefinedByService>
     
     ClientState: <Data sent in ClientState value in subscription request (if any)> 
  2. Webhooks service must provide a 200 response with the validationtoken value in its body as type plain/text within 5 seconds. The validation token is a random string that should be discarded by the webhook after providing it in the response.

Retiring Acknowledgement notification

The notification URL validation process is replacing the acknowledgement notification.

No ClientState in Subscription query response

The ClientState (or context in interim state) property is not going to be sent back when a client queries for a specific subscription.

More extensive documentation on the new functionality is coming soon in our API reference documentation page. Please let us know if you have any questions, and visit http://dev.outlook.com for the latest news and updates.

This post was a guest post from Abdelkader Bahgat, a Senior Program Manager with the Outlook team.

Comments (6)

  1. Christopher says:

    We can create, renew, delete, but Is there any way to retrieve all the current subscriptions ? Something like:

    GET outlook.office.com/…/subscriptions

    'Accept': 'application/json;odata.metadata=none',

    'Authorization': 'Bearer {0}'.format(access_token)

    Thanks a lot

  2. Christopher says:

    I also noticed that once the webhook is registered,

    I receive 3 times this webhook in 2 min:

    POST /integrations/office365/i/DbDq8ndl/hook/ee213a64970b69b7606670bb4aa7xxxxxxxxxxx/

    HTTP/1.1

    Content-Type: application/json; charset=utf-8

    Accept: text/xml

    Host: 4aade094.ngrok.io

    OData-Version: 4.0

    Content-Length: 312

    Connection: Close

    X-Forwarded-Proto: https

    X-Forwarded-For: 132.245.55.149

    {"value":[{"@odata.type":"#Microsoft.OutlookServices.Notification","Id":null,"subscriptionId":"RjQ0NUQwMTItMjNFMS00MDJGLUFGMEUtRTkwNUFCMTI1QzA5XzZCMDNBODk0LThFMEUtNEFBMi1BMUZFLTA1NjIwNjM3Rjk0RA==","subscriptionExpirationDateTime":"2015-11-01T12:57:57.8518183Z","sequenceNumber":0,"changeType":"Acknowledgment"}]}

    Between the first time i receive this webhook and the last one, i can receive any kind of activity webhook, but once i receive for the third time this webhook described above, no matter activity i generate, i stop receiving webhooks and my subscription seems cancelled, i do not understand why, i do respond:

    HTTP/1.1 200 OK

    Server: nginx/1.9.1

    Date: Thu, 29 Oct 2015 13:02:44 GMT

    Content-Type: text/html; charset=utf-8

    Transfer-Encoding: chunked

    Connection: close

    X-Frame-Options: SAMEORIGIN

    each time and i have no client context nor token to send back to your backend, anyone can explain me what is going wrong here?

    Thanks a lot for your help

  3. Christopher says:

    I answer myself,

    in django, the Httpresponse('OK') use the HTTP 1.1 Schema, and in the body response it create the following:

    2 <-the content length

    OK <- the actual response

    0 <-still no idea what this one is

    Well turns out your backend is really not fan of this answer and most likely don't understand it ,so it keep sending me again the webhooks before it gave up, the solution is to not send anything at all in the body and it works fine ! weird behavior

  4. Michael says:

    Hello there,

    I tried to renew the subscription, I send a patch request (with and without payload) to

    outlook.office.com/…/renew

    I am getting back

    {"error":{"code":"RequestBrokerOld-ParseUri","message":"Resource not found for the segment 'renew'."}}

    Could anyone suggest how to fix this please? My code did work prior to the change discussed in this blog post.

    Thanks,

    Michael

  5. Michael: there's no /renew segment to the URL. You should just send a patch to outlook.office.com/api/beta/me/subscriptions/{subscription id} with the payload.

  6. Herz3h says:

    I managed to register the webhook url, i get a subscription ID. Then i go to office365 calendar or outlook calendar (tried with two accounts) and whenever i change something on the calendar the webhook url I provided gets called but i get an empty array : [] <– like this

    This is my subscription request :

    POST outlook.office.com/…/subscriptions HTTP/1.1

    Content-Type: application/json

    {

      @odata.type:"#Microsoft.OutlookServices.PushSubscription",

      Resource: "outlook.office.com/…/events",

      NotificationURL: "https://mywebsitehere/api/send/notificationClient&quot;,  

      ChangeType: "Created, Updated, Deleted"

    }

    And i used the following scope : openid and outlook.office.com/Calendars.ReadWrite

    Could you help me i've been stuck on this part for two days…and couldn't find any help on the internet since the api is still new.

Skip to main content