> ## Documentation Index
> Fetch the complete documentation index at: https://darkbanner.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Transform

> Reshape data, loop over collections, gather parallel results, and add delays to your flows

The **Transform** node is the Swiss Army knife of your flow. It operates in four distinct modes — each designed for a different data manipulation pattern. Whether you need to reshape a payload, loop over a list, collect results from parallel branches, or pause execution, the Transform node handles it.

## Modes

> [tab] Message
>
> Reshape and map data from one structure to another.

> [tab] Iterate
>
> Loop over a collection and run downstream nodes once per item.

> [tab] Gather
>
> Collect results from parallel or iterated branches back into a single list.

> [tab] Wait
>
> Pause the flow for a specified duration before continuing.

***

## Message Mode

**Message** is the most common mode. It takes data from previous nodes and reshapes it into a new structure. Use it to extract fields, rename keys, combine data from multiple sources, build API payloads, or set default values.

### How It Works

You define a JSON mapping where each key is the output field name, and each value is either a static value or a template expression that pulls data from upstream nodes.

### Configuration

| Setting | Description |
| - | - |
| **Output Mapping** | A JSON object defining the transformed output. Values support `{{template}}` syntax. |

### Example

A previous Request node (ID `1`, label "Fetch User") returned:

```json theme={null}
{
  "body": {
    "first_name": "Jane",
    "last_name": "Doe",
    "contact": { "email": "jane@acme.com" },
    "metadata": { "tier": "enterprise" }
  }
}
```

Configure the Transform in Message mode:

```json theme={null}
{
  "full_name": "{{1_Fetch User.body.first_name}} {{1_Fetch User.body.last_name}}",
  "email": "{{1_Fetch User.body.contact.email}}",
  "tier": "{{1_Fetch User.body.metadata.tier}}",
  "source": "api_sync"
}
```

This outputs a clean, flat object:

```json theme={null}
{
  "full_name": "Jane Doe",
  "email": "jane@acme.com",
  "tier": "enterprise",
  "source": "api_sync"
}
```

### Common Patterns

> [accordion] Rename fields
>
> Map an external API's naming convention to your internal format:
>
> ```json theme={null}
> {
>   "customer_name": "{{1_API.body.customerName}}",
>   "customer_email": "{{1_API.body.emailAddress}}",
>   "signup_date": "{{1_API.body.createdAt}}"
> }
> ```

> [accordion] Merge data from multiple nodes
>
> Pull fields from different upstream nodes into a single object:
>
> ```json theme={null}
> {
>   "user": "{{1_Lookup User.body.name}}",
>   "order_total": "{{2_Fetch Order.body.total}}",
>   "status": "{{3_Check Status.body.result}}"
> }
> ```

> [accordion] Build an API payload
>
> Prepare a structured body for a downstream Request node:
>
> ```json theme={null}
> {
>   "to": "{{1_Form.form_data.email}}",
>   "subject": "Welcome, {{1_Form.form_data.name}}!",
>   "template": "onboarding_v2",
>   "variables": {
>     "name": "{{1_Form.form_data.name}}",
>     "company": "{{1_Form.form_data.company}}"
>   }
> }
> ```

> [accordion] Set defaults and constants
>
> Mix dynamic and static values:
>
> ```json theme={null}
> {
>   "name": "{{1_Input.body.name}}",
>   "role": "member",
>   "active": true,
>   "region": "us-east-1"
> }
> ```

> [!TIP]
>
> Use a Transform in Message mode before a Request node to cleanly separate "what data do I need" from "where do I send it." This makes your flows easier to debug and modify.

***

## Iterate Mode

**Iterate** takes a list and runs every downstream node once for each item in that list. It turns a single flow execution into a loop, processing each element individually.

### How It Works

You point the Transform at a list from a previous node. For each item in that list, the nodes connected after the Transform execute with that single item as their input. The flow effectively "fans out" — if the list has 50 items, the downstream path runs 50 times.

### Configuration

| Setting | Description |
| - | - |
| **Source List** | A template expression pointing to the array to iterate over (e.g., `{{1_Request.body.users}}`) |

### Example

A Request node fetches a list of 3 users:

```json theme={null}
{
  "body": {
    "users": [
      { "name": "Alice", "email": "alice@acme.com" },
      { "name": "Bob", "email": "bob@acme.com" },
      { "name": "Charlie", "email": "charlie@acme.com" }
    ]
  }
}
```

Set the Transform to Iterate mode with source list `{{1_Request.body.users}}`. The downstream nodes run 3 times — once with Alice's data, once with Bob's, once with Charlie's. Each iteration receives the current item as its input.

### Use Cases

* Sending a personalized email to each contact in a list
* Creating a ticket for every failed check in a batch
* Writing each record from an API response to a data table
* Making an individual API call per item (e.g., enriching each lead)

> [!NOTE]
>
> Iterations run sequentially by default. For large lists, keep downstream operations lightweight or use the failure path to handle individual item errors without stopping the entire loop.

***

## Gather Mode

**Gather** is the counterpart to Iterate. After a fan-out, Gather collects all the individual results back into a single list so the flow can continue with the complete set.

### How It Works

Place a Gather Transform after a section of your flow that was fanned out by an Iterate. The Gather waits for all iterations to complete, then combines their outputs into an array. Downstream nodes receive the full collected result.

### Configuration

| Setting | Description |
| - | - |
| **Source** | The node whose iterated outputs should be collected |

### Example

Continuing the example above:

1. **Iterate** fans out over 3 users
2. For each user, a **Request** node calls an enrichment API and returns additional data
3. **Gather** collects all 3 enrichment results into a single list

The Gather output:

```json theme={null}
[
  { "name": "Alice", "company": "Acme Corp", "title": "Engineer" },
  { "name": "Bob", "company": "Acme Corp", "title": "Designer" },
  { "name": "Charlie", "company": "Acme Corp", "title": "PM" }
]
```

Now a downstream Table node can write all 3 enriched records at once, or a Transform in Message mode can summarize the batch.

### The Iterate → Gather Pattern

This is one of the most powerful patterns in Zygo:

```
Fetch list → Iterate → Process each item → Gather → Continue with results
```

**1. Fetch**

A Request node retrieves a list of items from an API.

**2. Iterate**

A Transform in Iterate mode fans out over the list.

**3. Process**

Each item flows through one or more nodes — enrichment, validation, transformation.

**4. Gather**

A Transform in Gather mode collects all processed items back into a single list.

**5. Continue**

The flow continues with the complete set — write to a table, send a summary, or pass to another system.

> [!TIP]
>
> You can nest Iterate/Gather pairs for multi-level looping — for example, iterating over departments, then iterating over employees within each department.

***

## Wait Mode

**Wait** pauses the flow for a specified duration before continuing to the next node. Use it to add intentional delays — rate limit compliance, polling intervals, or giving an external system time to process before you check the result.

### Configuration

| Setting | Description |
| - | - |
| **Duration** | How long to pause, in seconds |

### Use Cases

> [accordion] API rate limiting
>
> You're calling an external API inside an Iterate loop that has a rate limit of 10 requests per second. Add a Wait node with a 1-second delay between each call to stay under the limit.

> [accordion] Polling for completion
>
> You trigger an async job on an external system, then need to check if it's done. Add a Wait before the status-check Request to give the job time to complete:
>
> 1. **Request** — trigger the job
> 2. **Wait** — pause for 30 seconds
> 3. **Request** — check the job status
> 4. **Condition** — is it done? If not, loop back to Wait

> [accordion] Staggered notifications
>
> Send a sequence of messages with delays between them — a welcome email now, a follow-up in 5 minutes, and a tips email in an hour.

> [accordion] Retry with backoff
>
> After a failed request, wait before retrying. Chain multiple Wait + Request pairs with increasing durations for exponential backoff.

> [!WARNING]
>
> Wait pauses the flow execution in the background job queue. Very long wait durations (hours) tie up a worker — for long delays, consider using a scheduled flow instead of a Wait node.

***

## Output

Regardless of mode, downstream nodes reference the Transform's output using the standard template syntax:

```
{{2_Transform.field_name}}
```

| Mode | Output |
| - | - |
| **Message** | The JSON object you defined in the mapping |
| **Iterate** | The current item from the list (available to nodes within the loop) |
| **Gather** | An array containing all collected results |
| **Wait** | Passes through the input data unchanged |

## Choosing the Right Mode

| I need to... | Use |
| - | - |
| Reshape or restructure data | **Message** |
| Process each item in a list individually | **Iterate** |
| Collect iterated results back into a list | **Gather** |
| Pause before the next step | **Wait** |
| Rename fields or build a payload | **Message** |
| Send an email to every user in a list | **Iterate** |
| Summarize results after a loop | **Gather** |
| Respect an API's rate limit | **Wait** |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.