Dynamic Variable Syntax
To manually add Dynamic Variables to a workflow, you can use our Expression Language syntax. This involves wrapping the variable in double curly brackets . This syntax specifies the variable type and its reference path within the workflow, enabling dynamic data usage across different workflow components.
Whether an expression is entered manually or chosen using the variable picker,it will be saved in the Workflow YAML
using the syntax shown below.
Dynamic Variables follow a structured syntax enclosed within double curly braces
{{ }}
.
The syntax specifies the variable type and its reference path within the workflow. Understanding this format allows you to insert variables manually when necessary or desired.
Tip
When working with dynamic variables, sometimes the value can be null
, which can cause issues when displaying values in the variable picker or workflow inputs.
Here is a useful tip to replace null
with a default value:
- If a variable might be null, you can use a ternary-style expression to replace it with a fallback value:
{{event.payload.case.vendors != null ? event.payload.case.vendors : "N/a"}}
- Another approach is to force the variable into a string format, which can ensure it does not remain null:
str({{steps.s2.output}})
General Syntax Structure
-
category
defines the dynamic variables type (e.g., inputs, steps, event, metadata). -
identifier
specifies the exact reference within the category. -
For example, referencing an input parameter named ‘slack_channel’:
Adding Dynamic Variables Manually in a Workflow
Workflow Input Parameters
To reference data entered in workflow inputs, use the following syntax:
param_name
represents the name you assigned to the input parameter.
Event payload
To reference data returned from an event payload that triggered an Event-Based Workflow, use the following syntax:
Step Output Variables
To reference data returned from a step’s output, use the following syntax:
The S
in steps.S1.output
represents a step in the workflow, and the number
following it (1
in this case) indicates the specific step being referenced.
Each step in a workflow is assigned a unique identifier (S1
, S2
, etc.),
allowing you to retrieve outputs from a particular step.
💡 You can also use last
instead of a step ID
to reference the most recent step output:
Step Status
To check the execution status of a previous step, use the following syntax:
Workflow Variables
To use Workflow’s variables created by the Set Variable Action, use the following syntax:
Metadata Variables
To access metadata (workflow-related information), use the following syntax
Python Actions
The syntax for referencing data returned from Python actions is different. In steps that include Python actions, you need to use the context
variable to access dynamic variables. This means that all the expressions mentioned above can be accessed in Python using the following syntax:
In Python actions, variables can be assigned a value, by using the following syntax:
Best Practices
- Use the Variable Picker to avoid syntax errors.
- When referencing JSON keys with dots (.), use square bracket notation if needed.
- Step outputs are only available after execution; ensure dependencies are correctly structured.
Common Expression Language Use Case Examples
This section provides practical examples of how to use Expression Language within Blink’s workflows to manipulate data, apply logic, and dynamically build output values. Each use case highlights a specific pattern ,such as conditional branching, string formatting, safe referencing of variables, or working with nested data structures, that is commonly needed when building automated logic in workflows.
All print steps are intended to display the content of a variable along with its expression. The variable can then be used like any standard variable, except in dynamic connection assignments.
Best practice: Start by using a print step to validate the variable’s behavior. Once it returns the expected output, you can confidently use it as a regular variable wherever needed.
Extract the Domain or Username from an Email Address
Extract the Domain or Username from an Email Address
This use case demonstrates how to use the split() function to extract either the domain or username portion of an email address using dynamic expressions.
Extract the Domain from an Email Address
Returns the domain part of an email (everything after the @
).
Syntax:
{{split(steps.1.output.payload.headers[0].value, '@')[1]}}
Breakdown:
steps.1.output.payload.headers[0].value
: References the email address value returned in step 1 (S1
), specifically from the first object in the headers array.
split(..., '@')
: Splits the email string into two parts at the @ symbol.
[1]
: Returns the second element of the array, which corresponds to the domain.
Example:
Extract the Username from an Email Address
Extracts the portion of the email address that appears before the @
symbol.
Syntax:
{{split(steps.1.output.payload.headers[0].value, '@')[0]}}
Breakdown:
Identical to the previous expression, but [0]
retrieves the first element from the split array, representing the username.
Example:
Extract the Domain from a URL
Extract the Domain from a URL
Extract the Domain from a URL
This use case demonstrates how to extract the domain portion from a full URL string by using nested split() functions.
Syntax:
{{split(split(steps.3.output.files[0].webViewLink, 'https://')[1], '.')[0]}}
Breakdown:
steps.3.output.files[0].webViewLink
: Retrieves a URL (e.g., https://drive.google.com/…) from the first file object in step S3.
split(..., 'https://')[1]
: Removes the https:// prefix and keeps the remaining part of the URL.
- Result: drive.google.com/…
split(..., '.')[0]
: Splits the remaining string at the first period and returns the first element — the subdomain or main domain prefix.
- Result: drive
Example:
In the following use case, we isolate the domain prefix from a URL, specifically extracting drive from a full URL such as https://drive.google.com/...
. This is done by targeting the subdomain or first segment of the domain name following the https://
prefix.
Create a New URL Using Part of Another URL
Create a New URL Using Part of Another URL
Create a New URL Using Part of Another URL
This use case demonstrates how to dynamically reconstruct a URL by removing a specific path segment and joining the remaining parts. In this example, the segment being removed is /api/v3, but this can be any string or path segment relevant to your use case.
Syntax
{{split(steps.1.output.data.links.item, '/api/v3')[0] + split(steps.1.output.data.links.item, '/api/v3')[1]}}
Breakdown:
steps.1.output.data.links.item
: Retrieves the original URL from the output of step S1.
split(..., '/api/v3')
: Splits the URL at the /api/v3 segment.
[0]
: Returns the portion of the URL before /api/v3.
+
: Concatenates both parts together, effectively removing /api/v3.
[1]
: Returns the portion of the URL after /api/v3.
Example:
Fallback if a Field is Null
Fallback if a Field is Null
Fallback if a Field is Null
Checks if the username exists, if not, shows a fallback message.
Syntax:
{{steps.1.output.username!= null ? steps.1.output.username: 'User Not found'}}
Example:
In the following example, the workflow attempts to retrieve user information from GitHub using the input blinkopstester123
. Since the user does not exist, the API response does not return a username
field—resulting in a null
value. The expression checks for this and instead displays the fallback message "User Not found"
to avoid showing a blank or null
output.
You can also wrap the expression in str() to ensure it doesn’t remain null, which is useful when passing values into string-only fields:
Syntax
str({{steps.s1.output}})
Switch-Case Style Value Mapping
Switch-Case Style Value Mapping
Switch-Case Style Value Mapping
This use case demonstrates how to implement a switch-case-like logic within an expression to map specific input values to custom outputs. It is particularly useful for normalizing inconsistent values or applying conditional logic directly within a dynamic expression.
Syntax:
{{event.payload.severity == "MEDIUM" ? "medium" : event.payload.severity == "Low"? "Low" : "Not Found"}}
Breakdown:
event.payload.severity
: Retrieves the severity value from the event payload.
== "MEDIUM"
: Checks if the value is “MEDIUM” and maps it to “medium” (lowercase).
== "Low"
: If the first condition fails, it checks for “Low” and maps it as-is.
"Not Found"
: If none of the conditions match, the expression returns a default fallback value of “Not Found”.
Example:
Map known severity levels to preferred output formats (e.g., lowercase), and return a default value for any unmatched input.
Check if a Value is in a List
Check if a Value is in a List
Check if a Value is in a List
This use case demonstrates how to evaluate whether a specific value exists within a defined list. If the value is found, it returns a corresponding output; otherwise, it returns a fallback value.
Syntax:
{{event.payload.severity in ["High", "Low"] ? steps.2.output.severity : "Not Found"}}
Breakdown:
event.payload.severity
: Retrieves the severity value from the incoming event payload.
in ["High", "Low"]
: Checks whether the severity is included in the specified list of allowed values.
? steps.2.output.severity
: If the value is in the list, return the severity output from step S2.
: "Not Found
: If the value is not in the list, return “Not Found” as the default response.
Example:
Check whether the severity value from the event payload matches one of the allowed values (“High” or “Low”). If it matches, return the severity output from a previous step; if not, return a default string ( “Not Found”).
Switch Based On Successful Action
Switch Based On Successful Action
Switch Based On Successful Action
This use case demonstrates how to return a step’s output conditionally based on whether the step executed successfully. It allows you to avoid using additional variable-setting steps by referencing the success status directly.
Syntax
{{steps.2.status == "OK" ? steps.2.output : steps.3.output}}
Breakdown:
steps.2.status
:
- Checks the status of step 2 (
S2
).
== "OK"
: Evaluates whether step S2 executed successfully.
? steps.2.output
: If step S2 was successful, return its output.
: steps.3.output
: If step S2 was not successful, fall back to the output from step S3.
if-else
structure.Example:
In workflows where you use branching logic (e.g., an If-Else condition), you often want to capture the output of the branch that actually executed. A common approach is to include a Set Variable action within each branch to define the result.
However, you can simplify this by checking which branch step completed successfully and referencing its output directly—no additional variable step needed.
Use a Variable Within a Variable
Use a Variable Within a Variable
Use a Variable Within a Variable
This use case demonstrates how to reference a dynamic value inside another variable, which is particularly useful for mapping values or accessing specific data within a JSON object using a dynamic key.
Syntax:
{{steps.2.output.keymap[ steps.1.output.selected_key]}}
Breakdown:
The whole expression retrieves the value from keymap that corresponds to the key stored in selected_key
.
steps.2.output.keymap
: refers to the output of step 2, specifically the keymap JSON object.
[steps.1.output.selected_key ]: uses the value of selected_key from step 1’s(
S1`) output as the dynamic key to access a value inside keymap.
2. Can also be chained:
{{steps.2.output.keymap[ steps.1.output.selected_key ][ steps.1.output.selected_key2 ]}}
Breakdown:
This expression accesses a nested value within keymap by chaining two dynamic keys.
-
steps.2.output.keymap
: A nested JSON object. -
[steps.1.output.selected_key]
: First-level dynamic key from step 1 output. -
[ steps.1.output.selected_key2]
: Second-level dynamic key from step 1 output.
3. Variable used inside another variable’s key:
{{steps.2.output.keymap[ steps.1.output.selected_key[ steps.1.output.selected_key2 ]]}}
Breakdown:
steps.1.output.selected_key
: A JSON object
[steps.1.output.selected_key2]
: dynamically accesses a key inside selected_key.
The result of steps.1.output.selected_key[ steps.1.output.selected_key2]
is used as a key to index into steps.2.output.keymap
Example:
Dynamic Loop Limiter
Dynamic Loop Limiter
Dynamic Loop Limiter
When configuring loops in workflows, it is important that the loop limit corresponds correctly to the size of the list it iterates over. Setting a loop limit that exceeds the length of the list will cause the loop to fail with an error.
This use case demonstrates how to dynamically set the loop limit by comparing the length of the list with a predefined maximum limit and selecting the appropriate value to avoid errors.
Syntax:
{{len(variables.data_to_loop) < variables.loop_max ? len(variables.data_to_loop)-1 : variables.loop_max}}
Breakdown:
len(variables.data_to_loop)
: Returns the number of items in the list stored in the variable data_to_loop.
< variables.loop_max
: Compares the list length to the maximum allowed number of iterations, loop_max.
? ... : ...
: This ternary operator returns one of two values depending on the comparison:
- If true, it returns
len(variables.data_to_loop) - 1
(the last valid index of the list). - If false, it returns the maximum loop limit,
variables.loop_max
.
len(variables.data_to_loop) - 1
: Because loops are zero-indexed, this sets the loop limit to the last valid item index if the list is shorter than the max limit.
variables.loop_max
: The maximum number of iterations allowed if the list is longer or equal in length.
Examples
-
List shorter than
loop_max
variables.data_to_loop = ["item1", "item2", "item3"]
variables.loop_max = 5
Evaluation
len(data_to_loop) = 3
3 < 5
→ True- Result →
3 - 1 = 2
Outcome The loop limit is set to
2
(allowing indices 0, 1, 2). -
List longer than
loop_max
variables.data_to_loop = ["item1", "item2", "item3"]
variables.loop_max = 2
Evaluation
len(data_to_loop) = 3
3 < 2
→ False- Result →
variables.loop_max = 2
Outcome The loop limit remains at
2
.
String Building
String Building
String Building
This use case demonstrates how to dynamically build a descriptive string using values from multiple elements in email header (JSON format). By using a combination of direct references and string concatenation, you can format output data into a clear, readable message.
Syntax:
{{steps.2.output.payload.headers[0].value + " ( " + steps.2.output.payload.headers[1].name + steps.2.output.payload.headers[1].value + " ) "}}
Breakdown:
inputs.Name
: This retrieves the Delivered-To email address from the email header.
+
: String concatenation which combines multiple substrings into one final string.
" ( " + ... + " ) "
: Literal characters that wrap the date value(steps.2.output.payload.headers[1].value
) in parentheses.
steps.2.output.payload.headers[1].name
: Retrieves the name of the second header, which in this case is Received
.
steps.2.output.payload.headers[1].value
: Represents metadata about the message transmission (e.g., SMTP server info, timestamp, etc.).
Example:
The expression combines multiple different strings into a single output:
johndoe@gmail.com (Received by 2002:a2ea:e990:0:b2d6:f3f:399 with SMTP id x16csp3161761qj; Wed, 10 Apr 2024 03:07:20 -0700 (PDT))