Power Automate Web API
Note
Microsoft Flow is now Power Automate. For more information, see this blog.
This content will be updated to reflect the branding change in the coming days.
Going forward, all flows will be stored in Common Data Service and leverage the rich Web API.
This content covers the management of flows included on the Solutions tab in Power Automate. Currently, flows under My Flows are not supported by these APIs.
Compose HTTP requests
To get started creating requests, you'll need to first construct the URL. The format for the base URL of the Power Automate Web API is: https://{Organization ID}.{Regional Subdomain}.dynamics.com/api/data/v9.1/
. The two parameters are:
The Organization ID is a unique name for the environment that stores your flows. You can see the Organization ID in the environment switcher at the top-right of Power Automate. Note that the Organization ID is different from the Environment ID (which is the GUID that appears in the URL of the flow).
The Regional Subdomain depends on the location of your environment. When you sign in to Power Automate, you can see the region of your environment in the URL of the web page. Use that region name to find the respective subdomain in the following table:
Region Subdomain United States crm South America crm2 Canada crm3 Europe crm4 Asia Pacific crm5 Australia crm6 Japan crm7 India crm8 US Government crm9 United Kingdom crm11
You can also programmatically get the list of instances available to you via the Get Instances method in the Online Management API.
Each request to the Web API must have the Accept
and Content-type
headers set to application/json
.
Finally, populate the Authorization
header with an Azure AD Bearer token. You can learn how to acquire an Azure AD Bearer token for Common Data Service. For example, this request:
GET https://org00000000.crm0.dynamics.com/api/data/v9.1/workflows
Accept: application/json
Authorization: Bearer ey...
The response contains the list of flows from within that environment:
{
"@odata.context": "https://org00000000.crm0.dynamics.com/api/data/v9.1/$metadata#workflows",
"value": [{
"@odata.etag": "W/\"12116760\"",
"category": 5,
"statecode": 0,
"workflowidunique": "00000000-0000-0000-0000-000000000001",
"workflowid" : "00000000-0000-0000-0000-000000000002",
"createdon": "2018-11-15T19:45:51Z",
"_ownerid_value": "00000000-0000-0000-0000-000000000003",
"modifiedon": "2018-11-15T19:45:51Z",
"ismanaged": false,
"name": "Sample flow",
"_modifiedby_value": "00000000-0000-0000-0000-000000000003",
"_createdby_value": "00000000-0000-0000-0000-000000000003",
"type": 1,
"description": "This flow updates some data in Common Data Service.",
"clientdata": "{\"properties\":{\"connectionReferences\":{\"shared_commondataservice\":{\"source\":\"NotSpecified\",\"id\":\"/providers/Microsoft.PowerApps/apis/shared_commondataservice\",\"tier\":\"NotSpecified\"}},\"definition\":{...}},\"schemaVersion\":\"1.0.0.0\"}"
}]
}
List flows
As shown above, you can get the list of workflows by calling GET
on workflows
. Each workflow has many properties, but the most relevant are:
Property name | Description |
---|---|
category | The category of the flow. The different types are: 0 - classic Common Data Service workflows, 1 - classic Common Data Service dialogs, 2 - business rules, 3 - classic Common Data Service actions, 4- business process flows and 5 - automated, instant or scheduled flows. |
statecode | The status of the flow. The status can be 0 - off or 1 - on. |
workflowuniqueid | The unique identifier for this installation of the flow. |
workflowid | The unique identifier for a flow across all imports. |
createdon | The date when the flow was created. |
_ownerid_value | The unique identifier of the user or team who owns the flow. This is an id from the systemusers entity in Common Data Service. |
modifiedon | The last time the flow was updated. |
ismanaged | Indicates if the flow was installed via a managed solution. |
name | The display name that you have given the flow. |
_modifiedby_value | The last user who updated the flow. This is an id from the systemusers entity in Common Data Service. |
_createdby_value | The user who created the flow. This is an id from the systemusers entity in Common Data Service. |
type | Indicates if the flow is a running flow, or a template that can be used to create additional flows. 1 - flow, 2 - activation or 3 - template. |
description | The user-provided description of the flow. |
clientdata | A string-encoded JSON of an object that contains the connectionReferences and the definition of the flow. |
You can also request specific properties, filter the list of flows, and much more, as described in the Common Data Service API documentation for querying data. For example, this query returns only the automated, instant, or scheduled flows that are currently on:
GET https://org00000000.crm0.dynamics.com/api/data/v9.1/workflows?$filter=category eq 5 and statecode eq 1
Accept: application/json
Authorization: Bearer ey...
Create a flow
Call POST
on the workflows
collection to create a flow. The required properties for automated, instant, and scheduled flows are: category, name, type, primaryentity, and clientdata. Use none
for the primaryentity for these types of flows.
You can also provide a description and statecode.
POST https://org00000000.crm0.dynamics.com/api/data/v9.1/workflows
Accept: application/json
Authorization: Bearer ey...
Content-type: application/json
{
"category": 5,
"statecode": 0,
"name": "Sample flow name",
"type": 1,
"description": "This flow reads some data from Common Data Service.",
"primaryentity":"none",
"clientdata": "{\"properties\":{\"connectionReferences\":{\"shared_commondataservice\":{\"connectionName\":\"shared-commondataser-00000000-0000-0000-0000-000000000004\",\"source\":\"Invoker\",\"id\":\"/providers/Microsoft.Power Apps/apis/shared_commondataservice\"}},\"definition\":{\"$schema\": \"https:\/\/schema.management.azure.com\/providers\/Microsoft.Logic\/schemas\/2016-06-01\/workflowdefinition.json#\",\"contentVersion\": \"1.0.0.0\",\"parameters\": {\"$connections\": {\"defaultValue\": {},\"type\": \"Object\"},\"$authentication\": {\"defaultValue\": {},\"type\": \"SecureObject\"}},\"triggers\": {\"Recurrence\": {\"recurrence\": {\"frequency\": \"Minute\",\"interval\": 1},\"type\": \"Recurrence\"}},\"actions\": {\"List_records\": {\"runAfter\": {},\"metadata\": {\"flowSystemMetadata\": {\"swaggerOperationId\": \"GetItems_V2\"}},\"type\": \"ApiConnection\",\"inputs\": {\"host\": {\"api\": {\"runtimeUrl\": \"https:\/\/firstrelease-001.azure-apim.net\/apim\/commondataservice\"},\"connection\": {\"name\": \"@parameters('$connections')['shared_commondataservice']['connectionId']\"}},\"method\": \"get\",\"path\": \"\/v2\/datasets\/@{encodeURIComponent(encodeURIComponent('default.cds'))}\/tables\/@{encodeURIComponent(encodeURIComponent('accounts'))}\/items\",\"queries\": {\"$top\": 1},\"authentication\": \"@parameters('$authentication')\"}}},\"outputs\": {}}},\"schemaVersion\":\"1.0.0.0\"}"
}
The most important section is the clientdata
, which contains the connectionReferences that the flow uses, and the definition of the flow. The connectionReferences are the mappings to each connection that the flow uses.
There are three properties:
Property name | Description |
---|---|
connectionName | Identifies the connection. You can see the connectionName by going to the Connections page and then copying it from the URL of the connection. |
source | Either Embedded or Invoker . Invoker is only valid for instant flows (those where a user selects a button to run the flow), and indicates that the end user will provide the connection. In this case the connectionName is only used at design time. If the connection is Embedded , that means the connectionName you specify is always used. |
id | The identifier of the connector. The id always starts with /providers/Microsoft.PowerApps/apis/ and then has the connector name, which you can copy from the URL of the connection or by selecting the connector from the Connectors page. |
Once you execute the POST
request, you'll receive the OData-EntityId
header, which will contain the workflowid
for your new flow.
Update a flow
You can call PATCH
on the workflow to update, turn on, or turn off a flow. Use the workflowid
property to make these calls. For example, you can update the description and the owner of the flow with the following call:
PATCH https://org00000000.crm0.dynamics.com/api/data/v9.1/workflows(00000000-0000-0000-0000-000000000002)
Accept: application/json
Authorization: Bearer ey...
Content-type: application/json
{
"description" : "This flow will ensure consistency across systems.",
"ownerid@odata.bind": "systemusers(00000000-0000-0000-0000-000000000005)",
}
Note
The syntax for changing the owner uses the odata.bind
format. This means instead of patching the _ownerid_value field directly, you append @odata.bind
to the property name and then wrap the ID with systemusers()
.
In another example, you can turn a flow on with this call:
PATCH https://org00000000.crm0.dynamics.com/api/data/v9.1/workflows(00000000-0000-0000-0000-000000000002)
Accept: application/json
Authorization: Bearer ey...
Content-type: application/json
{
"statecode" : 1
}
Delete a flow
Delete a flow with a simple DELETE
call:
DELETE https://org00000000.crm0.dynamics.com/api/data/v9.1/workflows(00000000-0000-0000-0000-000000000002)
Accept: application/json
Authorization: Bearer ey...
Note
You cannot delete a flow that's turned on. You must first turn off the flow (see Updating a flow previously) or else you will see the error: Cannot delete an active workflow definition.
Get all users with whom a flow is shared
Listing the users with access uses a function in Common Data Service. This function takes a single parameter of Target
:
GET https://org00000000.crm0.dynamics.com/api/data/v9.1/RetrieveSharedPrincipalsAndAccess(Target=@tid)?@tid={'@odata.id':'workflows(00000000-0000-0000-0000-000000000002)'}
Accept: application/json
Authorization: Bearer ey...
The Target
parameter is a JSON-like string with a single property called @odata.id
. Replace the workflow ID in the above example. It returns:
{
"@odata.context": "https://org00000000.crm0.dynamics.com/api/data/v9.1/$metadata#Microsoft.Dynamics.CRM.RetrieveSharedPrincipalsAndAccessResponse",
"PrincipalAccesses": [
{
"AccessMask": "ReadAccess",
"Principal": {
"@odata.type": "#Microsoft.Dynamics.CRM.systemuser",
"ownerid": "00000000-0000-0000-0000-000000000005"
}
}
]
}
Share or unshare a flow
You can share a flow using the GrantAccess
action.
POST https://org00000000.crm0.dynamics.com/api/data/v9.1/GrantAccess
Accept: application/json
Authorization: Bearer ey...
Content-type: application/json
{
"Target" : {
"@odata.type": "Microsoft.Dynamics.CRM.workflow",
"workflowid" : "00000000-0000-0000-0000-000000000002"
},
"PrincipalAccess": {
"Principal": {
"@odata.type" : "Microsoft.Dynamics.CRM.systemuser",
"ownerid" : "00000000-0000-0000-0000-000000000005"
},
"AccessMask": "ReadAccess"
}
}
The AccessMask
parameter is a field with the following values for different permission levels:
Name | Description |
---|---|
None | No access. |
ReadAccess | The right to read the flow. |
WriteAccess | The right to update the flow. |
DeleteAccess | The right to delete the flow. |
ShareAccess | The right to share the flow. |
AssignAccess | The right to change the owner of the flow. |
You can combine permissions with a comma; for example, provide the ability to both read and update a flow by passing ReadAccess,WriteAccess
.
You can unshare a flow with the RevokeAccess
action. Here's an example:
POST https://org00000000.crm0.dynamics.com/api/data/v9.1/RevokeAccess
Accept: application/json
Authorization: Bearer ey...
Content-type: application/json
{
"Target" : {
"@odata.type": "Microsoft.Dynamics.CRM.workflow",
"workflowid" : "00000000-0000-0000-0000-000000000002"
},
"Revokee": {
"@odata.type" : "Microsoft.Dynamics.CRM.systemuser",
"ownerid" : "00000000-0000-0000-0000-000000000005"
}
}
RevokeAccess
removes all permissions granted in the AccessMask
.
Export flows
Use the ExportSolution
action to export flows to a .zip file. First, add the flows that you want to a solution.
Once your flow is in a solution, call the following action:
POST https://org00000000.crm0.dynamics.com/api/data/v9.1/ExportSolution
Accept: application/json
Authorization: Bearer ey...
Content-type: application/json
{
"SolutionName" : "Awesome solution 1",
"Managed": false
}
ExportSolution
returns a base 64-encoded string in the ExportSoutionFile
property.
{
"@odata.context": "https://org00000000.crm0.dynamics.com/api/data/v9.1/$metadata#Microsoft.Dynamics.CRM.ExportSolutionResponse",
"ExportSolutionFile": "UEsDBBQAAgAI..."
}
You can then save this file into source control and/or use whatever version management or distribution system you want.
Import flows
Call the ImportSolution
action to import a solution.
Property name | Description |
---|---|
OverwriteUnmanagedCustomizations | If there are existing instances of these flows in Common Data Service, this flag needs to be set to true to import them. Otherwise they will not be overwritten. |
PublishWorkflows | Indicates if classic Common Data Service workflows will be activated on import. This setting doesn't apply to other types of flows. |
ImportJobId | Provides a new, unique GUID to track the import job. |
CustomizationFile | A base 64-encoded zip file that contains the solution. |
POST https://org00000000.crm0.dynamics.com/api/data/v9.1/ImportSolution
Accept: application/json
Authorization: Bearer ey...
Content-type: application/json
{
"OverwriteUnmanagedCustomizations": false,
"PublishWorkflows" : true,
"ImportJobId" : "00000000-0000-0000-0000-000000000006",
"CustomizationFile" : "UEsDBBQAAgAI..."
}
Since import is a long-running operation, the response to the ImportSolution action will be a 204 No content
. To track the progress, call a GET
on the importjobs
object, providing the ImportJobId
that you included in the original ImportSolution
action.
GET https://org00000000.crm0.dynamics.com/api/data/v9.1/importjobs(00000000-0000-0000-0000-000000000006)
Accept: application/json
Authorization: Bearer ey...
This call returns the status of the import operation, including progress
(the percentage of completion), startedon
, and completedon
(if import finished).
Once import has completed successfully, you will need to set up the connections for the flow, since the connectionNames
will likely be different in the destination environment (if the connections exist at all). If you are setting up new connections in the destination environment, then the owner of the flows must create them in the Power Automate designer. If the connections are already set up in the new environment, then you can PATCH
the clientData
of the flow with the names of the connections.
Feedback
Loading feedback...