In order to provide more granular and controlled access to flows, all our flows are enabled with access setting of "Override default behavior and restrict access to enabled profiles or permission sets" and access to the flows will be provisioned only using Permission Sets (Permission Set -> Flow Access settings).

We have a requirement to display the list of flows the user has access to based on the permission sets assigned to them. How can we achieve this using SOQL or Apex?

2 Answers 2


In short: I managed to do this in Apex by using apex-mdapi AFTER I updated the code to support flowAccesses. - here's the github commit with changes needed to support it. This is the only way I can see to do this through Apex as you need to hit the Metadata API.

Very Long Version

I didn't see anything within SOQL or Tooling API that can be used. It seems like it's only available with the Metadata API based on the simple fact that you can retrieve this information with the following package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">

This returns the following

<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">

That leaves you with trying to use Apex and the Metadata API. This isn't a supported type for what Salesforce provides access to through Apex. Likewise, I don't see any mention of flow access in the Metadata API Developer Guide which puzzled me. However, they do list the other naming conventions for other "access" types:


So now I looked towards apex-mdapi which does allow you to interact with apex/Metadata API

You can see the code/github here and this is a helpful answer with links to many questions concerning it. I had to make edits to it since it hasn't been updated since flowAccesses was brought into play. I used customMetadataTypeAccess (which is also relatively new) as a test since that one is at least documented in the developer guide.

You can see my changes in my forked repo and the latest commits contains all the changes needed for this in particular. Based on the naming convention in the developer guide (and testing that PermissionSetCustomMetadataTypeAccess[] worked first), I used PermissionSetFlowAccess[] and the example of the returned retrieve file to populate what the field names would be. You can see that the name of the flow is stored in <flow></flow>

So now, going off all that above...

Depending on when/where your code is executing, you'd probably first want to get a list of permission sets assigned to the user using SOQL. From this, you can see the following should do the trick

SELECT PermissionSet.Name FROM PermissionSetAssignment WHERE AssigneeId = 'User Name here'

Once you have a list of permission set names, you can call the Metadata API through the MetadataService you modified above to simply get those permission sets returned and loop through them to get a list of the Flows they have access to.

public class testmetadata {

    public static MetadataService.MetadataPort createService()
        MetadataService.MetadataPort service = new MetadataService.MetadataPort();
        service.SessionHeader = new MetadataService.SessionHeader_element();
        service.SessionHeader.sessionId = UserInfo.getSessionId();
        return service;     
    public static void testPerm()
        //presumably you'd pass this list based on the SOQL query
        String[] permissionSetNames = new String[] {'test', 'test2', 'test3'};

        String message = '';
        MetadataService.MetadataPort service = createService();
        List<MetadataService.PermissionSet> perm = (List<MetadataService.PermissionSet>) service.readMetadata('PermissionSet', permissionSetNames).getRecords();

        //loop through returned permission sets based on the names assigned to user
        for(MetadataService.PermissionSet permSet : perm){
            message = permSet.fullName + ' with access to the following flow(s): ';
            //loop through flows that are enabled for access in each perm set to display name
            for(MetadataService.PermissionSetFlowAccess singleFlow : permSet.flowAccesses){
               message += singleFlow.flow + ', ';

What I tested (using only 3 different flows):

  • Created 3 permission sets - test1, test2, test3
  • Gave test1 access to one flow
  • Gave test2 access to 2 flows
  • Gave test3 access to 3 flows

See the debug log returned below:

enter image description here

Update: Just to show that the assumptions I made above for the naming convention at least are now corroborated by info in the Metadata API WSDL. You can see the naming for Profile and Permission Set.

enter image description here

enter image description here

  • First of all, thank you so much for your time to answer this question.Its very detailed. I am facing this error when testing the code from your repo - "Line: 13496, Column: 1 System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: UNSUPPORTED_API_VERSION: Invalid Api version specified on URL faultcode=sf:UNSUPPORTED_API_VERSION faultactor=" Do I need to update something?
    – Mohan P
    Jan 16, 2020 at 22:58
  • 1
    Just pushed the commit. Forgot I was testing this in my Spring 20 dev org. Should work now. All I changed was the endpoint_x to be /services/Soap/m/47.0 Jan 16, 2020 at 23:21
  • 1
    This rocks. I would very much love it if you would now turn this code into one or more invocable actions and then post about it on unofficialsf.com. There is tremendous potential for declarative actions that allow admins to benefit from the powerful combination of MetadataService, Apex, and Flow. I'm working on some right now that pull in Approval Process metadata and expose useful actions in Flow screens. Just sayin'. =) Jan 21, 2020 at 23:54
  • 1
    @cropredy - flowaccesses now appears in the Metadata API WSDL! Still not in the documentation though. Jul 1, 2020 at 13:04
  • 1
    @PhilW - When you click on the dropdown of the flow row in setup, you should see an "Edit Access" button. There, you can configure your flow to Override default behavior and restrict access to enabled profiles or permission sets. This flowaccess is related to that - giving the user with the permissionset/profile ability to run a flow set up to be restricted by profile/permissionset access Mar 30, 2021 at 16:56

As of API version 58, you can:

Step 1) Query SetupEntityAccess

SELECT Id, SetupEntityType, SetupEntityId 
FROM SetupEntityAccess 
WHERE ParentId = :permSetId AND SetupEntityType = "FlowDefinition"

Step 2) Make a second query on FlowDefinitionView using the resulting SetupEntityId list:

SELECT DurableId, Label
FROM FlowDefinitionView
WHERE DurableId IN :setupEntityIdList

NOTE: As of this posting, the Object reference documentation for SetupEntityAccess has not yet been updated to reflect that the field SetupEntityType includes "FlowDefinition", but its working in practice.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .