
Loop Over Items and Branch in an API Test
Short answer: use a for-each node to run a request once per item in an array returned by an earlier response, and a condition node to send the flow down a Then or Else path based on a status code or body value. A break condition lets a loop stop before it reaches the end of the array.
This guide walks through each piece with the examples from the DevTools flows documentation, so every node and setting below is one you can find on that page.
The short version: for-each, condition, break
In a DevTools flow, three node types cover most looping and branching needs in an API test. The For-Each node iterates over an array of items from a previous response. The Condition node adds if/else logic. A loop node can also carry an optional break condition that exits early.
The usual shape of the work is short. Call an endpoint that returns a list, the same chaining of requests that any multi-step test relies on. Point a for-each node at that list and name the request that should run for each item. Put a condition after any request whose result decides what happens next. Add a break condition when the loop should stop before the list is finished.
The sections below take those in turn, then cover the fixed-count for loop, error policy and running the flow from the CLI.
Loop over an array from one response with for-each
The for-each node needs two settings. The items expression is the path to the array, for example {{GetUsers.response.body}}, and the loop target is the node to execute for each item.
Inside the loop you read the current item and its position. The docs name them {{ForEachName.item}} for the current item and {{ForEachName.index}} for the current index. Replace ForEachName with the name you gave the loop node.
The docs show the YAML for a three-step flow: fetch the users, loop over them, and update each one. The loop step looks like this.
- for_each:
name: ProcessUsers
items: '{{GetUsers.response.body}}'
loop: UpdateUser
The request that the loop runs reads fields from the current item through the loop's name. In the docs example, the update request builds its URL from {{ProcessUsers.item.id}}.
url: https://api.example.com/users/{{ProcessUsers.item.id}}
Two details are worth keeping straight. The loop's name is the prefix for the variables, so renaming the loop means renaming every reference. The loop value points at the request node that runs once per item, which is why the update request is defined as its own step.
Repeat a request a fixed number of times with a for loop
When there is no array to drive the iteration, use the For Loop node. It executes a sequence of nodes a fixed number of times. The YAML in the docs sets the count with iter_count.
- for:
name: FetchUsers
iter_count: 5
loop: GetUserById
The loop exposes its position as {{LoopName.index}}, which counts from zero. That makes the index a natural way to walk through numbered resources, or to repeat one call a set number of times.
Choose between the two by the data you have. If an earlier response gives you the list, for-each follows the list wherever it ends. If you know the count in advance, the for loop says so directly.
Branch on a status code or body value with a condition
A condition node branches execution based on a boolean expression. It has a Then target for when the expression is true and an Else target for when it is false, and the Else target is optional.
The docs give expressions for the two checks that matter most in API tests, the status code and a value in the body. For more patterns on asserting those values, see assertions in YAML.
// Check response status
GetUser.response.status == 200
// Check response body
Login.response.body.success == true
Checks can be combined with &&. The docs show a status check joined to a body check on the same response, so a branch only fires when the call succeeded and returned something.
GetUsers.response.status == 200 && GetUsers.response.body.length > 0
On the canvas, a condition node has two output handles, Then and Else. The docs sketch a condition after a request, with a processing node on the Then side and an error handler on the Else side.
[GetUser] → [CheckStatus]
├─ Then → [ProcessUser]
└─ Else → [HandleError]
That pattern is also the docs' suggestion for error handling: use condition nodes to handle errors gracefully. In a test, the Else side is where you put the step that records or reacts to an unexpected response.
Exit a loop early and choose what happens on error
A loop can carry a break condition, an optional condition that exits the loop early. Use it when the remaining iterations no longer matter, for example once a response shows the thing you were searching for.
Errors inside a loop have their own setting, the error policy. It has two values. Ignore continues on error, and Break stops the loop on error. For a test that must report every failing item, continuing through the list shows you all of them in one run. For a test where one failure makes the rest meaningless, stopping at the first one saves time.
On the canvas, a loop node has two output handles: one for the loop target and one for the next node after the loop. The next node runs after the loop and is where a final condition or summary step belongs.
The docs page shows the settings for the break condition and the error policy, but no YAML for them. Set them on the node in the editor and check the saved file instead of guessing the keys.
Keep the flow in YAML and run it from the CLI
Flows can be loaded from YAML files, which the docs describe as useful for version control and CI/CD. That keeps a loop test reviewable: the for-each and the request it runs sit in a file that a pull request can diff.
From the command line, the docs run a YAML flow with this command.
devtools flow run my-flow.yaml
To run the same file on every pull request, see the GitHub Actions workflow guide. The flows documentation also lists the other node types, such as sub-flows and waits, that you can combine with loops.
Studio and the CLI are free, run on your own machine and in your own CI, and need no account.
Conclusion
Looping and branching come down to a few nodes. Use for-each to run a request per item of a response, a for loop when the count is fixed, a condition for the Then and Else paths, and a break condition or error policy to control when a loop stops. Start with the docs examples, run the flow, and adapt the names and expressions to your API.
Common questions
Can a for-each loop read fields from the current item?
Yes. The current item is available as {{ForEachName.item}}, and the docs example reads its id field with {{ProcessUsers.item.id}}.
Is the Else branch of a condition required?
No. A condition has a Then target and an optional Else target.
What is the difference between a for loop and a for-each loop?
A for loop executes nodes a fixed number of times, while a for-each loop iterates over an array of items from a previous response.
What does the Break error policy do?
It stops the loop when an iteration errors. The other value, Ignore, continues on error.
