Building a “Comments Created Today” Digest for SharePoint Online with Power Automate (REST) — Including Clickable Item Links

This article documents a mature, production-ready pattern to collect SharePoint item comments created today, format them into a clean HTML email, and ensure the item links are truly clickable—even when you start from Create HTML table.

Privacy note (for public blogs): Replace any real tenant/site/list names with neutral placeholders, e.g.
https://contoso.sharepoint.com/sites/ExampleSite and Example List.


Why this pattern is needed

SharePoint exposes comments through REST under a specific list item:

  • .../items(<ID>)/comments

In practice, you iterate items, fetch comments per item, then filter comments by date. You can use normal OData $filter for list items (e.g., to reduce the number of items you scan), but comments themselves aren’t typically queried as a global list-like entity in a single OData query. For list item REST patterns and OData query operations, see Microsoft Learn. (Microsoft Learn)


Target outcome

Send an email containing a table with:

  • Comment Created Date
  • Comment Text
  • Author
  • Item Title / ID
  • Clickable “Open item” link

Architecture overview

Flow outline

  1. Get candidate items from your list (optionally pre-filtered).
  2. Apply to each item
    • Call REST: .../items(ID)/comments
    • Parse JSON
    • Append comment objects to an array
  3. Filter array to “created today”
  4. Create HTML table
  5. Compose to “unescape” anchors so the link becomes clickable
  6. Send email (V2) with HTML enabled

Step 1 — Get candidate items (reduce scanning)

If you already have your list of candidate items, skip this. Otherwise, use SharePoint REST list item querying with $select/$filter to reduce the number of items you loop through. Microsoft Learn covers list item REST operations and OData query capabilities. (Microsoft Learn)

Example REST (illustrative):

GET _api/web/lists/getbytitle('Example List')/items?$select=Id,Title,Modified&$filter=Modified ge datetime'2026-02-11T00:00:00Z'

Note: Whether “adding a comment” updates Modified can vary by scenario; if it doesn’t help, filter candidates using your own business rules (Status, last X days, etc.).


Step 2 — Get comments for each item (REST)

Inside your Apply to each (item) loop, call:

GET _api/web/lists/getbytitle('Example List')/items(@{items('Apply_to_each')?['ID']})/comments
Accept: application/json;odata=verbose

You already have this working—great.


Step 3 — Parse JSON and build a “rich” array (comment + item metadata)

Create an Array variable:

  • commentsToEmail (Array)

Then, inside the Apply to each (comment results), append objects (not just dates). Example:

Recommended object shape

  • createdDate
  • text
  • authorName
  • authorEmail
  • itemId
  • itemTitle
  • itemLinkHtml (this will be your <a> tag)

Item link (DispForm pattern)

concat(
'https://contoso.sharepoint.com/sites/ExampleSite/Lists/ExampleList/DispForm.aspx?ID=',
string(items('Apply_to_each')?['ID'])
)

Clickable anchor stored as a string

concat(
'<a href="',
<the link above>,
'">Open item</a>'
)

If your comment JSON fields differ (some tenants return text, some use another property), use the run-history sample to map fields correctly.


Step 4 — Filter comments created “today”

Use a Filter array on commentsToEmail.

If you treat “today” as UTC (simple + stable)

@greaterOrEquals(item()?['createdDate'], startOfDay(utcNow()))

For guidance on using expressions in conditions (Power Automate), see Microsoft Learn. (Microsoft Learn)

If you need “today” in a local timezone, you can apply timezone conversion logic. Be careful: startOfDay(utcNow()) is UTC day boundary (common gotcha). (This is a known behavior frequently discussed in the Power Platform community.) (Microsoft Power Platform Community)


Step 5 — Create HTML table (keep your current approach)

Now run Create HTML table using the filtered array.

At this stage, formatting is good—but the link often isn’t clickable because Create HTML table HTML-encodes content inside cells.

You asked specifically to reuse the HTML table you already built. Good—keep it.


Step 6 — Make links clickable (without rebuilding the table)

This is the key “maturity step” you reached:

  1. Store the link as an <a href="...">Open item</a> string in your array object (itemLinkHtml)
  2. After Create HTML table, use Compose to “unescape” only the anchor tags.

Compose expression (anchor-only unescape)

replace(
replace(
replace(
body('Create_HTML_table'),
'&lt;a href=&quot;',
'<a href="'
),
'&quot;&gt;',
'">'
),
'&lt;/a&gt;',
'</a>'
)

This converts escaped anchor markup back into real HTML anchors while leaving the rest of the table intact.


Step 7 — Send the email as HTML

Use Office 365 Outlook → Send an email (V2):

  • Body: the output of the Compose step (unescaped anchors)
  • Is HTML: Yes

Microsoft’s connector documentation includes notes about how Outlook/connector actions treat HTML. (Microsoft Learn)

Tip: Avoid “Send email with options” for this scenario unless you understand its HTML limitations (action cards can behave differently). (Microsoft Learn)


Formatting tips (without breaking Outlook)

Email clients—especially Outlook desktop—can be strict. If you want nicer formatting:

Wrap the table in a styled container

concat(
'<div style="font-family:Segoe UI, Arial; font-size:13px; color:#222;">',
'<h3 style="margin:0 0 10px 0;">Comments created today</h3>',
'<div style="border:1px solid #e1e1e1; border-radius:8px; overflow:hidden;">',
outputs('Compose_UnescapeAnchors'),
'</div>',
'<p style="margin-top:10px;color:#666;">Generated: ',
formatDateTime(utcNow(),'yyyy-MM-dd HH:mm'),
' UTC</p>',
'</div>'
)

Operational hardening (recommended next steps)

1) De-duplicate notifications

If the flow runs multiple times a day, store a “last processed comment timestamp/id” in a separate list (a “state list”). Then only email new comments since the last run.

2) Scope candidate items

To reduce calls, filter items first using business logic (Status, active projects, last N days, etc.). Microsoft Learn shows how to use $select/$filter efficiently on list items. (Microsoft Learn)

3) Error handling

Wrap REST + Parse JSON in a scope with failure handling so one problematic item doesn’t break the entire digest.


Final summary tables

Steps summary

StepActionOutput
1Get candidate items (optional $filter)Smaller item set to scan
2REST: items(ID)/commentsComments per item
3Parse JSONresults array
4Append object to arrayComment + item + link HTML
5Filter array (today)Only today’s comments
6Create HTML tableEmail-ready table
7Compose replace()Clickable <a> restored
8Send email (HTML)Final digest delivered

Technical reference

NeedExpression / Reference
SharePoint list REST basicsMicrosoft Learn: working with lists/items (Microsoft Learn)
OData $select/$filter patternsMicrosoft Learn: OData query operations (Microsoft Learn)
Compare dates in conditionsMicrosoft Learn: expressions in conditions (Microsoft Learn)
HTML handling considerationsMicrosoft connector notes (Outlook) (Microsoft Learn)
UTC day boundary gotchaCommunity explanation (timezone behavior) (Microsoft Power Platform Community)

Edvaldo Guimrães Filho Avatar

Published by