Assigning Microsoft Flow approvals to SharePoint Groups

One of the still missing (at time of writing!) features in Flow is the ability to assign approvals to a SharePoint group. This is a common scenario if you’re coming from a SharePoint background, or are working with a business process setup around a SharePoint site with lists and so on. This post will explain how to retrieve members from a SharePoint group and assign them to an approval task in Flow.

Some more background

In traditional SharePoint workflows (on-prem, hybrid or in the cloud), workflow tasks are often assigned to SharePoint groups. This means we can avoid hard coding individuals into the process and make things easier to manage when people come and go from the company.

Currently, Flow doesn’t let you assign directly to anything other than a named email. However, we do have the ability to assign the approval action to a string variable… so all we need is a list of approver emails in a variable. I also want the users to come from one of my SharePoint groups. Should be easy right? Kind of!

The SharePoint REST API provides a nice endpoint to retrieve the users from within a specific group. This endpoint is available at /_api/web/sitegroups/getbyname(‘Group display name’)/users

So, to get those users within a Flow, we need to hit that endpoint. Historically it used to be quite tricky to make SharePoint REST API calls in Flow. To call back to SharePoint using the HTTP request action, a lot of extra leg work was needed to get proper access – registering an app in Azure, granting permissions to your tenancy… thankfully, we no longer need to do this with the ‘Send an HTTP request to SharePoint’ action. You don’t need to do any app registrations or even pass form digests when doing POST requests.

Enough background info, here’s how to do it!

How to do it

Step 1 – Have your SharePoint site ready. Create a list of the items you want to request approval for. You’ll also need the name of the SharePoint group in the site that you wish to use for assigning the approval task(s)

Step 2 – Create your Flow from blank (go to flow.microsoft.com in your desired tenancy, then go to My Flows then ‘Create from blank’)

Step 3 – For the trigger, I’ve gone with ‘SharePoint – for a selected item’ as my Flow will be triggered via the item context menu in my SharePoint list. You could also go for ‘SharePoint – when an item is created’ or the most appropriate trigger, depending on your approval process. If choosing ‘for a selected item’, don’t forget to configure any additional users for the Flow and consider the connection credentials. Make sure you select your list. E.g.:

Process Screenshot 1

Step 4 – Add a ‘Send an HTTP request to SharePoint’ action and configure like this to query the SharePoint API for your specified group’s users (NB if you’re making use of run-only users in Flow and using those user’s credentials, I think this may mean the running user needs access to view the members in the SharePoint group chosen or this might fail. For Flows running on creation/modified you’re fine, assuming the Flow is created with an account with access to your SharePoint groups):

Process Screenshot 2

Step 5 – Now, we need a string variable for where we will store our approver email addresses. Add a ‘Variables – Initialize variable’ action and configure like this:

Process Screenshot 3

Step 6 – Now we need to do the fun bit, which is parsing the response from the SharePoint REST API call. To do this, add a ‘Data Operations – Parse JSON’ action. The ‘Content’ is the ‘Body’ from the ‘Send an HTTP request to SharePoint’ action earlier:

Process Screenshot 4

Now for the fun bit! We need to tell Flow what schema the response is, so that we can use the SharePoint group response data properly within our Flow (and actually read the email address(es) from the response). Without doing this, we’ve just got a bunch of text and Flow can’t read specific values. To do this, we can provide an example response from the API call by clicking the ‘Use sample payload to generate schema’ link at the bottom.

Within this popup, you can paste in an example JSON response from SharePoint when you hit the endpoint at /_api/web/sitegroups/getbyname(‘Group display name’)/users. An entire example response can be pasted in, exactly as it gets returned with all the users and other values inside it. Flow is very clever and just strips out all the values themselves and leaves the schema! You can use this approach for any SharePoint REST API call. You can get one of these responses by submitting the SharePoint REST API call by using common tools such as Postman.

To save time here though, here’s the full schema you need for this scenario. Just paste this directly into the ‘schema’ section in the action and ignore the ‘Use sample payload…’ link.


{
    "type": "object",
    "properties": {
        "d": {
            "type": "object",
            "properties": {
                "results": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "__metadata": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string"
                                    },
                                    "uri": {
                                        "type": "string"
                                    },
                                    "type": {
                                        "type": "string"
                                    }
                                }
                            },
                            "Alerts": {
                                "type": "object",
                                "properties": {
                                    "__deferred": {
                                        "type": "object",
                                        "properties": {
                                            "uri": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                }
                            },
                            "Groups": {
                                "type": "object",
                                "properties": {
                                    "__deferred": {
                                        "type": "object",
                                        "properties": {
                                            "uri": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                }
                            },
                            "Id": {
                                "type": "integer"
                            },
                            "IsHiddenInUI": {
                                "type": "boolean"
                            },
                            "LoginName": {
                                "type": "string"
                            },
                            "Title": {
                                "type": "string"
                            },
                            "PrincipalType": {
                                "type": "integer"
                            },
                            "Email": {
                                "type": "string"
                            },
                            "IsEmailAuthenticationGuestUser": {
                                "type": "boolean"
                            },
                            "IsShareByEmailGuestUser": {
                                "type": "boolean"
                            },
                            "IsSiteAdmin": {
                                "type": "boolean"
                            },
                            "UserId": {
                                "type": "object",
                                "properties": {
                                    "__metadata": {
                                        "type": "object",
                                        "properties": {
                                            "type": {
                                                "type": "string"
                                            }
                                        }
                                    },
                                    "NameId": {
                                        "type": "string"
                                    },
                                    "NameIdIssuer": {
                                        "type": "string"
                                    }
                                }
                            }
                        },
                        "required": [
                            "__metadata",
                            "Alerts",
                            "Groups",
                            "Id",
                            "IsHiddenInUI",
                            "LoginName",
                            "Title",
                            "PrincipalType",
                            "Email",
                            "IsEmailAuthenticationGuestUser",
                            "IsShareByEmailGuestUser",
                            "IsSiteAdmin",
                            "UserId"
                        ]
                    }
                }
            }
        }
    }
}

The completed action should look something like this:

Process Screenshot 5

Step 7 – Now we’ve got the data in a format Flow can work with, we can loop through our users and append them into a semi-colon separated string of email addresses. To loop the results, click ‘New step’ then go to ‘More’ and choose ‘Add an apply to each’:

Process Screenshot 6

Step 8 – Add the ‘results’ from the previous ‘Parse JSON’ action to the apply to each action:

Process Screenshot 7

Step 9 – Within the ‘Apply to each’ action, click ‘Add an action’ and add a ‘Variables – Append to string variable’ action. Within this, we want to set the ‘approverEmails’ variable created earlier. The value will be the ‘Email’ from the ‘Parse JSON’ action, plus also add semi-colon immediately after this (important, so our email addresses are separated properly!):

Process Screenshot 8

As we parsed our JSON nicely, we can just add the email here and because we’re in an ‘apply to each’, Flow will loop through every user returned and append the email address to our approverEmails variable. Don’t forget that semi-colon!

Step 10 – Phew. Finally, we’ve now got all the users from the group into a semi-colon separated variable in our Flow. We can now go ahead and create the approvals action. Add the action and configure as per your requirements. For the ‘Assigned To’, you need to click the ‘See more’ link underneath the ‘Variables’ section under Dynamic content:

Process Screenshot 9

Then choose our ‘approverEmails’ variable:

Process Screenshot 10

Step 11 – The finished Flow should look like this:

Process Screenshot 11

Step 12 – Now all that’s left to do is name, save, and run the Flow! I setup a group called ‘My SP group’ in my site  to use in the Flow and added the following users:

Process Screenshot 12

When I run the Flow, the tasks get sent out as below (check your Approvals > Sent section within Flow to see everybody the task went to):

Process Screenshot 13

If you look at the Flow run itself, you can check through the actions to see the data returned from the SharePoint call to get the group members. You can even click through the ‘apply to each’ to see all the emails (4 in my case) which were appended to the approverEmails variable:

Process Screenshot 14

Conclusion

It’s a bit of an initial faff, but it’s perfectly feasible to use SharePoint groups as assignees for your approval tasks in Flow if you’re prepared to query the group for the users first and build up a string of email addresses. If you have many approval tasks, it might get a bit bloated in your Flow, but perhaps you can figure out a fancy way to redo steps without having to do all the actions over and over. At least this is Flow, where you pay per execution, rather than Logic Apps where you pay by the action…!!

I suspect at some point Microsoft will improve Flow to allow some dynamic way of maintaining approver assignees, as the current implementation of just typing in emails manually isn’t great. So although this post is just a workaround, it’s viable for production use and the SharePoint REST API isn’t going anywhere anytime soon.

Next steps

  • Rename your actions in Flow with some better names than the defaults – always helps with readability. I usually keep the original name but add something to the end to indicate what it is. E.g. ‘Initialise variable approverEmails’ and ‘Apply to each user found in group’. Watch out for disallowed characters here as Flow is quite picky about special ones.
  • You could use Azure AD groups instead of SharePoint groups.
  • You could try storing your approvers in a list item in SharePoint, and query for that value to separate the emails out into a semi-colon separated string.
  • Wait for Microsoft to support assigning approvals directly to Azure AD/SharePoint groups 😊.
  • You can use the same approach as above to work with all other SharePoint REST API calls – so anything else you can achieve via the REST API in SharePoint that hasn’t made it into Flow as an action yet, just fall back on this approach of using the SharePoint HTTP request action.

Need more help with Flow or process automation?

If you have a tricky business process or questions about Flow, PowerApps, LogicApps or perhaps Nintex products and want assistance, advice or someone else to build it for you, our experts can help. We have over a decade of experience building workflows, business forms and other processes with various Microsoft and related technologies.

Find out more about our Process Automation services