Conditional Execution

Skip or run requests based on previous results.

Overview

Conditional execution allows you to control which requests run based on the results of previous requests. Use the when field to define conditions that must be met for a request to execute.

Flexible

Multiple Operators

Compare values with ==, !=, >, <, contains, matches, exists, and more

Powerful

Compound Conditions

Combine conditions with AND (all) and OR (any) logic

Basic Usage

Add a when field to any request to make it conditional. The request will only execute if the condition evaluates to true.

basic-when.yaml
# Basic conditional execution
requests:
  # First request: Get data and store values
  - name: Get User
    url: https://api.example.com/users/1
    method: GET
    expect:
      status: 200
    store:
      userId: body.id
      userRole: body.role

  # Only runs if userId exists
  - name: Get User Details
    url: https://api.example.com/users/${store.userId}/details
    method: GET
    when:
      left: store.userId
      operator: exists
    expect:
      status: 200

How it works:

  1. First request executes and stores values
  2. Before each subsequent request, the when condition is evaluated
  3. If condition is true, request executes normally
  4. If condition is false, request is skipped (marked as skipped, not failed)

String Shorthand Syntax

For simple conditions, use the string shorthand syntax instead of the full object format. This makes your YAML more readable.

shorthand.yaml
# String shorthand syntax
requests:
  - name: Check Status
    url: https://api.example.com/status
    store:
      code: status
      type: body.type

  # Equality check
  - name: Handle Success
    url: https://api.example.com/success
    when: "store.code == 200"

  # Comparison
  - name: Handle Error
    url: https://api.example.com/error
    when: "store.code >= 400"

  # Exists check
  - name: Process Type
    url: https://api.example.com/process
    when: "store.type exists"
ShorthandEquivalent Object
"store.status == 200"left: store.status, operator: "==", right: 200
"store.userId exists"left: store.userId, operator: exists
"store.count >= 10"left: store.count, operator: ">=", right: 10
"store.name contains admin"left: store.name, operator: contains, right: "admin"

Operators

All available operators for building conditions.

OperatorDescriptionExample
==Equal tostore.status == 200
!=Not equal tostore.status != 404
>Greater thanstore.count > 0
<Less thanstore.count < 100
>=Greater than or equalstore.version >= 2
<=Less than or equalstore.count <= 50
containsString contains substringstore.name contains "admin"
matchesRegex pattern matchstore.email matches "^.+@.+"
existsValue exists and not emptystore.token exists
not-existsValue missing or emptystore.error not-exists
operators.yaml
# Operator reference
requests:
  - name: Get Data
    url: https://api.example.com/data
    store:
      status: status
      count: body.count
      name: body.name
      error: body.error

  # Equality operators
  - name: Check Equal
    url: https://api.example.com/eq
    when:
      left: store.status
      operator: "=="
      right: 200

  - name: Check Not Equal
    url: https://api.example.com/neq
    when:
      left: store.status
      operator: "!="
      right: 404

  # Comparison operators
  - name: Check Greater
    url: https://api.example.com/gt
    when:
      left: store.count
      operator: ">"
      right: 0

  - name: Check Less Or Equal
    url: https://api.example.com/lte
    when:
      left: store.count
      operator: "<="
      right: 100

  # String operators
  - name: Check Contains
    url: https://api.example.com/contains
    when:
      left: store.name
      operator: contains
      right: "admin"

  - name: Check Matches (regex)
    url: https://api.example.com/matches
    when:
      left: store.name
      operator: matches
      right: "^user_\\d+"

  # Existence operators
  - name: Check Exists
    url: https://api.example.com/exists
    when:
      left: store.count
      operator: exists

  - name: Check Not Exists
    url: https://api.example.com/not-exists
    when:
      left: store.error
      operator: not-exists

Compound Conditions

AND Logic (all)

Use all when every condition must be true. Evaluation stops on the first false condition (short-circuit).

all-conditions.yaml
# AND conditions - all must be true
requests:
  - name: Get Feature Flags
    url: https://api.example.com/flags
    store:
      enabled: body.enabled
      version: body.version
      region: body.region

  # Only runs if ALL conditions pass
  - name: Use New Feature
    url: https://api.example.com/new-feature
    when:
      all:
        - left: store.enabled
          operator: "=="
          right: true
        - left: store.version
          operator: ">="
          right: 2
        - left: store.region
          operator: "=="
          right: "us-east"

OR Logic (any)

Use any when at least one condition must be true. Evaluation stops on the first true condition (short-circuit).

any-conditions.yaml
# OR conditions - any must be true
requests:
  - name: Get User
    url: https://api.example.com/user
    store:
      role: body.role

  # Runs if user is admin OR superuser
  - name: Admin Dashboard
    url: https://api.example.com/admin
    when:
      any:
        - left: store.role
          operator: "=="
          right: "admin"
        - left: store.role
          operator: "=="
          right: "superuser"
        - left: store.role
          operator: "=="
          right: "moderator"

Case Sensitivity

String comparisons are case-insensitive by default. Use caseSensitive: true for exact matching.

case-sensitive.yaml
# Case sensitivity control
requests:
  - name: Get User
    url: https://api.example.com/user
    store:
      name: body.name  # "John"

  # Case-insensitive (default) - matches "john", "John", "JOHN"
  - name: Check Name Insensitive
    url: https://api.example.com/check
    when:
      left: store.name
      operator: "=="
      right: "john"

  # Case-sensitive - only matches exact "John"
  - name: Check Name Sensitive
    url: https://api.example.com/check
    when:
      left: store.name
      operator: "=="
      right: "John"
      caseSensitive: true

Common Use Cases

Authentication Flow

Execute authenticated requests only when login succeeds.

auth-flow.yaml
# Authentication flow with conditions
global:
  execution: sequential
  continueOnError: true

requests:
  # Step 1: Try to authenticate
  - name: Login
    url: https://api.example.com/auth/login
    method: POST
    body:
      username: "admin"
      password: "secret"
    store:
      status: status
      token: body.token
      error: body.error

  # Step 2: Only proceed if login succeeded
  - name: Get Protected Data
    url: https://api.example.com/protected
    headers:
      Authorization: Bearer ${store.token}
    when:
      all:
        - left: store.status
          operator: "=="
          right: 200
        - left: store.token
          operator: exists
    expect:
      status: 200

  # Step 3: Handle login failure
  - name: Refresh Token
    url: https://api.example.com/auth/refresh
    method: POST
    when:
      left: store.status
      operator: "!="
      right: 200

Error Handling

Branch execution based on success or error responses.

error-handling.yaml
# Error handling with conditions
global:
  continueOnError: true

requests:
  - name: Create Resource
    url: https://api.example.com/resources
    method: POST
    body:
      name: "Test"
    store:
      status: status
      resourceId: body.id
      errorCode: body.error.code

  # Success path
  - name: Verify Creation
    url: https://api.example.com/resources/${store.resourceId}
    when: "store.status == 201"
    expect:
      status: 200

  # Error path - duplicate
  - name: Handle Duplicate
    url: https://api.example.com/resources/existing
    when:
      all:
        - left: store.status
          operator: "=="
          right: 409
        - left: store.errorCode
          operator: "=="
          right: "DUPLICATE"

  # Error path - validation error
  - name: Handle Validation Error
    url: https://api.example.com/validation-errors
    method: POST
    when: "store.status == 400"

Workflow Branching

Build dynamic workflows with feature flags and rollout percentages.

workflow.yaml
# Complete workflow with branching
global:
  execution: sequential
  continueOnError: true

requests:
  # 1. Check feature flag
  - name: Check Feature
    url: https://api.example.com/features/new-checkout
    store:
      featureEnabled: body.enabled
      rolloutPercent: body.rollout

  # 2a. New checkout flow (if enabled and rollout >= 50%)
  - name: New Checkout
    url: https://api.example.com/checkout/v2
    method: POST
    when:
      all:
        - left: store.featureEnabled
          operator: "=="
          right: true
        - left: store.rolloutPercent
          operator: ">="
          right: 50
    body:
      items: ["item-1", "item-2"]

  # 2b. Legacy checkout (if feature disabled)
  - name: Legacy Checkout
    url: https://api.example.com/checkout/v1
    method: POST
    when:
      left: store.featureEnabled
      operator: "!="
      right: true
    body:
      items: ["item-1", "item-2"]

Important Notes

Sequential Execution Required

Conditional execution only works in sequential mode (the default). In parallel mode, request order is not guaranteed, so conditions based on previous responses won't work as expected.

Skipped Requests Don't Fail

When a condition evaluates to false, the request is skipped and marked as successful. Skipped requests don't count toward failure thresholds in CI mode.

Short-Circuit Evaluation

For all conditions, evaluation stops at the first false. For any conditions, evaluation stops at the first true. This improves performance for complex conditions.

Variable Interpolation

Use ${VAR} syntax in condition values. Variables are resolved before condition evaluation.

Best Practices

Use String Shorthand

For simple conditions, prefer "store.x == y" over the verbose object syntax. It's more readable.

Check Existence First

Before comparing values, ensure they exist. Use exists in all conditions to guard against missing data.

Plan Your Flow

Design your workflow before adding conditions. Ensure data-producing requests come before conditional requests.

Use continueOnError

When building error-handling flows, enable continueOnError to allow conditional error handlers to execute.