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:
- Changes in Renew subscription API
- Addition of Notification URL validation
- Retiring Acknowledgement notification
- 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:
Outlook service post the following to webhook service:
POST https://<notificationUrl>?validationtoken=<TokenDefinedByService> ClientState: <Data sent in ClientState value in subscription request (if any)>
Webhooks service must provide a 200 response with the
validationtoken
value in its body as typeplain/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 https://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
Anonymous
October 28, 2015
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 lotAnonymous
October 28, 2015
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 helpAnonymous
October 29, 2015
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 behaviorAnonymous
November 03, 2015
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, MichaelAnonymous
November 04, 2015
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.Anonymous
January 17, 2016
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", 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.Anonymous
June 27, 2017
hi, After subscription the notifications will be sent to notification url. how to forward it to my application? What API should be used to get response ?