Excelgoodies logo +40 31 2299227

LEARN THIS HANDS ON

Power Apps & Power Automate

. Live Online FILLING FAST
View all upcoming batches
Building Robust Approval Workflows in Power Automate and SharePoint

Building Robust Approval Workflows in Power Automate and SharePoint

Power Automate + SharePoint is usually the first combo people try for approvals, but the default templates fall apart once you add real-world rules: rejections, delegations, escalations, and auditability. This guide walks through a complete pattern for end-to-end approval workflows with Power Automate and SharePoint, focusing on how to handle those edge cases cleanly.

If you want to turn this into a broader automation capability across your team, it’s worth investing in a structured path like a dedicated Power Automate skills program, but let’s get hands-on right now.


1. Scenario and Design Principles

We’ll use a simple but realistic scenario:

  • Requests are stored in a SharePoint list.
  • Each request needs manager approval.
  • If the manager doesn’t respond in 2 days, escalate to their manager.
  • Approvers can delegate to someone else.
  • Rejections should stop the process and log a clear reason.
  • Every decision must be traceable.

Design constraints:

  • No orphaned approvals (someone leaves the company, or is on holiday).
  • No silent timeouts (requests stuck in limbo).
  • Clear audit trail in SharePoint.

We’ll build this as a single main flow plus a small helper pattern for escalations.


2. SharePoint List Design for Approvals

Power Automate is only as robust as your data model. Before touching flows, fix the SharePoint list.

Recommended columns (beyond your business fields):

  • Title – Request title.
  • Requester (Person) – Who raised the request.
  • Approver (Person) – Primary approver.
  • Backup Approver (Person) – Used for escalation or manual fallback.
  • Approval Status (Choice)
    • Pending
    • Approved
    • Rejected
    • Escalated
    • Delegated
  • Approval Stage (Single line of text)
    • E.g. Manager, Finance, Director.
  • Approval Outcome (Single line of text)
    • E.g. Approved by Manager, Rejected by Finance, etc.
  • Approval Comments (Multiple lines of text)
    • Reason for decision.
  • Approval History (Multiple lines of text, append changes enabled)
    • Optional, for a human-readable log.
  • Due Date (Date) – For escalation logic.
  • Current Approver (Person) – The person currently expected to act.

This structure gives you enough metadata to:

  • Query pending approvals.
  • Drive escalations.
  • Report on bottlenecks.
  • Reconstruct what happened without digging into flow run history.

3. Core Flow: From Submission to Decision

3.1 Trigger and Initial Setup

Create a cloud flow with:

  • Trigger: When an item is created or modified (SharePoint)
    • Site Address: your site
    • List Name: your approvals list

Immediately after the trigger, add a Condition to protect against infinite loops:

  • If Approval Status is equal to Pending AND Current Approver is empty
    • Only then start a new approval

This ensures the flow only fires for fresh items or items that have been reset.

3.2 Setting Due Date and Current Approver

Add a Compose or Initialize variable for due date:

  • Type: String
  • Value:
    addDays(utcNow(), 2)
    

Then update the SharePoint item:

  • Approval Status = Pending
  • Current Approver = Approver column
  • Due Date = output of addDays(...)
  • Approval Stage = Manager (or your first stage)

3.3 Start and Wait for Approval

Add action: Start and wait for an approval

  • Approval type: Approve/Reject – First to respond
  • Title: Manager approval for @{triggerOutputs()?['body/Title']}
  • Assigned to: Approver (email from the SharePoint column)
  • Details: include a short summary and a link to the item

Use the Link to item from the trigger in the email body so approvers can open the request directly.

3.4 Handling Approval vs Rejection

After the approval action, add a Condition:

  • Left value: Outcome (from the approval action)
  • Operator: is equal to
  • Right value: Approve

In the If yes branch (approved):

  1. Update the SharePoint item:

    • Approval Status = Approved
    • Approval Outcome = Approved by @{outputs('Start_and_wait_for_an_approval')?['body/responder/email']}
    • Approval Comments = @{outputs('Start_and_wait_for_an_approval')?['body/comments']}
    • Current Approver = null (clear it)
  2. If you have another stage (e.g. Finance), this is where you:

    • Set Approval Stage = Finance
    • Set Current Approver = Finance approver
    • Call another approval action or another flow.

In the If no branch (rejected):

  • Update SharePoint item:

    • Approval Status = Rejected
    • Approval Outcome = Rejected by @{...}
    • Approval Comments = approver’s comments
    • Current Approver = null
  • Optionally send an email to the requester with:

    • Decision
    • Comments
    • Link to the item

At this point, basic approvals and rejections are covered. Now we extend for delegation and escalation.


4. Handling Delegations Cleanly

Delegation usually means: “I’m not the right person; assign this to someone else.” If you don’t design for it, users will forward emails and reply in Outlook, and your workflow will never know.

4.1 Delegation Pattern Choices

Two practical options:

  1. Delegation via SharePoint fields

    • Approver edits the SharePoint item and sets:
      • Current Approver = new person
      • Approval Status = Delegated
    • Flow detects this change and resends the approval.
  2. Delegation via Power Apps / custom form

    • Approver clicks a button “Delegate” in a Power Apps form.
    • The app updates Current Approver and flags a Delegation Requested field.

We’ll use the first option (simpler, no extra tools).

4.2 Flow Logic for Delegation

Extend your main flow:

  1. Add a Condition near the start:

    • If Approval Status is Delegated
  2. In this branch:

    • Update Approval Status back to Pending
    • Keep Current Approver as set by the user (delegated person)
    • Start a new Start and wait for an approval action, but now assign to Current Approver.
  3. For audit trail, append to Approval History:

    CONCATENATE(
        formatDateTime(utcNow(), 'yyyy-MM-dd HH:mm'),
        ' | Delegated to ',
        string(outputs('Current_Approver_DisplayName'))
    )
    

    (This is pseudocode; in practice you’ll build this using a Compose and then write to the field.)

Key rule: never reuse the original approval after delegation. Always start a fresh approval action for the new person.


5. Building Time-Based Escalations

Escalations are about time: if no decision by a deadline, move it up.

We’ll implement this with a separate scheduled flow to avoid complex delay branches in the main flow.

5.1 Scheduled Escalation Flow

Create a new scheduled cloud flow:

  • Trigger: Recurrence
    • Every 1 hour (or whatever is acceptable)

Add Get items (SharePoint):

  • Filter Query:
    ApprovalStatus eq 'Pending' and DueDate lt '@{utcNow()}'
    

(Adjust field names to your internal names, e.g. ApprovalStatus might be Approval_x0020_Status.)

5.2 Determining Escalation Target

For each item (use Apply to each):

  1. Decide who to escalate to. Options:

    • Use Backup Approver column.
    • Use a lookup table (another list) mapping approvers to their managers.
  2. If Backup Approver is not empty:

    • Set Current Approver = Backup Approver.
    • Set Approval Status = Escalated.
  3. If no Backup Approver is set:

    • Optionally send an alert to an admin group.
    • Or leave it for manual intervention.

5.3 Starting the Escalated Approval

After setting the new approver, call the same Start and wait for an approval pattern:

  • Title: Escalated approval for @{Title}
  • Assigned to: Current Approver

Update the Due Date again using:

addDays(utcNow(), 2)

This gives the escalated approver their own SLA window.

5.4 Avoiding Double Approvals

Because we’re using a separate flow, we must ensure we don’t start multiple approvals for the same item.

Tactics:

  • Check if there is an active approval before starting a new one:
    • Use a custom Approval Token field (GUID) and only escalate if it’s empty.
    • Or ensure that the main flow clears Current Approver and Due Date as soon as a decision is made.

A simple, robust rule:

  • Escalation flow only acts on items where Current Approver is not empty and Approval Status is Pending.

6. Audit Trail and Reporting

Approvals without reporting are painful to manage. With the fields we defined earlier, you can build simple Power BI reports on top of the SharePoint list.

Key columns to track:

  • Approval Status
  • Approval Stage
  • Current Approver
  • Modified (built-in, for last change)
  • Created (built-in)

6.1 Basic Metrics

You can easily derive:

  • Average time to approve per stage.
  • Number of escalations per approver.
  • Rejection rate per department.

If you use Power BI, a simple measure for approval time might look like:

Approval Duration (hours) = 
VAR CreatedDate = MIN('Approvals'[Created])
VAR ApprovedDate = MIN('Approvals'[ApprovedDate])
RETURN
    IF(
        NOT ISBLANK(ApprovedDate),
        DATEDIFF(CreatedDate, ApprovedDate, HOUR)
    )

You’d populate ApprovedDate via Power Automate when an item is approved.

6.2 Logging Decisions

For a more narrative audit trail, you can append logs into Approval History.

Example text pattern:

2024-09-15 10:23 | Manager (john.doe@contoso.com) approved | Comment: OK to proceed
2024-09-16 09:05 | Escalated to jane.smith@contoso.com (no response in 2 days)

You build this with:

  1. A Compose action that formats the line.
  2. A Get item to read current Approval History.
  3. An Update item that concatenates existing + new line.

7. Common Pitfalls and How to Avoid Them

7.1 Infinite Loops on Item Update

Problem:

  • Flow triggers on update, then updates the item, which retriggers the flow.

Mitigation:

  • Use conditions at the top:
    • Only proceed if Approval Status is Pending and Current Approver is empty.
  • Or add a Flow State field and only act when it’s Ready.

7.2 Stuck Items After Rejection

Problem:

  • Users expect to resubmit after rejection, but fields stay locked.

Mitigation:

  • On rejection, explicitly:
    • Clear Current Approver.
    • Set Approval Stage back to initial when user edits and resubmits.
  • Optionally add a Resubmit flag the user can set to restart the flow.

7.3 Delegation Without Audit

Problem:

  • Delegations happen via email forwards, and you lose traceability.

Mitigation:

  • Enforce delegation via Current Approver field.
  • Educate users to change Current Approver instead of forwarding.
  • Log every change to Current Approver in Approval History.

8. One Practical Takeaway

Don’t start with templates. Design your SharePoint list first, with explicit fields for Current Approver, Approval Status, Due Date, and Approval Stage, then build your Power Automate flows around those fields. Once you’ve modeled rejections, delegations, and escalations in the data, the flow logic becomes straightforward—and far easier to maintain when your process changes.

Power Automate

New

Next Batches Now Live

Power BIPower BI
SQLSQL
Power AppsPower Apps
Power AutomatePower Automate
Microsoft FabricMicrosoft Fabrics
AzureAzure Data Engineering
Explore Dates & Reserve Your Spot → Reserve Your Spot →