KoltrixKoltrix docs

Sequences

Drip sequences are ordered, time-delayed email automations attached to a newsletter list. When a subscriber joins the list, Koltrix schedules step 0 to fire after its configured delay, then chains the rest of the steps so each one's "wait" time is honoured precisely — no polling loop on your end.

Each enrollment has a status: active, completed, unsubscribed, paused, suppressed, or bounced. The worker reads the row, sends the matching step, advances the pointer, and either schedules the next step or marks the enrollment complete.

When to use a sequence

  • Welcome series — three or four messages teaching new signups how to get value from your product.
  • Onboarding — day 1, day 3, day 7 nudges introducing a feature each.
  • Re-engagement — fire a sequence when a contact transitions to a "cold" tag.
  • Trial conversion — automated reminders 7, 3, and 1 day before a free trial ends.

Use broadcasts for one-shot announcements; use sequences for anything that should hit subscribers on a relative schedule from when they joined.

Create a sequence

In the dashboard: Newsletters → Sequences → New. Pick a list, name the sequence (e.g. "Welcome series"), and add steps. The default trigger is subscribe (the only one we ship today).

Via the API:

curl https://api.koltrix.com/api/v2/sequences \
  -H "Authorization: Bearer kx_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name":    "Welcome series",
    "list_id": "0b3c...",
    "trigger": "subscribe"
  }'
{
  "id":         "9a4f...",
  "name":       "Welcome series",
  "list_id":    "0b3c...",
  "trigger":    "subscribe",
  "active":     true,
  "step_count": 0,
  "created_at": "2026-05-21T12:00:00Z"
}

Required scope: newsletter (or *). Listing routes also accept read.

Add steps

Each step has a position (zero-indexed), a delay in hours measured from when the previous step was sent (or from enrollment for step 0), and the email content.

curl https://api.koltrix.com/api/v2/sequences/$SEQ_ID/steps \
  -H "Authorization: Bearer kx_..." \
  -H "Content-Type: application/json" \
  -d '{
    "position":    0,
    "delay_hours": 0,
    "subject":     "Welcome to Acme",
    "body_html":   "<h1>Hi {{name}}!</h1><p>Glad you’re here.</p>",
    "body_text":   "Hi {{name}}!\n\nGlad you’re here."
  }'
 
curl https://api.koltrix.com/api/v2/sequences/$SEQ_ID/steps \
  -H "Authorization: Bearer kx_..." \
  -H "Content-Type: application/json" \
  -d '{
    "position":    1,
    "delay_hours": 24,
    "subject":     "Setup guide",
    "body_html":   "<p>Here’s the 5-minute setup we promised.</p>",
    "body_text":   "Here’s the 5-minute setup we promised."
  }'
 
curl https://api.koltrix.com/api/v2/sequences/$SEQ_ID/steps \
  -H "Authorization: Bearer kx_..." \
  -H "Content-Type: application/json" \
  -d '{
    "position":    2,
    "delay_hours": 72,
    "subject":     "How is it going?",
    "body_html":   "<p>Quick check-in — anything I can help with?</p>",
    "body_text":   "Quick check-in — anything I can help with?"
  }'

The resulting schedule, with each delay measured from the previous send:

T+0h    Welcome
T+24h   Setup guide
T+96h   "How's it going?" check-in

Step bodies support the same template placeholders as broadcasts: {{name}}, {{email}}, {{unsubscribe_url}}.

List and inspect

# All sequences
curl https://api.koltrix.com/api/v2/sequences \
  -H "Authorization: Bearer kx_..."
 
# Steps for one sequence
curl https://api.koltrix.com/api/v2/sequences/$SEQ_ID/steps \
  -H "Authorization: Bearer kx_..."

Delete

# Single step
curl -X DELETE https://api.koltrix.com/api/v2/sequences/$SEQ_ID/steps/$STEP_ID \
  -H "Authorization: Bearer kx_..."
 
# Whole sequence (cascades enrollments)
curl -X DELETE https://api.koltrix.com/api/v2/sequences/$SEQ_ID \
  -H "Authorization: Bearer kx_..."

What happens when a subscriber joins

When a subscriber transitions to active on the list (either directly, after a CSV import, or after confirming double opt-in):

  1. Koltrix looks up every active sequence on the list with trigger = 'subscribe'.
  2. For each, an enrollment row is created with next_step_index = 0 and next_send_at = NOW() + step_0_delay.
  3. A scheduled job is enqueued to fire at next_send_at carrying the enrollment ID.

If the subscriber is pending double-opt-in, enrollment is deferred until they click the confirm link. The same flow runs then.

What happens at each step fire

When the scheduled job wakes, the worker:

  1. Loads the enrollment and the step at next_step_index. If either is gone (sequence deleted, subscriber removed), the task quietly succeeds.
  2. Checks status. If unsubscribed, suppressed, bounced, or paused, it skips without sending.
  3. Resolves the list's from_address. If unset, the enrollment is paused with a warning — fix the list, unpause to resume.
  4. Checks the suppression list. If suppressed, marks the enrollment suppressed and ends the chain.
  5. Sends the email through the same pipeline as any other send — tracking, webhooks, warmup all apply.
  6. Updates last_sent_at, advances the pointer, and either schedules the next step or marks completed.

The delay-chained model means a 7-day drip uses zero polling, zero cron jobs, and zero database scans on your side.

Unsubscribe mid-flight

When a subscriber clicks the one-click unsubscribe link (or any other unsubscribe path), Koltrix flips every active enrollment for that subscriber to unsubscribed. Any sleeping job still wakes at its scheduled time, sees the new status, and skips silently. No race, no duplicate send.

Limits and gotchas

  • Delays are in hours. Minute-level granularity isn't supported. The smallest useful delay is 1; use /api/v2/emails directly if you need "fire in 30 seconds."
  • Steps are effectively immutable once an enrollment is in flight. Editing a step's body affects only future enrollments, not anyone already past that step.
  • Sequence sends count against your warmup budget like any other send. Big lists with long sequences can pile up on day one; consider trickling enrollments while a new domain warms up.