{"id":1011,"date":"2016-01-14T00:00:00","date_gmt":"2016-01-14T07:00:00","guid":{"rendered":"http:\/\/officedevblogs.wpengine.com\/?p=1011"},"modified":"2016-01-14T00:00:00","modified_gmt":"2016-01-14T07:00:00","slug":"microsoft-graph-webhooks-update-january-2016","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/microsoft-graph-webhooks-update-january-2016\/","title":{"rendered":"Microsoft Graph WebHooks Update &#8211; January 2016"},"content":{"rendered":"<div id=\"body-content\">\n<div>\n<p>Hi, Gareth Jones here.&nbsp; I recently joined the Microsoft Graph team from our friends over in <a href=\"https:\/\/dev.onenote.com\">OneNote<\/a>. I&#8217;m beyond excited at the wonderful enthusiasm you&#8217;ve shown for the <a href=\"https:\/\/developer.microsoft.com\/graph\">Microsoft Graph<\/a> since we launched at Connect(); back in 2015 (wow, that sounds so retro now).<\/p>\n<p>  <br>  <\/p>\n<p>One area we didn&#8217;t talk about too much at launch time was our preview of WebHooks for the API, so we wanted to dive in and explain a little more what you can do with the preview and talk about an upcoming breaking change to validate endpoints. If you&#8217;re already using webhooks, skip ahead to the <a href=\"#changing\">what&#8217;s changing<\/a> section at the end.<\/p>\n<p>  <br>  <\/p>\n<h4>What&#8217;s a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Webhook\">webhook<\/a>?<\/h4>\n<p>Webhooks are callbacks for the web. They let you create web apps that respond efficiently to change in your user&#8217;s data. For example, if you want to keep up with changes to all the email messages in a user&#8217;s Vacation folder, perhaps to extract hotel or flight information, you can create a webhook subscription and get notified whenever there&#8217;s something new to process. This saves your app from having to regularly poll for changes.<\/p>\n<p>  <br>  <\/p>\n<p>So how do I get started?<\/p>\n<p>  <br>  <\/p>\n<p>If you&#8217;re already coding with the Microsoft Graph API, you&#8217;ll have an app registered, so you can authenticate and get an OAUTH token. If not, there&#8217;s a <a href=\"https:\/\/developer.microsoft.com\/graph\/docs\/get-started\/rest\">walkthrough here<\/a>.<\/p>\n<p>  <br>  <\/p>\n<p>Currently we support webhooks on mail, calendars and contacts, so you&#8217;ll need to make sure you have requested one of the matching scopes: Mail.Read, Calendars.Read, or Contacts.Read.<\/p>\n<p>  <br>  <\/p>\n<p>Then you&#8217;ll POST a request to the \/subscriptions endpoint like so<\/p>\n<p>  <br>  <\/p>\n<pre><code>  POST https:\/\/graph.microsoft.com\/beta\/subscriptions  Content-type: application\/json  Authorization: Bearer &lt;YourOAuthToken&gt;  {    \"changeType\": \"Created\",    \"notificationUrl\": \"https:\/\/&lt;YourAppURLHere&gt;\/api\/webhookCallback\",    \"resource\": \"me\/messages\"  }  <\/code><\/pre>\n<p>  <br>  <\/p>\n<p>This request asks for all changes to the user&#8217;s mail to be sent to the &#8216;\/api\/webhookCallback&#8217; path on your app. Note that the URL for your app MUST be https. You can also ask for &#8216;me\/contacts&#8221; or &#8220;me\/events&#8221; or a specific folder, such as &#8216;me\/folders(&#8216;vacation&#8217;)\/messages&#8217;.<\/p>\n<p>If all goes well, you&#8217;ll get a 201 Created response with the details of the subscription including an expiration time. You&#8217;ll need to replace your subscription after the expiration time with a new one. In future we&#8217;ll allow renewing an existing subscription. Here&#8217;s an example response:<\/p>\n<p>  <br>  <\/p>\n<pre><code>  HTTP\/1.1 201 Created  {    \"@odata.context\":\"https:\/\/graph.microsoft.com\/beta\/$metadata#subscriptions\/$entity\",    \"subscriptionId\":\"7f105c7d-2dc5-4530-97cd-4e7af6534c07\",    \"resource\":\"me\/messages\",    \"changeType\":\"Created\",    \"notificationUrl\":\"https:\/\/&lt;YourAppURLHere&gt;\/api\/webhookCallback\",    \"subscriptionExpirationDateTime\":\"2015-11-20T18:23:45.9356913Z\"  }  <\/code>  <\/pre>\n<p>  <br>  <\/p>\n<h4>What do I get?<\/h4>\n<p>As change to the user&#8217;s email happens, your webhook callback will then start receiving notification packets. We&#8217;ll send them batched up for efficiency, so you&#8217;ll typically see an array:<\/p>\n<p>  <br>  <\/p>\n<pre><code>  POST https:\/\/&lt;YourAppURLHere&gt;\/api\/webhookCallback  Content-type: application\/json  {    \"value\":[      {        \"subscriptionId\":\"7f105c7d-2dc5-4530-97cd-4e7af6534c07\",        \"subscriptionExpirationDateTime\":\"2015-11-20T18:23:45.9356913Z\",        \"changeType\":\"Created\",        \"resource\":\"Users\/ddfcd489-628b-7d04-b48b-20075df800e5@1717622f-1d94-c0d4-9d74-f907ad6677b4\/messages\/AAMkADMxZmEzMDM1LTFjODQtNGVkMC04YzY3LTBjZTRlNDFjNGE4MwBGAAAAAAAr-q_ZG7oXSaqxum7oZW5RBwCoeN6SYXGLRrvRm_CYrrfQAAAAAAEMAACoeN6SYXGLRrvRm_CYrrfQAACvtMe6AAA=\",        \"resourceData\":{          \"@odata.type\":\"#Microsoft.Graph.Message\",          \"@odata.id\":\"Users\/ddfcd489-628b-7d04-b48b-20075df800e5@1717622f-1d94-c0d4-9d74-f907ad6677b4\/messages\/AAMkADMxZmEzMDM1LTFjODQtNGVkMC04YzY3LTBjZTRlNDFjNGE4MwBGAAAAAAAr-q_ZG7oXSaqxum7oZW5RBwCoeN6SYXGLRrvRm_CYrrfQAAAAAAEMAACoeN6SYXGLRrvRm_CYrrfQAACvtMe6AAA=\",          \"@odata.etag\":\"W\/\"CQAAABYAAACoeN6SYXGLRrvRm+CYrrfQAACvvGdb\"\",          \"Id\":\"AAMkADMxZmEzMDM1LTFjODQtNGVkMC04YzY3LTBjZTRlNDFjNGE4MwBGAAAAAAAr-q_ZG7oXSaqxum7oZW5RBwCoeN6SYXGLRrvRm_CYrrfQAAAAAAEMAACoeN6SYXGLRrvRm_CYrrfQAACvtMe6AAA=\"        }      }    ]  }  <\/code>  <\/pre>\n<p>  <br>  <\/p>\n<p>That&#8217;s all there is to it! From there you can go and retrieve more details about the changed messages.<\/p>\n<p>  <br>  <\/p>\n<p>As a note, webhooks currently only work with app+user tokens, as all subscriptions are for changes in data belonging to a specific user. You can find more details about Microsoft Graph webhooks <a href=\"https:\/\/developer.microsoft.com\/graph\/docs\/api-reference\/beta\/api\/subscription_post_subscriptions\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/p>\n<p>  <br>  <\/p>\n<h4 id=\"changing\">What&#8217;s changing<\/h4>\n<p>As a preview, we&#8217;re always taking feedback and making minor adjustments to our APIs as we get them ready for production primetime in future. In the coming week, we&#8217;ll be tightening up our anti-spam protection a little with an extra validation check required before notifications start flowing.<\/p>\n<p>  <br>  <\/p>\n<p>As part of the act of subscribing, we&#8217;ll send a POST request to validate that there&#8217;s a real live callback URL waiting to receive the notifications.<\/p>\n<p>  <br>  <\/p>\n<pre><code>  POST https:\/\/&lt;YourAppURLHere&gt;\/api\/webhookCallback?validationtoken=&lt;token&gt;  <\/code>  <\/pre>\n<p>We expect the &lt;token&gt; value to be echoed back in the response as plain\/text within 10 seconds.<\/p>\n<p>  <br>  <\/p>\n<p>As ever, please let us know how you like Microsoft Graph and webhooks in particular.<\/p>\n<\/p><\/div>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Hi, Gareth Jones here.&nbsp; I recently joined the Microsoft Graph team from our friends over in OneNote. I&#8217;m beyond excited at the wonderful enthusiasm you&#8217;ve shown for the Microsoft Graph since we launched at Connect(); back in 2015 (wow, that sounds so retro now). One area we didn&#8217;t talk about too much at launch time [&hellip;]<\/p>\n","protected":false},"author":69076,"featured_media":25159,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3,128,11],"tags":[18,35,12],"class_list":["post-1011","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-graph","category-microsoft-teams","category-office-add-ins","tag-excel","tag-onedrive","tag-outlook"],"acf":[],"blog_post_summary":"<p>Hi, Gareth Jones here.&nbsp; I recently joined the Microsoft Graph team from our friends over in OneNote. I&#8217;m beyond excited at the wonderful enthusiasm you&#8217;ve shown for the Microsoft Graph since we launched at Connect(); back in 2015 (wow, that sounds so retro now). One area we didn&#8217;t talk about too much at launch time [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/1011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/users\/69076"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/comments?post=1011"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/1011\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media\/25159"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media?parent=1011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/categories?post=1011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/tags?post=1011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}