Reorganizing by Feature sections
Capabilities folders to give an overview of each feature
How-Tos folders to give guidance for advanced customizations
Reorganized the Developers section as well, moving the API sub section
there
added some new visuals and videos to illustrate the How-Tos articles
checked the typos, the links and added a section at the end of the
doc.json file to redirect existing links to the new ones (SEO purpose +
continuity of the user experience)
What I have not updated is the "l" folder that, per my understanding,
contains the translation of the User Guide - that I only edited in
English
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> <sup>[Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) is
generating a summary for commit
5301502a32. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Abdul Rahman <ar5438376@gmail.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
178 lines
5.0 KiB
Plaintext
178 lines
5.0 KiB
Plaintext
---
|
|
title: Use Iterator
|
|
description: Loop through arrays of records to perform actions on each item.
|
|
image: /images/user-guide/workflows/workflow.png
|
|
---
|
|
|
|
Iterator lets you loop through an array of records and perform actions on each one. It's essential for workflows that need to process multiple records returned by Search Records or received via webhooks.
|
|
|
|
<Note>
|
|
Iterator is currently in beta. Activate it under **Settings → Releases → Lab**.
|
|
</Note>
|
|
|
|
## When to Use Iterator
|
|
|
|
| Scenario | Example |
|
|
|----------|---------|
|
|
| **Process search results** | Send email to each person found |
|
|
| **Handle webhook arrays** | Create records for each item in order |
|
|
| **Bulk updates** | Update multiple records with calculated values |
|
|
| **Notifications** | Alert multiple people about an event |
|
|
|
|
## Understanding Iterator
|
|
|
|
Iterator expects an **array** as input. It then:
|
|
1. Takes the first item from the array
|
|
2. Runs all actions inside the iterator with that item
|
|
3. Moves to the next item
|
|
4. Repeats until all items are processed
|
|
|
|
## Basic Setup
|
|
|
|
### Example: Email Everyone in Search Results
|
|
|
|
**Goal**: Find all contacts in a specific company and send each one a personalized email.
|
|
|
|
### Step 1: Search for Records
|
|
|
|
1. Add **Search Records** action
|
|
2. Object: **People**
|
|
3. Filter: Company equals "Acme Inc"
|
|
4. This returns an array of people
|
|
|
|
### Step 2: Check Results Exist
|
|
|
|
1. Add **Filter** action
|
|
2. Condition: `{{searchRecords.length}}` is greater than 0
|
|
3. This prevents Iterator errors on empty results
|
|
|
|
### Step 3: Add Iterator
|
|
|
|
1. Add **Iterator** action
|
|
2. Array input: Select `{{searchRecords}}`
|
|
3. This creates a loop
|
|
|
|
### Step 4: Add Actions Inside Iterator
|
|
|
|
Actions placed after Iterator run for each item:
|
|
|
|
1. Add **Send Email** action (inside iterator)
|
|
2. To: `{{iterator.currentItem.email}}`
|
|
3. Subject: Hello `{{iterator.currentItem.firstName}}`!
|
|
4. Body: Personalized message using current item fields
|
|
|
|
### Result
|
|
|
|
If Search Records returns 5 people, the Iterator:
|
|
- Sends email to person 1
|
|
- Sends email to person 2
|
|
- ... continues for all 5
|
|
|
|
## Accessing Current Item Data
|
|
|
|
Inside Iterator, use `{{iterator.currentItem}}` to access the current record:
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `{{iterator.currentItem}}` | The entire current record object |
|
|
| `{{iterator.currentItem.id}}` | Record ID |
|
|
| `{{iterator.currentItem.email}}` | Email field |
|
|
| `{{iterator.currentItem.company.name}}` | Related company name |
|
|
| `{{iterator.index}}` | Current position in array (0-based) |
|
|
|
|
## Common Patterns
|
|
|
|
### Update Multiple Records
|
|
|
|
**Goal**: Mark all overdue tasks as "Late"
|
|
|
|
```
|
|
1. Search Records (Tasks, Due Date < Today, Status ≠ Completed)
|
|
2. Filter (length > 0)
|
|
3. Iterator (searchRecords)
|
|
└── Update Record
|
|
- Object: Tasks
|
|
- Record: {{iterator.currentItem.id}}
|
|
- Status: Late
|
|
```
|
|
|
|
### Create Records from Array
|
|
|
|
**Goal**: Webhook receives order with multiple items, create a record for each
|
|
|
|
```
|
|
1. Webhook Trigger (receives items array)
|
|
2. Filter (items.length > 0)
|
|
3. Iterator (trigger.body.items)
|
|
└── Create Record
|
|
- Object: Order Items
|
|
- Name: {{iterator.currentItem.name}}
|
|
- Quantity: {{iterator.currentItem.qty}}
|
|
- Related Order: {{trigger.body.orderId}}
|
|
```
|
|
|
|
### Conditional Processing Inside Loop
|
|
|
|
**Goal**: Only send email to contacts with valid emails
|
|
|
|
```
|
|
1. Search Records (People)
|
|
2. Iterator (searchRecords)
|
|
└── Filter (currentItem.email is not empty)
|
|
└── Send Email
|
|
- To: {{iterator.currentItem.email}}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### "Iterator expects an array"
|
|
|
|
**Cause**: You passed a single record instead of an array.
|
|
|
|
**Fix**: Make sure you're passing the result of Search Records or an array field, not a single record.
|
|
|
|
```
|
|
✅ Correct: {{searchRecords}}
|
|
❌ Wrong: {{searchRecords[0]}}
|
|
```
|
|
|
|
### Iterator Doesn't Run
|
|
|
|
**Cause**: The array is empty.
|
|
|
|
**Fix**: Add a Filter before Iterator to check array length:
|
|
```
|
|
Filter: {{searchRecords.length}} > 0
|
|
```
|
|
|
|
### Actions Run Too Many Times
|
|
|
|
**Cause**: Search Records returned more records than expected.
|
|
|
|
**Fix**:
|
|
- Add more specific filters to Search Records
|
|
- Set a limit on Search Records (max 200)
|
|
- Add Filter inside Iterator for additional conditions
|
|
|
|
## Performance Considerations
|
|
|
|
- **Credit usage**: Each iteration consumes credits for its actions
|
|
- **Time**: Large arrays take longer to process
|
|
- **Limits**: Consider batching very large operations
|
|
- **Rate limits**: External API calls may hit rate limits with many iterations
|
|
|
|
## Best Practices
|
|
|
|
1. **Always check array length** before Iterator to avoid errors
|
|
2. **Add filters inside loops** when not all items need processing
|
|
3. **Rename your Iterator step** to describe what it's looping through
|
|
4. **Test with small arrays** before processing large datasets
|
|
5. **Monitor workflow runs** to ensure iterations complete as expected
|
|
|
|
## Related
|
|
|
|
- [Workflow Actions](/user-guide/workflows/capabilities/workflow-actions)
|
|
- [How to Use Branches](/user-guide/workflows/capabilities/use-branches-in-workflows)
|
|
- [Workflows FAQ](/user-guide/workflows/how-tos/need-more-help/workflows-faq)
|
|
|