Marketing Journeys

Behavioral journeys (a.k.a. flows) are multi-step automations that enroll contacts on a trigger and advance them through steps over time. They live in the journeys tRPC router on the company-manager API, called at /api/trpc/journeys.<procedure> with the standard tRPC conventions.

Warning

v1 limitation — only EMAIL steps actually do anything outbound. The SMS step is a non-functional stub, and several action steps are advance-only no-ops today. Read Step types before designing a journey — a WEBHOOK step does not emit a webhook yet.

Procedures

Procedure Purpose Permission
list List journeys. automation:read
get Fetch one journey. automation:read
create Create a journey. automation:write
update Update journey metadata. automation:write
updateSteps Replace the journey's steps. automation:write
activate Activate a journey (starts firing). automation:write
pause Pause a journey. automation:write
setActive Set active state explicitly. automation:write
listTemplates List prebuilt templates. automation:read
createFromTemplate Create a journey from a template. automation:write
listEnrollments List enrollments. automation:read
enroll Manually enroll a contact. automation:write
getStats Journey statistics. automation:read
tick Advance due enrollments (see Firing). automation:write

Triggers

A journey starts when its trigger fires for a contact:

Trigger Fires on
NEWSLETTER_SIGNUP A public newsletter / signup submit.
CART_ABANDONED An abandoned-cart sweep.
ORDER_MINTED An order being minted.
DATE_WINBACK A date-based win-back sweep.
MANUAL An explicit journeys.enroll call.

Step types

Steps are declared on the journey (via create + updateSteps, or a template). The status column reflects the v1 reality:

Step type Status
EMAIL Functional — this is the only step that sends.
WAIT Flow control — the delay between steps (e.g. J+3).
CONDITION Flow control — branching marker.
GOAL Flow control — goal marker.
SMS Non-functional stub — does not send.
WEBHOOK Advance-only no-op (v1) — emits no outbound webhook.
UPDATE_FIELD Advance-only no-op (v1).
ADD_TO_SEGMENT Advance-only no-op (v1).
REMOVE_FROM_SEGMENT Advance-only no-op (v1).
CREATE_TASK Advance-only no-op (v1).
SEND_NOTIFICATION Advance-only no-op (v1).
Warning

An "advance-only no-op" step is traversed — the enrollment moves past it — but it performs no side effect. Do not rely on WEBHOOK, UPDATE_FIELD, ADD_TO_SEGMENT / REMOVE_FROM_SEGMENT, CREATE_TASK, or SEND_NOTIFICATION to do anything today, and treat SMS as inert.

Prebuilt templates

listTemplates exposes ready-made journeys; createFromTemplate instantiates one:

Template Trigger Shape
welcome NEWSLETTER_SIGNUP J+0 / J+3 / J+7 emails + a GOAL.
abandoned-cart CART_ABANDONED 1h + 24h.
post-purchase ORDER_MINTED J+0 thanks + J+7 review.
win-back DATE_WINBACK J+0 + J+3.
Note

createFromTemplate creates an inactive journey. Nothing fires until an admin activates it.

How firing works

Enrollment happens differently per trigger:

Trigger How it fires Default
NEWSLETTER_SIGNUP From the public newsletter / signup submit. Live.
CART_ABANDONED A cron sweep emitter (JOURNEYS_CART_EMITTER). Bounded, capped 500/tick. On.
DATE_WINBACK A cron sweep emitter (JOURNEYS_WINBACK_EMITTER). Bounded, capped 500/tick. On.
ORDER_MINTED Event-driven from the order lifecycle + the Stripe magazine webhook (JOURNEYS_PURCHASE_EMITTER). Off.
MANUAL Call journeys.enroll with a journeyId. n/a

Once a contact is enrolled, the recurring "advance due enrollments" work is driven by journeys.tick. tick is invoked on a schedule by the bext SDK scheduler over loopbacknot BullMQ. See Scheduled Jobs.

Defining and activating a journey

The developer path is short:

journeys.createFromTemplate         (or: journeys.create + journeys.updateSteps)
        │
        ▼
journeys.activate

After activate:

  • Enrollment is automatic for the trigger types (subject to the emitter defaults above).
  • Or enroll contacts manually with journeys.enroll (the MANUAL path).

Related