SharePoint, Outlook, Teams, and Approvals connector action patterns.
All examples assume "runAfter" is set appropriately.
Replace with the you used in
(e.g. , ). This is NOT the connection
GUID — it is the logical reference name that links the action to its entry in
the map.
Note the single-quotes inside double-quotes — correct OData string literal
syntax. Avoids a separate variable action.
Pagination for large lists: by default, GetItems stops at $top. To auto-paginate
beyond that, enable the pagination policy on the action. In the flow definition this
appears as:
json
"paginationPolicy": { "minimumItemCount": 10000 }
Set minimumItemCount to the maximum number of items you expect. The connector will
keep fetching pages until that count is reached or the list is exhausted. Without this,
flows silently return a capped result on lists with >5,000 items.
Result reference: @body('Get_SP_Item')?['FieldName']
Use GetItem (not GetItems with a filter) when you already have the ID.
Re-fetching after a trigger gives you the current row state, not the
snapshot captured at trigger time — important if another process may have
modified the item since the flow started.
PatchItem can validate required SharePoint columns even when you are not
changing those fields. Echo unchanged required fields from the trigger or a
prior Get Item action, for example item/Title, and use internal field names.
SharePoint’s CreateFile fails if the file already exists. To upsert (create or overwrite)
without a prior existence check, use GetFileMetadataByPath on both Succeeded and Failed
from CreateFile — if create failed because the file exists, the metadata call still
returns its ID, which UpdateFile can then overwrite:
If Create_File succeeds, Get_File_Metadata_By_Path is Skipped and Update_File
still fires (accepting Skipped), harmlessly overwriting the file just created.
If Create_File fails (file exists), the metadata call retrieves the existing file’s ID
and Update_File overwrites it. Either way you end with the latest content.
Document library system properties — when iterating a file library result (e.g.
from ListFolder or GetFilesV2), use curly-brace property names to access
SharePoint’s built-in file metadata. These are different from list field names:
@item()?['{Name}'] — filename without path (e.g. "report.csv")@item()?['{FilenameWithExtension}'] — same as {Name} in most connectors@item()?['{Identifier}'] — internal file ID for use in UpdateFile/DeleteFile@item()?['{FullPath}'] — full server-relative path@item()?['{IsFolder}'] — boolean, true for folder entries
When a SharePoint “item modified” trigger fires, it doesn’t tell you WHICH
column changed. Use GetItemChanges to get per-column change flags, then gate
downstream logic on specific columns:
New-item detection: On the very first modification (version 1.0),
GetItemChanges may report no prior version. Check
@equals(triggerBody()?['OData__UIVersionString'], '1.0') to detect
newly created items and skip change-gate logic for those.
For cross-list updates or advanced operations not supported by the standard
Update Item connector (e.g., updating a list in a different site), use the
SharePoint REST API via the HttpRequest operation:
X-HTTP-Method: MERGE — tells SharePoint to do a partial update (PATCH semantics)
IF-MATCH: * — overwrites regardless of current ETag (no conflict check)
The HttpRequest operation reuses the existing SharePoint connection — no extra
authentication needed. Use this when the standard Update Item connector can’t
reach the target list (different site collection, or you need raw REST control).
Keep the connector-specific parameter names exactly as shown:
parameters/method, parameters/uri, parameters/headers, and
parameters/body. The body is a JSON string, and parameters/uri is relative
to the SharePoint dataset.
Use a SharePoint document library JSON file as a queryable “database” of
last-known-state records. A separate process (e.g., Power BI dataflow) maintains
the file; the flow downloads and filters it for before/after comparisons.
Decode chain:GetFileContent returns base64-encoded content in
body(...)?['$content']. Apply decodeBase64() then json() to get a
usable array. Filter Array then acts as a WHERE clause.
When to use: When you need a lightweight “before” snapshot to detect field
changes from a webhook payload (the “after” state). Simpler than maintaining
a full SharePoint list mirror — works well for up to ~10K records.
File path encoding: In the id parameter, SharePoint URL-encodes paths
twice. Spaces become %2b (plus sign), slashes become %252f.
Office Script actions require real workbook and script identifiers at save time.
Do not deploy placeholder scriptId values; update_live_flow can fail during
dynamic operation validation even before a test run exists.
Use describe_live_connector or get_live_dynamic_options when available, or
ask the user for the workbook and script if they are not discoverable. If a real
scriptId still cannot be resolved, ask the user to add the Run script action
once in the designer, then read the flow definition and preserve the resolved
parameters.
Outlook-as-CMS pattern: store a template email in a dedicated Outlook folder.
Set fetchOnlyUnread: false so the template persists after first use.
Non-technical users can update subject and body by editing that email —
no flow changes required. Pass subject and body directly into SendEmailV2.
To get a folder ID: in Outlook on the web, right-click the folder → open in
new tab — the folder GUID is in the URL. Prefix it with Id:: in folderPath.
For 1:1 (“Chat with Flow bot”), use "location": "Chat with Flow bot" and set
body/recipient to the user’s email address.
Active-user gate: When sending notifications in a loop, check the recipient’s
Azure AD account is enabled before posting — avoids failed deliveries to departed
staff:
When using the Copilot Studio connector, publish the agent before running the
flow. Draft/test agents can exist in the studio canvas but still be unavailable
or stale through the flow connector endpoint.
If a connector action fails with an unavailable-agent or endpoint-style error,
publish the agent, wait briefly for propagation, then resubmit the same flow run
before changing the flow definition.
The standard “Start and wait for an approval” is a single blocking action.
For more control (e.g., posting the approval link in Teams, or adding a timeout
scope), split it into two actions: CreateAnApproval (fire-and-forget) then
WaitForAnApproval (webhook pause).
"Approve/Reject - First to respond" — binary, first responder wins
"Approve/Reject - Everyone must approve" — requires all assignees
"CustomResponse/Result" — define your own response buttons
After Wait_For_Approval, read the outcome:
@body('Wait_For_Approval')?['outcome'] → "Approve", "Reject", or custom@body('Wait_For_Approval')?['responses'][0]?['responder']?['displayName']@body('Wait_For_Approval')?['responses'][0]?['comments']
The split pattern lets you insert actions between create and wait — e.g.,
posting the approval link to Teams, starting a timeout scope, or logging
the pending approval to a tracking list.