Automations

Steps

Steps and their properties in automation workflows.

How it works

Steps are the building blocks of automation workflows. They define the actions that will be executed when the automation runs.

The following steps are available:

Step properties

Every step in an automation has the following base properties:

keystringrequired

A unique identifier for the step. Used in connection definitions to connect steps.

typestringrequired

The type of step. Possible values: trigger, send_email, delay, wait_for_event, condition, split, contact_update, contact_delete, add_to_segment.

configobjectrequired

The configuration object for the step. The shape depends on the step type.

Below is a list of all the possible step types and their configurations.

trigger

The trigger step starts the automation when a matching event is received.

config.event_namestringrequired

The name of the event that triggers the automation.

{
  "key": "start",
  "type": "trigger",
  "config": {
    "event_name": "user.created"
  }
}

send_email

Sends an email using a template.

config.templateobjectrequired

The published template to send. Provide id and optionally variables.

config.template.idstringrequired

The ID or alias of the template to send.

config.template.variablesobjectoptional

A key-value map of template variables. Each value can be a static string or a variable reference object ({ "var": "event.fieldName" }) that resolves dynamically from the event.*, contact.*, or wait_events.* namespaces.

config.fromstringoptional

The sender email address. If provided, this value will override the template's default value.

config.subjectstringoptional

The email subject line. If provided, this value will override the template's default value.

config.reply_tostringoptional

Reply-to email address. If provided, this value will override the template's default value.

{
  "key": "welcome",
  "type": "send_email",
  "config": {
    "template": {
      "id": "062f8ef4-fbfa-44f1-b5e0-ff8e1e8ffa96",
      "variables": {
        "name": { "var": "event.firstName" }
      }
    },
    "from": "hello@example.com",
    "subject": "Welcome!",
    "reply_to": "support@example.com"
  }
}

delay

Pauses execution for a specified duration.

config.durationstringrequired

The delay duration in natural language (e.g. "1 hour", "3 days"). Maximum: 30 days.

{
  "key": "wait_1_hour",
  "type": "delay",
  "config": {
    "duration": "1 hour"
  }
}

wait_for_event

Pauses execution until a specific event is received or a timeout is reached.

config.event_namestringrequired

The name of the event to wait for.

config.timeoutstringoptional

The maximum time to wait before timing out (e.g. "3 days", "1 hour"). Maximum: 30 days.

config.filter_ruleobjectoptional

An optional rule object to filter incoming events.

{
  "key": "wait_for_purchase",
  "type": "wait_for_event",
  "config": {
    "event_name": "purchase.completed",
    "timeout": "3 days"
  }
}

condition

Branches the workflow based on rules. Condition configs can be a single rule or a logical group (and/or) of rules.

config.typestringrequired

The type of condition node: rule, and, or or.

config.fieldstringrequired

For rule type — the field to evaluate. Must use the event. or contact. namespace prefix (e.g. event.amount, contact.email).

config.operatorstringrequired

For rule type — the comparison operator: eq, neq, gt, gte, lt, lte, contains, starts_with, ends_with, exists, is_empty.

config.valuestring | number | boolean | nulloptional

For rule type — the value to compare against. Not required for exists and is_empty operators.

config.rulesobject[]optional

For and / or types — an array of nested condition config objects. Must contain at least one item.

Single rule
{
  "key": "check_plan",
  "type": "condition",
  "config": {
    "type": "rule",
    "field": "event.plan",
    "operator": "eq",
    "value": "pro"
  }
}
Combined rules
{
  "key": "check_plan_and_amount",
  "type": "condition",
  "config": {
    "type": "and",
    "rules": [
      { "type": "rule", "field": "event.plan", "operator": "eq", "value": "pro" },
      { "type": "rule", "field": "event.amount", "operator": "gte", "value": 100 }
    ]
  }
}

split

A/B split: randomly routes contacts between two branches by percentage. Assignment is deterministic per contact+step (re-runs keep the same branch). Branch A rides the condition_met edge, branch B condition_not_met.

config.percentnumberrequired

Share of contacts taking branch A, an integer from 1 to 99.

{
  "key": "ab",
  "type": "split",
  "config": {
    "percent": 50
  }
}

contact_update

Updates a contact's fields. Each field value can be either a hardcoded value or a dynamic variable reference using the { "var": "..." } syntax, with the event.* or contact.* scope.

config.first_namestring | objectoptional

The contact's first name. Accepts a hardcoded string or a variable reference.

config.last_namestring | objectoptional

The contact's last name. Accepts a hardcoded string or a variable reference.

config.unsubscribedboolean | objectoptional

The contact's unsubscribed status. Accepts a boolean or a variable reference.

config.propertiesobjectoptional

A map of custom contact properties to update. Each value can be a hardcoded value (string, number, boolean) or a variable reference.

{
  "key": "update_contact",
  "type": "contact_update",
  "config": {
    "properties": {
      "company": { "var": "event.company" },
      "vip": true
    }
  }
}

contact_delete

Deletes the contact from the audience. This step does not require any configuration fields. Pass an empty object {} as the config.

{
  "key": "remove_contact",
  "type": "contact_delete",
  "config": {}
}

add_to_segment

Adds the contact to a segment.

config.segment_idstringrequired

The ID of the segment to add the contact to.

{
  "key": "add_to_vip",
  "type": "add_to_segment",
  "config": {
    "segment_id": "83a1e324-26dc-47eb-9b28-ba8b6d1fe808"
  }
}