Skip to main content
Automations are currently in private alpha and only available to a limited number of users. APIs might change before GA.To use the methods on this page, you must upgrade your Resend SDK:
npm install resend@6.10.0-preview-workflows.3
Contact us if you’re interested in testing this feature.

Step properties

Every step in an automation has the following base properties:
ref
string
required
A unique reference identifier for the step. Used in edge definitions to connect steps.
type
string
required
The type of step. Possible values: - trigger - send_email - delay - wait_for_event - condition - contact_update - contact_delete - add_to_segment
config
object
required
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_name
string
required
The name of the event that triggers the automation.
{
  "ref": "trigger",
  "type": "trigger",
  "config": {
    "event_name": "user.created"
  }
}

send_email

Sends an email using a template.
config.template_id
string
required
The ID of the email template to send.
config.subject
string
The email subject line.
config.from
string
The sender email address.
config.reply_to
string
Reply-to email address.
config.variables
object
A key-value map of template variables.
{
  "ref": "welcome_email",
  "type": "send_email",
  "config": {
    "template_id": "062f8ef4-fbfa-44f1-b5e0-ff8e1e8ffa96",
    "subject": "Welcome!",
    "from": "hello@example.com"
  }
}

delay

Pauses execution for a specified duration.
config.seconds
number
required
The delay duration in seconds.
Example
{
  "ref": "wait_1_hour",
  "type": "delay",
  "config": {
    "seconds": 3600
  }
}

wait_for_event

Pauses execution until a specific event is received or a timeout is reached.
config.event_name
string
required
The name of the event to wait for.
config.timeout_seconds
number
The maximum time to wait in seconds before timing out.
config.filter_rule
object
An optional rule object to filter incoming events.
Example
{
  "ref": "wait_for_purchase",
  "type": "wait_for_event",
  "config": {
    "event_name": "purchase.completed",
    "timeout_seconds": 86400
  }
}

condition

Branches the workflow based on rules. Condition configs can be a single rule or a logical group (and/or) of rules.
config.type
string
required
The type of condition node. Possible values:
  • rule
  • and
  • or
For rule type:
config.field
string
required
The field to evaluate. Must use the event. or contact. namespace prefix (e.g., event.amount, contact.email).
config.operator
string
required
The comparison operator. Possible values:
  • eq: equals
  • neq: not equals
  • gt: greater than
  • gte: greater than or equal to
  • lt: less than
  • lte: less than or equal to
  • contains: contains a given value
  • starts_with: starts with a given value
  • ends_with: ends with a given value
  • exists: field exists
  • is_empty: field is empty
config.value
string | number | boolean | null
The value to compare against. Not required for exists and is_empty operators.
For and / or types:
config.rules
object[]
required
An array of nested condition config objects. Must contain at least one item.
Single rule example:
{
  "ref": "check_plan",
  "type": "condition",
  "config": {
    "type": "rule",
    "field": "event.plan",
    "operator": "eq",
    "value": "pro"
  }
}
Use and or or to combine multiple rules into a single branch:
{
  "ref": "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
      }
    ]
  }
}

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. Variable references use dot-notation with one of these scopes:
  • event.* — references a field from the triggering event payload (e.g., event.firstName).
  • contact.* — references a field from the current contact (e.g., contact.last_name, contact.properties.company).
config.first_name
string | object
The contact’s first name. Accepts a hardcoded string or a variable reference.
config.last_name
string | object
The contact’s last name. Accepts a hardcoded string or a variable reference.
config.properties
object
A map of custom contact properties to update. Keys correspond to your Contact Custom Properties. Each value can be a hardcoded value (string, number, boolean) or a variable reference.
Example
{
  "ref": "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.
Example
{
  "ref": "remove_contact",
  "type": "contact_delete",
  "config": {}
}

add_to_segment

Adds the contact to a segment.
config.segment_id
string
required
The ID of the segment to add the contact to.
Example
{
  "ref": "add_to_vip",
  "type": "add_to_segment",
  "config": {
    "segment_id": "83a1e324-26dc-47eb-9b28-ba8b6d1fe808"
  }
}

Edge properties

Edges define connections between steps in the automation graph.
from
string
required
This is the ref of the origin step.
to
string
required
This is the ref of the destination step.
edge_type
string
The type of connection between the origin and destination steps. Most automations use the default edge type.Use a non-default edge_type only when the origin step can branch to multiple destinations:
  • For wait_for_event, use event_received or timeout.
  • For condition, use condition_met or condition_not_met.
Possible values:
  • default
  • condition_met
  • condition_not_met
  • timeout
  • event_received
Example
{
  "from": "trigger",
  "to": "welcome_email",
  "edge_type": "default"
}