Queue-Based Document Approval Pipeline
When a document needs approval, queue it in Azure Queues, then process sequentially through a multi-stage approval chain.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
A SharePoint-triggered, multi-stage document approval flow that uses Azure Queues as a handoff bus between approval stages. Every transition (initial submission, Stage 1 outcome, Stage 2 outcome) writes a structured JSON message to the Azure Queue so downstream observers, audit pipelines, or other Power Automate flows can subscribe to lifecycle events without coupling to the SharePoint list directly. Stage 1 (Manager) and Stage 2 (Director) approvals are blocking via the Approvals connector, and the SharePoint item is patched with the final disposition (Fully Approved, Rejected at Stage 1, or Rejected at Stage 2).
Use Case
Use this pattern when document approvals need multi-stage gating with auditable handoff events and loose coupling between the orchestrator and downstream systems. Typical real-world fits: contract approvals, capital expenditure requests, change management for security policies, compliance attestations, and any two-tier sign-off flow where the trail of state transitions is itself a deliverable.
The flow is ideal for teams that:
- Sequential multi-stage gating (Manager → Director) where Stage 2 only fires if Stage 1 approves
- Auditable, replayable handoff events captured outside the primary record (Azure Queue lets a separate flow drain handoff messages into Dataverse, Splunk, an Event Hub, or a data warehouse)
- Loose coupling between the approval orchestrator and downstream systems — they consume the queue, not the SharePoint list
- Disposition writeback to the originating list so requestors and dashboards can read the final status without polling Approvals
Flow Architecture
When_Document_Approval_Item_Is_Created
SharePoint - When an item is created (GetOnNewItems)Polling trigger (every 5 minutes) on the SharePoint list named in flowlibs_DocApprovalPipelineListName. Fires when a new item is added.
Init_varDocumentTitle
Initialize variableString variable seeded from triggerOutputs()?['body/Title'].
Init_varDocumentLink
Initialize variableString variable, coalesces body/DocumentLink to empty string.
Init_varRequestor
Initialize variableString variable, coalesces body/Author/Email to empty string.
Init_varListItemId
Initialize variableString variable, cast from triggerOutputs()?['body/ID'] via string().
Init_varFinalStatus
Initialize variableString variable, seeded with literal 'Submitted'.
Compose_Initial_Queue_Message
ComposeBuilds a JSON object: {stage, docTitle, docLink, requestor, listItemId, submittedAt} representing the initial submission event.
Put_Initial_Request_To_Queue
Azure Queues - Put message (PutMessage_V2)Writes the initial submission message to the queue named in flowlibs_ApprovalPipelineQueueName.
Stage1_Manager_Approval
Approvals - Start and wait for an approvalApprove/Reject approval with the WebhookApprovalCreationInput as a nested body object. Assigned to flowlibs_ApprovalStage1Approver. Blocks until the Manager responds.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_SharePointSiteURL | String | https://your-tenant.sharepoint.com | SharePoint site hosting the approval list. |
| flowlibs_DocApprovalPipelineListName | String | FlowLibs - Document Approval Queue | List name where new items trigger the flow. |
| flowlibs_AzureQueueStorageAccountName | String | <configure> | Storage account hosting the handoff queue (e.g., your Azure Storage account name). |
| flowlibs_ApprovalPipelineQueueName | String | approval-pipeline | Queue name for the three handoff messages. |
| flowlibs_ApprovalStage1Approver | String | <configure> | Stage 1 (Manager) approver UPN — set to the manager's email/UPN in your tenant. |
| flowlibs_ApprovalStage2Approver | String | <configure> | Stage 2 (Director) approver UPN — set to the director's email/UPN in your tenant. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| SharePoint | shared_sharepointonline | GetOnNewItems (trigger) PatchItem |
| Azure Queues | shared_azurequeues | PutMessage_V2 |
| Approvals | shared_approvals | StartAndWaitForAnApproval |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Add more approval stages
- Duplicate the Stage2_Director_Approval + Compose_Stage*_Result_Message + Put_Stage*_Result_To_Queue triplet inside the If_Stage2_Approved Yes branch and shift the SharePoint update further down the chain. Each new stage gets its own env var for the approver email and a corresponding Status literal in the PatchItem.
- Change the queue cadence or go event-driven
- To make the trigger more responsive, shorten the recurrence.interval on When_Document_Approval_Item_Is_Created (minimum 1 minute). For an event-driven model, replace the SharePoint trigger with shared_azurequeues/OnNewMessageInQueue and read the document metadata from the message body itself.
- Route by document category
- Add a Switch action after Init_varListItemId that branches on a SharePoint column (e.g., Category) and points each case at a different flowlibs_ApprovalStage1Approver* env var. The queue messages can carry the category for downstream consumers to filter.
- Replace Approvals with Adaptive Cards
- Swap each StartAndWaitForAnApproval action for shared_teams/PostAdaptiveCardAndWaitForAResponse. The outcome field changes from body/outcome to a custom card response field, and the If expressions need to compare against the card's submit value. The queue handoff pattern stays identical.
- Add a queue drainer flow
- Build a separate FlowLibs flow with shared_azurequeues/OnNewMessageInQueue trigger pointing at the same queue. Parse the JSON body and route to Dataverse CreateRecord, Splunk HEC, or Event Hubs based on the stage field (submitted, stage1-result, stage2-result). Canonical way to extend the pipeline without modifying the orchestrator.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Cast SP item ID to string
Cast SharePoint integer ID to string for the queue message body.
EXPR.02Default requestor to empty
Default to empty string if SharePoint didn't return a requestor email.
EXPR.03Build queue message as typed JSON
Build a queue message as a typed JSON object — json() validates the structure before it lands in the queue.
EXPR.04Re-stringify Compose output for queue payload
PutMessage_V2 takes a string for its message body parameter — re-stringify the JSON output of the Compose action.
EXPR.05Read approval outcome
Read the approval outcome from the Stage 1 action; compare against literal 'Approve' for the Approve/Reject approval type.
EXPR.06Pass SP item ID into PatchItem path
Pass the original SharePoint item ID into PatchItem's path parameter for writeback of final disposition.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.