Skip to main content
Skip table of contents

Unwind Tasks

LAST UPDATED: JUNE 20, 2025

Unwind tasks split a JSON array into individual objects, each containing one element from the array along with any root-level fields preserved. This results in a new object per deconstructed array item.

An image of the unwind task node.

Understanding the Unwind Task

The Unwind task type can support various data processing scenarios. Common use cases include the following:

  • Allowing each item in an JSON array to be processed independently by downstream tasks.

  • Enabling conditional logic to evaluate each array element individually, allowing multiple branches to match rather than stopping at the first true condition.

    Refer to this example for details.

  • Creating structured reports in which each array element produces a distinct row or entry (e.g., an Excel report)

If the Unwind task executes successfully, all downstream tasks will run n times, where n is the number of items deconstructed by the Unwind task.

Group 51.png

The Stage and Stage 2 tasks executed 3 times as they are downstream of the Unwind task, which unwound three objects from an array.

Using the Unwind Task

There are two input parameters available for the Unwind task.

  1. JSON Data: The JSON object to be processed. This can be a root-level array or an object that contains at least one array.

  2. JSON Path of Array Field (Optional): The path to the specific array within the JSON object (provided in JSON Data) to be deconstructed.

Group 1 (6).png

Specifying the JSON Data

The first step in using the Unwind task is to identify the JSON Data to deconstruct. The input value must contain at least one array. In the example below, the JSON Data parameter references the output from a task named Data, which returns an array at the root level.

Group 53.png

This directs the Unwind task to deconstruct the root-level array, which contains two objects.

Group 52 (1).png

Users can view the unwound objects on the Context Data tab, along with additional details such as the count field (indicating the number of items unwound from the array) and the unwound items themselves, now contained within the data array.

Group 83.png

In this example, since two objects were unwound, any downstream task—such as the Execute Twice Stage task—will execute or be suggested for execution twice, once per unwound item.

Group 55.png

Specifying the Array Field to Deconstruct

In some scenarios, users may need to unwind an array nested within an object while retaining fields from the parent level. For example, an analyst might unwind an array of IP addresses while preserving contextual information—such as the triggering alert, its ID, priority, and timestamp—present at the root level.

ORIGINAL DATA STRUCTURE

The data structure in the example below illustrates a case where elements requiring individual processing (i.e., IP addresses) are stored in a nested array, while parent-level information must be retained across each iteration.

JSON
{
  "alert_id": "evt-12345",
  "priority": "high",
  "source": "Firewall",
  "timestamp": "2025-06-02T14:20:00Z",
  "ip_addresses": [
    "192.168.1.10",
    "10.0.0.5",
    "172.16.0.3"
  ]
}

POST-UNWIND DATA STRUCTURE

This structure can be generated by using the Unwind task and setting the JSON Path of Array Field to $.ip_addresses, which deconstructs the array while preserving the surrounding context from the parent object.

JSON
[
  {
    "alert_id": "evt-12345",
    "priority": "high",
    "source": "Firewall",
    "timestamp": "2025-06-02T14:20:00Z",
    "ip_addresses": "192.168.1.10"
  },
  {
    "alert_id": "evt-12345",
    "priority": "high",
    "source": "Firewall",
    "timestamp": "2025-06-02T14:20:00Z",
    "ip_addresses": "10.0.0.5"
  },
  {
    "alert_id": "evt-12345",
    "priority": "high",
    "source": "Firewall",
    "timestamp": "2025-06-02T14:20:00Z",
    "ip_addresses": "172.16.0.3"
  }
]

Walking Through the Process

To unwind the ip_addresses array while preserving root-level contextual information, configure the Unwind task as follows:

Group 77.png
  1. Specify the path to the JSON data that contains the array field to be deconstructed. This ensures that the fields at this level are preserved in the resulting data structure.

  2. Provide the relative path to the array field to be deconstructed. In this case, use $.ip_addresses, which refers to the ip_addresses array located at the root of the object at the $.PlaybookData.Data.returnData path.

RESULT

The Unwind task will not only create a separate object for each value unwound from the ip_addresses array but also retain all root-level fields returned by the path $.PlaybookData.Data.returnData.

Group 60.png

All root-level fields and their values are in the final data structure:

(tick) "alert_id": "evt-12345"

(tick) "priority": "high"

(tick) "source": "Firewall"

(tick) "timestamp": "2025-06-02T14:20:00Z"

Inspecting Downstream Task Executions

All tasks downstream of an Unwind task execute once for each item deconstructed from the array. This is because the Unwind task converts an array into multiple individual objects—one per unwound element.

Group 38.png

In the example above, downstream tasks executed or were suggested three times because the Unwind task deconstructed the ip_addresses array, which contained three items.

Group 42 (2).png

Tasks downstream of an Unwind task execute once per unwound item, whether or not they take any input. For example, Stage tasks take no input but are still executed or suggested for execution n times when following an Unwind task, as each run follows a separate parallel path.

Group 39.png

Users can view individual executions of downstream tasks as follows. In this example, the Output Data task displays each IP address that was unwound from the ip_addresses array (extracted from the Data task).

Group 84.png
  1. Click the task status icon of a downstream task.

    Group 85.png
  2. In the top-right corner, click the {number} – {task status} dropdown.

    Group 86.png
  3. Select a specific execution instance.

    Group 87.png
Task Execution Instance - 1: Return Data

The Output Data task returns the IP address 192.168.1.10, unwound from the ip_addresses array.

Group 88.png
Task Execution Instance - 2: Return Data

The Output Data task returns the IP address 10.0.0.5, unwound from the ip_addresses array.

Group 89.png
Task Execution Instance - 3: Return Data

The Output Data task returns the IP address 172.16.0.3, unwound from the ip_addresses array.

Group 90.png

Recombining Execution Paths

Using an Unwind task causes downstream tasks to execute multiple times, creating multiple parallel execution paths. These paths often need to be recombined to consolidate results or pass aggregated data to subsequent tasks.

Vector (2).png

The Merge task node can consolidate multiple execution paths created downstream of an Unwind task back into a single path.

WITHOUT MERGE TASK

Without a Merge task node, the Stage task runs once for each execution path, leading to multiple parallel execution paths.

Group 82.png

WITH MERGE TASK

Including a Merge task node in the execution path consolidates the parallel branches created by the Unwind task before proceeding to the Stage task.

Group 81.png

READER NOTE

For more information about the Merge task node, refer to this article.

Use Case Examples

Example 1: Executing IP Reputation Checks Separately for Each Array Element

SCENARIO An event containing three IP addresses is ingested, and their reputations must be assessed individually while preserving root-level contextual information. The Unwind task deconstructs the addresses, enabling separate reputation checks for each.

READER NOTE

This example assumes the incoming event data contains an array of IP addresses. The steps should be adjusted as necessary to match the structure of the data being used.

  1. Click the Test Playbook button to create a data source, ensuring the trigger output fields for the event containing three IP addresses are available for dynamic input selection.

    Group 4 (1).png
    Add an Unwind task node to the On Event Ingestion trigger.

    Group 28.png
  2. Name the task Unwind IP Addresses, then select the Auto Run checkbox.

    Group 29.png
  3. Provide the input for the JSON Data parameter.

    Group 30.png
    1. Enable the Dynamic toggle.

    2. Click the Anno ellipses.png icon.

    3. Select the JSON path located at Trigger > data > Data.

    4. Click the Save button.

  4. Provide the input for the JSON Path of Array Field parameter.

    Group 31.png
    1. Click the Test button to inspect the JSON data structure.

    2. Identify the array field to be deconstruction.

    3. Enter the corresponding JSON path (e.g., $.ip_addresses).

  5. Click the unwind node checkmark.png button to save.

    Group 32.png
  6. Click the Group 125.png button to test the Unwind IP Addresses task.

    Group 33.png

    This generates task outputs that can be referenced by downstream tasks.

  7. Add a Check IP Reputation Command task (for example, one from AlienVault OTX) to the preceding task node.

    add alien check ip.gif
  8. Name the task, ensure that the Testable option is selected, then click the Next button.

    Group 34.png
  9. Provide the input for the IP Addresses parameter.

    Group 35.png
    1. Click the Anno ellipses.png icon.

    2. Click the Frame 2.png icon.

    3. Select the JSON path located at Unwind IP Addresses > contextData > data > ip_addresses.

    4. Click the Generate button.

    5. Click the Save button.

  10. Choose a valid connection, select the Auto Run checkbox, then click the command node checkmark.png button to save.

    Group 36.png
  11. Click the Group 125.png button to test the Command task.

    Group 37.png

RESULT

If the Command task executed successfully, users can observe that the reputation command executed once per unwound IP address.

Group 43.png

Clicking the task status icon will display the following:

  • A dropdown in the top-right corner indicating the specific instance of the task execution and its status (e.g., 1 - Done, 2 - Done, etc.)

    Group 46.png
  • The IP Addresses field in the Input section containing only one value

    Group 48.png

These indicators confirm that the task executed once for each object returned by the Unwind task.

Example 2: Handling Unwound Artifact Data by Observable Type

SCENARIO An analyst needs to route artifact data through different execution paths based on the type of each artifact. The following example demonstrates how to accomplish this using an Unwind task and Conditional task.

READER NOTE

The Unwind task receives its input from a Data Formatter task that returns a JSON array containing five objects—each representing a different type of artifact.

Group 50.png

To follow along with the example, users should add a Data Formatter task and:

Group 63.png
  1. Name it Extract Artifact Data.

  2. Copy the JSON data below and paste it into the code editor:

    JSON
    [
      {
        "IP": "45.83.91.210"
      },
      {
        "Hash": "e99a18c428cb38d5f260853678922e03"
      },
      {
        "User": "admin@corp-secure-login.com"
      },
      {
        "Email": "alert@account-verification.com, billing@secure-check.com, login@security-alerts.org, update@user-access.net, notify@webmail-center.info, helpdesk@secure-access.io, support@credential-update.biz"
      },
      {
        "URL": "http://corp-login-alert.com, http://verify-user-access.net"
      }
    ]
  1. Click the Test Playbook button to ensure that the outputs of the Extract Artifact Data task are available for dynamic input selection.

    Group 2 (1).png

  2. Add an Unwind task node to the Extract Artifact Data task.

    Group 64.png
  3. Name the task Unwind Artifact Data, then select the Auto Run checkbox.

    Group 65.png
  4. Provide the input for the JSON Data parameter.

    Group 66.png
    1. Enable the Dynamic toggle.

    2. Click the Anno ellipses.png icon.

    3. Select the JSON path located at Extract Artifact Data > returnData.

    4. Click the Save button.

  5. Click the unwind node checkmark.png button to save.

    Group 67.png
  6. Click the Group 125.png button to execute the Unwind task.

    Group 68.png
  7. Add a Conditional task node to the Unwind Artifact Data task.

    Frame 70.png
  8. Name the task Check Artifact Type, ensure that the Testable option is selected, then click the Next button.

    Group 69.png
  9. Select the Auto Run checkbox, then navigate to the Condition Settings tab.

    Group 70.png
  10. Select the Dynamic Input option, then copy and paste the code below into the code editor.

    Group 71 (1).png
    CODE
    {# 
      Runs once per artifact object from the Unwind task.
      Each condition checks if the current object contains a value for a specific field.
      If a value is found, the corresponding label is returned.
    #}
    
    {% if PlaybookData | jsonpath('$.["Unwind Artifact Data"].contextData.data[*].IP') %}
    IP
    {% elif PlaybookData | jsonpath('$.["Unwind Artifact Data"].contextData.data[*].Hash') %}
    Hash
    {% elif PlaybookData | jsonpath('$.["Unwind Artifact Data"].contextData.data[*].User') %}
    User
    {% elif PlaybookData | jsonpath('$.["Unwind Artifact Data"].contextData.data[*].Email') %}
    Email
    {% elif PlaybookData | jsonpath('$.["Unwind Artifact Data"].contextData.data[*].URL') %}
    URL
    {% endif %}

    This block runs once for each object produced by the Unwind task. It checks whether the current object contains a value for one of the known artifact types: IP, Hash, User, Email, or URL. If a value is found, the corresponding conditional branch is activated.

  11. Navigate to the Branch Settings tab, click the + Add Branch button, and add branches for IP, Hash, User, Email, and URL.

    Group 72.png

    Ensure that the branch names are entered exactly as shown.

  12. Click the conditional node checkmark.png button to save.

    Group 73.png
  13. Add a Stage task to each branch.

    Group 75 (1).png

    This verifies that all branches follow the correct execution path and that execution does not stop at the first matching condition.

  14. Click the Test Playbook button to view the execution flow.

    Group 2 (1).png

RESULT

The Conditional task evaluates each artifact individually and activates the matching execution path based on its type, rather than stopping at the first match. Using a Conditional task alongside an Unwind task is particularly effective when different reputation check commands must be applied to different artifact types.

Group 76.png

Also note that configuring tasks in this manner does not result in multiple parallel executions of the same downstream task.

Example 3: Separating Email Recipients to Generate Reports

SCENARIO Three employees receive a suspicious email in Outlook. An analyst can use the Unwind task to deconstruct the toRecipients field, to create an Excel sheet listing all affected individuals along with relevant event details.

READER NOTE

This example assumes that a D3 event was created in response to a suspicious Office 365 email sent to multiple recipients.

  1. Click the Test Playbook button to create a data source, ensuring the trigger output fields for the Office 365 event are available for dynamic input selection.

    Group 4 (1).png

  2. Add an Unwind task node to the On Event Ingestion trigger.

    Group 9 (4).png
  3. Name the task Unwind Recipients, then select the Auto Run checkbox.

    Group 10 (4).png
  4. Provide the input for the JSON Data parameter.

    Group 11 (4).png
    1. Enable the Dynamic toggle.

    2. Click the Anno ellipses.png icon.

    3. Select the JSON path located at Trigger > data > Data.

    4. Click the Save button.

  5. Provide the input for the JSON Path of Array Field parameter.

    Group 12 (3).png
    1. Click the Test button to inspect the JSON data structure.

    2. Identify the array field to be deconstruction.

    3. Enter the corresponding JSON path (e.g., $.toRecipients).

  6. Click the unwind node checkmark.png button to save.

    Group 13 (3).png
  7. Click the Group 125.png button to test the Unwind Recipients task.

    Group 14.png

    This generates task outputs that can be referenced by downstream tasks.

  8. Add a Data Formatter task to the previous task node.

    Group 15.png

    This task will be used to convert unwound recipient data into a flat JSON array for reporting.

  9. Name the task Flatten Recipient Data, then select the Auto Run checkbox.

    Group 16.png
  10. Enter the code below (supplemented with comments) in the code editor.

    CODE
    {# Extracts the unwound recipient data array from the playbook output #}
    {% set data = PlaybookData | jsonpath('$.["Unwind Recipients"].contextData.data') %}
    [
    
    {# Iterates through each recipient object in the unwound data array #}
    {% for item in data %}
      {
        {# Extracts the recipient's email address #}
        "recipient_email": "{{ item.toRecipients.emailAddress.address }}",
    
        {# Extracts the email subject from the original message #}
        "subject": "{{ item.originalEmail[0].detail.item.subject | default('') }}",
    
        {# Extracts the sender's display name #}
        "sender_name": "{{ item.originalEmail[0].detail.item.sender.emailAddress.name | default('') }}",
    
        {# Extracts the sender's email address #}
        "sender_email": "{{ item.originalEmail[0].detail.item.sender.emailAddress.address | default('') }}",
    
        {# Extracts the email's sent timestamp #}
        "sent_time": "{{ item.originalEmail[0].detail.item.sentDateTime | default('') }}"
      }
    
      {# Adds a comma between JSON objects, except after the last item #}
      {% if not loop.last %},{% endif %}
    {% endfor %}
    
    ]

    This generates a flat JSON array by extracting key email fields for each unwound recipient.

  11. Click the dataformatter node checkmark.png button to save.

    Group 17 (1).png
  12. Click the Group 125.png button to test the Flatten Recipient Data task.

    Group 18.png
  13. Add a Convert JSON Array to CSV Command task to previous task node.

    add convert json array to csv.gif
  14. Name the task, ensure that the Testable option is selected, then click the Next button.

    Group 20.png
  15. Provide the input for the JSON Array to Convert parameter.

    Group 21.png
    1. Enable the Dynamic toggle.

    2. Click the Anno ellipses.png icon.

    3. Select the JSON path located at Flatten Recipient Data > returnData.

    4. Click the Save button.

  16. Select the Auto Run checkbox, then click the command node checkmark.png button to save.

    Group 22.png
  17. Click the Group 125.png button to test the Convert JSON Array to CSV task.

    Group 23.png

RESULT

If the Convert JSON Array to CSV task executed successfully, users can click the Frame 3.png icon and navigate to the Results tab to access the CSV download link. Clicking the link downloads the CSV file for viewing.

Group 27.png
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.