{"id":579,"date":"2025-01-30T17:05:40","date_gmt":"2025-01-30T16:05:40","guid":{"rendered":"https:\/\/niklas-boesch.de\/?p=579"},"modified":"2025-01-30T17:05:41","modified_gmt":"2025-01-30T16:05:41","slug":"syncing-outlook-messages-beware-of-this-delta-link-issue-in-power-automate","status":"publish","type":"post","link":"https:\/\/niklas-boesch.de\/en\/2025\/01\/syncing-outlook-messages-beware-of-this-delta-link-issue-in-power-automate","title":{"rendered":"Syncing Outlook Messages? Beware of This Delta Link Issue in Power Automate"},"content":{"rendered":"<p>When you want to sync anything accessible via Graph API, delta queries can be a great tool. Instead of relying on individual triggers (&#8222;Each time a message arrives&#8220;) or a time-based filter (&#8222;Return all messages received in the last 24 hours&#8220;), you can just call a delta link that returns both the data you&#8217;re asking for and a new delta link for the next time you want to sync. This ensures you get all new items that have been created in the meantime, whether you call the link 5 minutes or 5 days later.<\/p>\n\n\n\n<p>So when I recently had the requirement to sync Outlook mail attachments from emails in a specific folder to SharePoint, delta links called via a Power Automate Flow with a time-based repeating trigger seemed like a great idea. Using delta links saved me from having to compare individual IDs as a filter or using a time-based filter, which may run into issues if your flow is ever turned off or the connection breaks. There&#8217;s even a &#8222;Send an HTTP request&#8220; action in the Office 365 Outlook connector, meaning there&#8217;s no need to mess around with the &#8222;HTTP with Microsoft Entra ID (preauthorized)&#8220; connector, which is a bit more complicated to set up. Easy!<\/p>\n\n\n\n<p>Or so I thought.<\/p>\n\n\n\n<p><strong>When delta links get weird<\/strong><\/p>\n\n\n\n<p>The first call works exactly as expected:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"639\" height=\"302\" src=\"https:\/\/niklas-boesch.de\/wp-content\/uploads\/2025\/01\/image.png\" alt=\"\" class=\"wp-image-581\" srcset=\"https:\/\/niklas-boesch.de\/wp-content\/uploads\/2025\/01\/image.png 639w, https:\/\/niklas-boesch.de\/wp-content\/uploads\/2025\/01\/image-300x142.png 300w, https:\/\/niklas-boesch.de\/wp-content\/uploads\/2025\/01\/image-18x9.png 18w\" sizes=\"auto, (max-width: 639px) 100vw, 639px\" \/><\/figure>\n\n\n\n<p>You get your messages and a delta link for the next sync<sup data-fn=\"55a03d6a-12f8-4004-9790-ac36a723c679\" class=\"fn\"><a href=\"#55a03d6a-12f8-4004-9790-ac36a723c679\" id=\"55a03d6a-12f8-4004-9790-ac36a723c679-link\">1<\/a><\/sup>. But when you actually try to use that delta link in Power Automate, things start to fall apart.<\/p>\n\n\n\n<p>Instead of a nice, clean URL, the @odata.deltaLink returned by Graph looks something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:\/\/graph.microsoft.com\/v1.0\/me\/mailFolders<strong>('AAMkAGNjMj...')<\/strong>\/messages\/delta?$deltatoken=...<\/code><\/pre>\n\n\n\n<p>The folder ID is suddenly wrapped in parentheses and single quotes.  Power Automate refuses to accept it when you try to use this link, returning this error:<\/p>\n\n\n\n<div style=\"    background-color: #ffebeb;    color: #d32f2f;    border-left: 4px solid #d32f2f;    padding: 12px;    font-family: 'Courier New', Courier, monospace;    font-size: 14px;    white-space: pre-wrap;\">URI path is not a valid Graph endpoint, path is neither absolute nor relative or resource\/object is not supported for this connector.\n<\/div>\n\n\n\n\n<p>Funny (and exasperating) thing: the link works in the Graph API Explorer without any issues.<\/p>\n\n\n\n<p><strong>Fixing the delta link mess<\/strong><\/p>\n\n\n\n<p>Turns out, Power Automate expects the URL in the same format as the original request:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:\/\/graph.microsoft.com\/v1.0\/me\/mailFolders<strong>\/folderId\/messages\/delta?$deltatoken=...<\/strong><\/code><\/pre>\n\n\n\n<p>No parentheses, no single quotes. Just the folder ID and the delta token.<\/p>\n\n\n\n<p>The fix? Instead of saving the delta link in full for the next call (I saved it in a hidden Sharepoint column), get the query part of the returned URL which includes the delta token. You can easily do it with this expression in a Compose action:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>uriQuery(body('Send_first_Delta_request')?&#91;'@odata.deltaLink'])<\/code><\/pre>\n\n\n\n<p>This returns something like <code>\"?$deltatoken=LztZwWjo5Iiv...\"<\/code>, which you can simply append to the URL you  successfully used for your first request. <\/p>\n\n\n\n<p><strong>Final thoughts<\/strong><\/p>\n\n\n\n<p>This was a weird one. I&#8217;m not sure what is going on behind the scenes here to make it work in Graph Explorer (and my browser) and messed around quite a bit with different links, encodings and so on. The solution I provided here should still keep working if Microsoft ever changes the return format to the one we actually need, so that&#8217;s a plus \ud83d\ude42<\/p>\n\n\n<ol class=\"wp-block-footnotes\"><li id=\"55a03d6a-12f8-4004-9790-ac36a723c679\">It may also be a nextLink, if there have been more changes than can be returned in one call. Just wrap the action in a &#8222;Do Until&#8220; loop and call nextLinks until the call returns a deltaLink. <a href=\"#55a03d6a-12f8-4004-9790-ac36a723c679-link\" aria-label=\"Jump to footnote reference 1\">\u21a9\ufe0e<\/a><\/li><\/ol>","protected":false},"excerpt":{"rendered":"<p>When you want to sync anything accessible via Graph API, delta queries can be a great tool. Instead of relying on individual triggers (&#8222;Each time a message arrives&#8220;) or a time-based filter (&#8222;Return all messages received in the last 24 hours&#8220;), you can just call a delta link that returns both the data you&#8217;re asking&hellip;&nbsp;<a href=\"https:\/\/niklas-boesch.de\/en\/2025\/01\/syncing-outlook-messages-beware-of-this-delta-link-issue-in-power-automate\" rel=\"bookmark\">Read More &raquo;<span class=\"screen-reader-text\">Syncing Outlook Messages? Beware of This Delta Link Issue in Power Automate<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":584,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","_themeisle_gutenberg_block_has_review":false,"footnotes":"[{\"content\":\"It may also be a nextLink, if there have been more changes than can be returned in one call. Just wrap the action in a \\\"Do Until\\\" loop and call nextLinks until the call returns a deltaLink.\",\"id\":\"55a03d6a-12f8-4004-9790-ac36a723c679\"}]"},"categories":[17,38,6,16],"tags":[29,21,36,8],"class_list":["post-579","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-integration","category-outlook","category-power-automate","category-sharepoint","tag-exchange","tag-integration","tag-low-code","tag-power-automate"],"featured_image_src":"https:\/\/niklas-boesch.de\/wp-content\/uploads\/2025\/01\/Title-Image.png","author_info":{"display_name":"Niklas B\u00f6sch","author_link":"https:\/\/niklas-boesch.de\/en\/author\/niklasboesch"},"_links":{"self":[{"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/posts\/579","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/comments?post=579"}],"version-history":[{"count":3,"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/posts\/579\/revisions"}],"predecessor-version":[{"id":583,"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/posts\/579\/revisions\/583"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/media\/584"}],"wp:attachment":[{"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/media?parent=579"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/categories?post=579"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/niklas-boesch.de\/en\/wp-json\/wp\/v2\/tags?post=579"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}