Kraiter
Guides

Sequences

Build automated drip campaigns with delays, conditions, and event-based triggers.

Sequences are automated email workflows that send a series of emails to contacts over time. They are the core of Kraiter's automation capabilities — use them for onboarding flows, nurture campaigns, re-engagement series, and more.

A sequence is defined using a YAML format that specifies triggers, steps, delays, conditions, and exit conditions.

Creating a sequence

Create (or replace) a sequence with upsert, keyed by a sequence ID. Provide a name and the YAML definition as content:

SDK
const sequence = await kraiter.sequences.upsert('onboarding', {
  name: 'onboarding',
  content: `
trigger:
  event: signup.completed

steps:
  - action: email
    template: welcome-email
  - action: delay
    duration: 1d
  - action: email
    template: getting-started
  - action: delay
    duration: 3d
  - action: condition
    property: contact.properties.hasCompletedOnboarding
    operator: equals
    value: true
    onTrue: exit
  - action: email
    template: onboarding-reminder
  `,
});

YAML format

The sequence definition has three top-level keys: trigger, steps, and optionally exitConditions.

Trigger

The trigger determines how contacts are enrolled in the sequence. Every sequence must declare an event-based trigger — a sequence submitted without a trigger event is rejected. Contacts are enrolled automatically whenever a matching event is tracked for them:

trigger:
  event: purchase.completed

Steps

Steps are executed in order for each enrolled contact. There are three step types:

Email step

Sends an email using a named template:

- action: email
  template: welcome-email

The template must exist before the sequence is activated. The email is sent using the contact's email address and their properties are available as Liquid variables.

Delay step

Pauses the sequence for a specified duration before continuing to the next step:

- action: delay
  duration: 3d

Supported duration units:

UnitExampleDescription
m30mMinutes
h2hHours
d3dDays
w1wWeeks

You can combine units: 1d12h means one day and twelve hours.

Condition step

Evaluates a condition and branches based on the result. If the condition is true, the onTrue action is taken; otherwise, the sequence continues to the next step.

- action: condition
  property: contact.properties.isVip
  operator: equals
  value: true
  onTrue: skip

Available actions for onTrue:

  • exit — Remove the contact from the sequence
  • skip — Skip the next step and continue

Condition operators:

OperatorTypesDescription
equalsallExact match
notEqualsallNot equal
containsstringString contains substring
greaterThannumber, dateGreater than
lessThannumber, dateLess than
existsallProperty has a value
notExistsallProperty has no value

You can also check segment membership in a condition:

- action: condition
  segment: high-value-customers
  onTrue: exit

Exit conditions

Exit conditions are evaluated before each step. If any exit condition is true, the contact is removed from the sequence immediately. This is useful for stopping a sequence when the contact's situation changes.

exitConditions:
  - property: contact.unsubscribed
    operator: equals
    value: true
  - property: contact.properties.hasConverted
    operator: equals
    value: true

Complete example

Here is a full sequence definition for a trial expiry campaign:

trigger:
  event: trial.started

exitConditions:
  - property: contact.properties.plan
    operator: notEquals
    value: "trial"

steps:
  - action: email
    template: trial-welcome
  - action: delay
    duration: 3d
  - action: email
    template: trial-tips
  - action: delay
    duration: 4d
  - action: condition
    property: contact.properties.activatedFeature
    operator: equals
    value: true
    onTrue: skip
  - action: email
    template: trial-feature-prompt
  - action: delay
    duration: 5d
  - action: email
    template: trial-expiring-soon
  - action: delay
    duration: 2d
  - action: email
    template: trial-expired

This sequence:

  1. Sends a welcome email immediately when a trial starts
  2. Follows up with tips after three days
  3. Checks whether the user has activated a feature — if yes, skips the prompt
  4. Sends an expiry warning at day twelve
  5. Sends a final email at day fourteen
  6. Exits early if the contact upgrades from the trial plan

Enabling and disabling sequences

A sequence is controlled by a single enabled flag rather than a multi-state lifecycle. While disabled, no contacts are enrolled and no steps are processed. Toggle it with update (a partial metadata update):

SDK
// Enable the sequence so it starts enrolling and processing contacts
await kraiter.sequences.update('onboarding', { enabled: true });

// Disable it — enrolment and step processing stop
await kraiter.sequences.update('onboarding', { enabled: false });

Editing a sequence's content with upsert never flips the enabled flag implicitly — enabling and disabling is always an explicit action. While a sequence is disabled, contacts already partway through remain at their current step and resume when it is re-enabled.

Enrolling contacts

Enrolment is automatic and event-driven: when you track the sequence's trigger event for a contact, that contact is enrolled. There is no separate manual-enrolment endpoint — to enrol a contact, track the trigger event for them:

SDK
// Enrols the contact into any sequence triggered by 'signup.completed'
await kraiter.events.track({
  email: 'alice@example.com',
  name: 'signup.completed',
});

A contact can only be active in the same sequence once at a time. If they have already completed or exited the sequence, tracking the trigger event again re-enrols them.

Dry-run testing

Before activating a sequence, test it with a dry run. A dry run simulates the sequence execution without actually sending emails:

SDK
const result = await kraiter.sequences.dryRun('onboarding', {
  contactId: 'CONTACT_ID',
});

console.log(result.steps); // Shows what would happen at each step

This helps you verify that conditions, delays, and exit conditions behave as expected before going live.