Skip to main content

What is a Condition?

A Condition step evaluates a field in the pipeline context and branches the automation into two paths:
  • Then — steps that run when the condition is true
  • Otherwise — steps that run when the condition is false (optional)
If a branch has no steps, it is skipped. The pipeline continues after the condition with any remaining steps.

Configuration

Every condition has three fields:

Field

The field path references any value in the pipeline context. Common paths:

Operators

Value

The value you compare against. How you enter it depends on the operator: The value field automatically parses JSON. If you type 3, it’s treated as the number 3. If you type true, it’s treated as boolean true. If you need the literal string "true", wrap it in quotes: "true".

Branching

Then (on true)

Steps added to the Then branch run only when the condition evaluates to true. You can add any step type inside a branch — Transform, Destination, Upsert Contact, or even another Condition.

Otherwise (on false)

Steps added to the Otherwise branch run only when the condition evaluates to false. This branch is optional. If you leave it empty, the pipeline simply skips it and continues.

After the condition

Any steps placed after the condition step in the main pipeline run regardless of which branch was taken. Use this for steps that should always execute.

Nesting Conditions

You can place a Condition inside another Condition’s branch to create multi-level logic. Nesting is limited to 2 levels deep.
This example:
  1. First checks if the call completed
  2. If yes, checks whether the rating was low
  3. Sends different notifications depending on the outcome

Common Patterns

Route by call status

Branch on whether the call was successful:
  • Field: call.status
  • Operator: eq
  • Value: completed
  • Then: Sync results to CRM, send follow-up email
  • Otherwise: Alert the team to retry or follow up manually

Route by call outcome

Use structured data fields from your Script to route based on what happened during the call:
  • Field: call.structured_data.appointment_booked
  • Operator: eq
  • Value: true
  • Then: Send confirmation email, update CRM status to “Booked”
  • Otherwise: Send nurture email, update CRM status to “Follow up”

Flag low ratings

Alert your team when a customer gives a low satisfaction score:
  • Field: call.structured_data.rating
  • Operator: lte
  • Value: 2
  • Then: SMS to team with call summary, email to customer success manager
  • Otherwise: (skip)

Check for missing data

Only proceed if a required field exists:
  • Field: contact.email
  • Operator: exists
  • Then: Send follow-up email to contact
  • Otherwise: (skip — no email available)

Route by end reason

Branch based on how the call ended — useful for distinguishing voicemail from hangups:
  • Field: call.end_reason
  • Operator: eq
  • Value: voicemail
  • Then: Sync to CRM as “Left voicemail”, schedule retry
  • Otherwise: (skip)

Route by multiple values

Check if the call ended in one of several statuses:
  • Field: call.status
  • Operator: in
  • Value: ["User unavailable", "rang-out", "failed"]
  • Then: Schedule a retry call via webhook
  • Otherwise: (skip — call was answered)

Escalate based on a threshold

If the call lasted less than 30 seconds, it likely didn’t go well:
  • Field: call.duration
  • Operator: lt
  • Value: 30
  • Then: SMS to team — “Very short call with {{contact.full_name}} ({{call.duration}}s). May need manual follow-up.”
  • Otherwise: (skip)

Branch by trigger data

Route differently based on data from the incoming webhook:
  • Field: trigger.priority
  • Operator: eq
  • Value: high
  • Then: Create Call immediately using priority Script
  • Otherwise: Create Call using standard Script

Tips

  • Keep conditions simple. One condition checking one field is easier to debug than nested logic. If you find yourself nesting 2 levels deep, consider whether two separate automations would be clearer.
  • Check the Execution Log. When a condition branch is not taken, the log shows that branch as “Skipped” in grey. This makes it easy to verify your conditions are evaluating as expected.
  • Use exists before accessing optional data. If a field might not be present (e.g., contact.email for contacts without an email), use an exists condition before steps that depend on it.
  • Types are sorted out for you. Values carry their type through the pipeline, and a comparison converts them to match where it sensibly can. A structured data field holding the text "4" still compares correctly against the number 4, and the text "true" still compares correctly against true. The same applies to values used in templates and integration requests. If you genuinely need to compare the literal text rather than the number, wrap it in quotes.
  • The in operator expects a JSON array. Enter the value as ["option1", "option2"] with square brackets and quotes around strings.