Assertions
Expression syntax for validating step results — comparisons, string operators, type checks, and more.
Assertions are boolean expressions that must all evaluate to true for a step to pass. They appear in the assert array on any step, and can also be used as standalone steps with the assert action.
Basic syntax
assert:
- status == 200
- response.body.id existsEach assertion is a string expression. When a flow runs, every assertion in the array is evaluated. If any assertion fails, the step is marked as failed and (by default) the flow stops.
Comparison operators
assert:
- status == 200 # Equal
- status != 404 # Not equal
- count > 0 # Greater than
- price < 100 # Less than
- age >= 18 # Greater than or equal
- score <= 100 # Less than or equalExistence and null checks
assert:
- id exists # Field is present and not null
- user.email exists
- response.body.data exists
- deleted_at is null # Field is null or absent
- error is not null # Field is present and not nullType checks
assert:
- id is number
- name is string
- active is boolean
- tags is array
- metadata is objectString operators
assert:
- email contains "@"
- url starts_with "https://"
- filename ends_with ".pdf"
- content matches "\\d{3}-\\d{4}" # Regex matchmatches uses standard regular expression syntax. Backslashes must be escaped in YAML strings.
Array operators
assert:
- tags contains "important" # Array includes value
- users.length == 10 # Array length equals
- prices.length > 0 # Array is non-emptyBoolean logic
assert:
- status == 200 && body exists # Both must be true
- status == 200 || status == 201 # Either must be true
- !(status >= 400) # Negation
- (status == 200 || status == 201) && response.body.id exists # CombinedAccessing response data
The path used in an assertion depends on the action type.
assert:
- status == 200 # HTTP status code
- response.body.id exists # JSON body field
- response.body.users[0].email exists # Array element field
- response.headers["Content-Type"] contains "json"
- response.time < 1000 # Response time in millisecondsassert:
- result.count > 0 # Number of rows returned
- result.count == 1 # Exact row count
- result.rows[0].email exists # First row field
- result.rows[0].status == "active" # Field equality
- result.rows[0].email_verified == false # Boolean fieldassert:
- result.count > 0 # Messages received
- result.messages[0].value.event_type == "user.created"
- result.messages[0].value.user_id existsassert:
- result.status == "OK" # gRPC status
- result.response.id == "${user_id}" # Response field
- result.response.name existsTime assertions
assert:
- response.time < 1000 # Milliseconds
- created_at > "2024-01-01T00:00:00Z" # ISO 8601 timestampJSONPath assertions
For complex filtering, use JSONPath syntax directly in an assertion:
assert:
- "$.users[?(@.status == 'active')].length > 0" # At least one active user
- "$.products[?(@.price < 100)].length >= 3" # At least 3 products under $100Custom failure messages
Plain string assertions give generic error output. Adding a message field makes failures easier to diagnose.
assert:
- expression: "status == 201"
message: "Expected user creation to return 201 Created"
- expression: "response.body.id exists"
message: "Response must include the new user's ID"
- expression: "response.time < 1000"
message: "Response time must be under 1 second (was ${response.time}ms)"Assertion modes
By default, every assertion in the assert array must pass. Two alternative modes are available for cases where that's too strict.
# Default: all must pass
assert:
- status == 200
- body exists
# At least one must pass
assert_any:
- status == 200
- status == 201
# None should be true (negative assertions)
assert_none:
- status >= 400
- error existsMultiple assertions (all must pass)
When multiple assertions are listed, they are evaluated independently. All must pass. The first failure does not prevent the others from being evaluated — the report shows every failing assertion.
- id: create_user
action: http_request
config:
method: POST
url: "${API_URL}/users"
body:
email: "test@example.com"
assert:
- status == 201
- response.body.id exists
- response.body.email == "test@example.com"
- response.body.token exists
- response.time < 500Standalone assert step
Use the assert action to validate accumulated state at any point in a flow, independently of any specific action.
- id: verify_conditions
action: assert
config:
assertions:
- expression: "${user_id} exists"
message: "User ID is required before placing an order"
- expression: "${status_code} == 200"
message: "Expected status 200"
- expression: "${response_time} < 1000"
message: "Response too slow"