Schema reference guide for the Workflow Definition Language in Azure Logic Apps

When you create a logic app in Azure Logic Apps, your logic app has an underlying workflow definition that describes the actual logic that runs in your logic app. That workflow definition uses JSON and follows a structure that's validated by the Workflow Definition Language schema. This reference provides an overview about this structure and how the schema defines attributes in your workflow definition.

Workflow definition structure

A workflow definition always includes a trigger for instantiating your logic app, plus one or more actions that run after the trigger fires.

Here is the high-level structure for a workflow definition:

"definition": {
  "$schema": "<workflow-definition-language-schema-version>",
  "actions": { "<workflow-action-definitions>" },
  "contentVersion": "<workflow-definition-version-number>",
  "outputs": { "<workflow-output-definitions>" },
  "parameters": { "<workflow-parameter-definitions>" },
  "staticResults": { "<static-results-definitions>" },
  "triggers": { "<workflow-trigger-definitions>" }
}
Attribute Required Description
definition Yes The starting element for your workflow definition
$schema Only when externally referencing a workflow definition The location for the JSON schema file that describes the Workflow Definition Language version, which you can find here:

https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json
actions No The definitions for one or more actions to execute at workflow runtime. For more information, see Triggers and actions.



Maximum actions: 250
contentVersion No The version number for your workflow definition, which is "1.0.0.0" by default. To help identify and confirm the correct definition when deploying a workflow, specify a value to use.
outputs No The definitions for the outputs to return from a workflow run. For more information, see Outputs.



Maximum outputs: 10
parameters No The definitions for one or more parameters that pass the values to use at your logic app's runtime. For more information, see Parameters.



Maximum parameters: 50
staticResults No The definitions for one or more static results returned by actions as mock outputs when static results are enabled on those actions. In each action definition, the runtimeConfiguration.staticResult.name attribute references the corresponding definition inside staticResults. For more information, see Static results.
triggers No The definitions for one or more triggers that instantiate your workflow. You can define more than one trigger, but only with the Workflow Definition Language, not visually through the workflow designer. For more information, see Triggers and actions.



Maximum triggers: 10

Triggers and actions

In a workflow definition, the triggers and actions sections define the calls that happen during your workflow's execution. For syntax and more information about these sections, see Workflow triggers and actions.

Parameters

The deployment lifecycle usually has different environments for development, test, staging, and production. When deploying logic apps to various environments, you likely want to use different values, such as connection strings, based on your deployment needs. Or, you might have values that you want to reuse throughout your logic app without hardcoding or that change often. In your workflow definition's parameters section, you can define or edit parameters for the values that your logic app uses at runtime. You must define these parameters first before you can reference these parameters elsewhere in your workflow definition.

Here is the general structure for a parameter definition:

"parameters": {
   "<parameter-name>": {
      "type": "<parameter-type>",
      "defaultValue": <default-parameter-value>,
      "allowedValues": [ <array-with-permitted-parameter-values> ],
      "metadata": {
         "description": "<parameter-description>"
      }
   }
},
Attribute Required Type Description
<parameter-name> Yes String The name for the parameter that you want to define
<parameter-type> Yes int, float, string, bool, array, object, securestring, secureobject



Note: For all passwords, keys, and secrets, use the securestring or secureobject types because the GET operation doesn't return these types. For more information about securing parameters, see Security recommendations for action and input parameters.
The type for the parameter
<default-parameter-value> Yes Same as type The default parameter value to use if no value is specified when the workflow instantiates. The defaultValue attribute is required so that the Logic App Designer can correctly show the parameter, but you can specify an empty value.
<array-with-permitted-parameter-values> No Array An array with values that the parameter can accept
<parameter-description> No JSON object Any other parameter details, such as a description for the parameter

Next, create an Azure Resource Manager template for your workflow definition, define template parameters that accept the values you want at deployment, replace hardcoded values with references to template or workflow definition parameters as appropriate, and store the values to use at deployment in a separate parameter file. That way, you can change those values more easily through the parameter file without having to update and redeploy your logic app. For information that is sensitive or must be secured, such as usernames, passwords, and secrets, you can store those values in Azure Key Vault and have your parameter file retrieve those values from your key vault. For more information and examples about defining parameters at the template and workflow definition levels, see Overview: Automate deployment for logic apps with Azure Resource Manager templates.

Static results

In the staticResults attribute, define an action's mock outputs and status that the action returns when the action's static result setting is turned on. In the action's definition, the runtimeConfiguration.staticResult.name attribute references the name for the static result definition inside staticResults. Learn how you can test logic app workflows with mock data by setting up static results.

"definition": {
   "$schema": "<...>",
   "actions": { "<...>" },
   "contentVersion": "<...>",
   "outputs": { "<...>" },
   "parameters": { "<...>" },
   "staticResults": {
      "<static-result-definition-name>": {
         "outputs": {
            <output-attributes-and-values-returned>,
            "headers": { <header-values> },
            "statusCode": "<status-code-returned>"
         },
         "status": "<action-status>"
      }
   },
   "triggers": { "<...>" }
}
Attribute Required Type Description
<static-result-definition-name> Yes String The name for a static result definition that an action definition can reference through a runtimeConfiguration.staticResult object. For more information, see Runtime configuration settings.

You can use any unique name that you want. By default, this unique name is appended with a number, which is incremented as necessary.
<output-attributes-and-values-returned> Yes Varies The requirements for these attributes vary based on different conditions. For example, when the status is Succeeded, the outputs attribute includes attributes and values returned as mock outputs by the action. If the status is Failed, the outputs attribute includes the errors attribute, which is an array with one or more error message objects that have error information.
<header-values> No JSON Any header values returned by the action
<status-code-returned> Yes String The status code returned by the action
<action-status> Yes String The action's status, for example, Succeeded or Failed

For example, in this HTTP action definition, the runtimeConfiguration.staticResult.name attribute references HTTP0 inside the staticResults attribute where the mock outputs for the action are defined. The runtimeConfiguration.staticResult.staticResultOptions attribute specifies that the static result setting is Enabled on the HTTP action.

"actions": {
   "HTTP": {
      "inputs": {
         "method": "GET",
         "uri": "https://www.microsoft.com"
      },
      "runAfter": {},
      "runtimeConfiguration": {
         "staticResult": {
            "name": "HTTP0",
            "staticResultOptions": "Enabled"
         }
      },
      "type": "Http"
   }
},

The HTTP action returns the outputs in the HTTP0 definition inside staticResults. In this example, for the status code, the mock output is OK. For header values, the mock output is "Content-Type": "application/JSON". For the action's status, the mock output is Succeeded.

"definition": {
   "$schema": "<...>",
   "actions": { "<...>" },
   "contentVersion": "<...>",
   "outputs": { "<...>" },
   "parameters": { "<...>" },
   "staticResults": {
      "HTTP0": {
         "outputs": {
            "headers": {
               "Content-Type": "application/JSON"
            },
            "statusCode": "OK"
         },
         "status": "Succeeded"
      }
   },
   "triggers": { "<...>" }
},

Expressions

With JSON, you can have literal values that exist at design time, for example:

"customerName": "Sophia Owen",
"rainbowColors": ["red", "orange", "yellow", "green", "blue", "indigo", "violet"],
"rainbowColorsCount": 7

You can also have values that don't exist until run time. To represent these values, you can use expressions, which are evaluated at run time. An expression is a sequence that can contain one or more functions, operators, variables, explicit values, or constants. In your workflow definition, you can use an expression anywhere in a JSON string value by prefixing the expression with the at-sign (@). When evaluating an expression that represents a JSON value, the expression body is extracted by removing the @ character, and always results in another JSON value.

For example, for the previously defined customerName property, you can get the property value by using the parameters() function in an expression and assign that value to the accountName property:

"customerName": "Sophia Owen",
"accountName": "@parameters('customerName')"

String interpolation also lets you use multiple expressions inside strings that are wrapped by the @ character and curly braces ({}). Here is the syntax:

@{ "<expression1>", "<expression2>" }

The result is always a string, making this capability similar to the concat() function, for example:

"customerName": "First name: @{parameters('firstName')} Last name: @{parameters('lastName')}"

If you have a literal string that starts with the @ character, prefix the @ character with another @ character as an escape character: @@

These examples show how expressions are evaluated:

JSON value Result
"Sophia Owen" Return these characters: 'Sophia Owen'
"array[1]" Return these characters: 'array[1]'
"@@" Return these characters as a one-character string: '@'
" @" Return these characters as a two-character string: ' @'

For these examples, suppose you define "myBirthMonth" equal to "January" and "myAge" equal to the number 42:

"myBirthMonth": "January",
"myAge": 42

These examples show how the following expressions are evaluated:

JSON expression Result
"@parameters('myBirthMonth')" Return this string: "January"
"@{parameters('myBirthMonth')}" Return this string: "January"
"@parameters('myAge')" Return this number: 42
"@{parameters('myAge')}" Return this number as a string: "42"
"My age is @{parameters('myAge')}" Return this string: "My age is 42"
"@concat('My age is ', string(parameters('myAge')))" Return this string: "My age is 42"
"My age is @@{parameters('myAge')}" Return this string, which includes the expression: "My age is @{parameters('myAge')}`

When you're working visually in the workflow designer, you can create expressions using the expression editor, for example:

Screenshot shows workflow designer and expression editor.

When you're done, the expression appears for the corresponding property in your workflow definition, for example, the searchQuery property here:

"Search_tweets": {
  "inputs": {
    "host": {
      "connection": {
        "name": "@parameters('$connections')['x']['connectionId']"
      }
    }
  },
  "method": "get",
  "path": "/searchtweets",
  "queries": {
    "maxResults": 20,
    "searchQuery": "Azure @{concat('firstName','', 'LastName')}"
  }
},

Outputs

In the outputs section, define the data that your workflow can return when finished running. For example, to track a specific status or value from each run, specify that the workflow output returns that data.

Note

When responding to incoming requests from a service's REST API, don't use outputs. Instead, use the Response action type. For more information, see Workflow triggers and actions.

Here is the general structure for an output definition:

"outputs": {
  "<key-name>": {
    "type": "<key-type>",
    "value": "<key-value>"
  }
}
Attribute Required Type Description
<key-name> Yes String The key name for the output return value
<key-type> Yes int, float, string, securestring, bool, array, JSON object The type for the output return value
<key-value> Yes Same as <key-type> The output return value

To get the output from a workflow run, review your logic app's run history and details in the Azure portal or use the Workflow REST API. You can also pass output to external systems, for example, Power BI so that you can create dashboards.

Operators

In expressions and functions, operators perform specific tasks, such as reference a property or a value in an array.

Operator Task
' To use a string literal as input or in expressions and functions, wrap the string only with single quotation marks, for example, '<myString>'. Do not use double quotation marks (""), which conflict with the JSON formatting around an entire expression. For example:

Yes: length('Hello')
No: length("Hello")

When you pass arrays or numbers, you don't need wrapping punctuation. For example:

Yes: length([1, 2, 3])
No: length("[1, 2, 3]")
[] To reference a value at a specific position (index) in an array or inside a JSON object, use square brackets, for example:

- To get the second item in an array:

myArray[1]

- To access the properties inside a JSON object:

Example 1:
setProperty(<object>, '<parent-property>', addProperty(<object>['<parent-property>'], '<child-property>', <value>)

Example 2:
lastIndexOf(triggerBody()?['subject'],'some string')
. To reference a property in an object, use the dot operator. For example, to get the name property for a customer JSON object:

"parameters('customer').name"
? To reference null properties in an object without a runtime error, use the null-ignore (?) operator. For example, to handle null outputs from a trigger, you can use the following expression:

coalesce(trigger().outputs?.body?['<someProperty>'], '<property-default-value>')

Functions

Some expressions get their values from runtime actions that might not yet exist when your workflow definition starts to run. To reference or work with these values in expressions, you can use functions that the Workflow Definition Language provides.

Next steps