Journey, initiative, run
Every journey belongs to exactly one initiative. A new initiative arrives without one, so building the first draft is your first step after creating it, and an initiative cannot launch until that draft exists and validates. From there the initiative can carry several journey versions over its life:journeys_list and journeys_get return the read-only summary of a journey (its trigger and ordered steps, in plain language). journeys_get_definition returns the full editable graph, the shape you build with and save back.
Node kinds
Discover these fromjourneys_authoring_catalog rather than hardcoding them: it returns every kind’s inputs, its output handles (the signals it can emit), and the connection rules, scoped to what your organization actually has enabled.
The visual builder also has an email-send step, outbound only, with no reply of its own. It is not yet in the authoring catalog above, so
journeys_add_node cannot add one today. A journey already built with one in the app still runs and can still be read back; the rule below under Troubleshooting still applies to it.It also needs a PUBLISHED email template, and templates are WhatsApp only on the API and MCP surface (whatsapp_numbers_list, templates_list, templates_get, templates_create). There is no email-template capability. An email template is created and published in the Boom app, after the organization has a verified sending domain and from address set up there too.Build a journey
1
Discover what you can build
Call
journeys_authoring_catalog for the node kinds, and the reference catalogs for the ids and paths a node needs: journeys_message_channels and journeys_message_templates for a SEND_MESSAGE node, journeys_event_catalog for event names, journeys_condition_catalog for DECISION/CASE attribute paths, and journeys_message_variables for what a template placeholder can bind to.2
Start a draft
journeys_create_draft with an initiativeId and a definition (name, nodes, edges). Omit node positions and the server lays the graph out for you. To keep editing an initiative’s existing draft instead, load it with journeys_get_definition.3
Add and wire nodes
Shape the graph with
journeys_add_node, journeys_update_node, and journeys_delete_node, then connect them with journeys_connect_nodes, naming the source node’s output handle (SENT, REPLIED, YES, case:<id>, and so on). A handle wires to at most one node. journeys_disconnect_nodes removes an edge.4
Set the trigger
journeys_set_trigger configures the ENTRY node: manual, segment (needs a segmentId), or cdp_event (needs an eventName), with an optional frequency cap.5
Validate
journeys_validate dry-runs the publish checks against a stored draft or an arbitrary definition, without saving anything. It returns whether the graph is valid and the full list of issues, errors block publishing, warnings are advisory.6
Publish
journeys_publish with confirm: true. This is the one action here that starts real outreach.Publishing and versioning
Publishing is deliberately guarded:- It validates first. Any error-severity issue blocks the publish, the same checks
journeys_validateruns. - It requires an explicit
confirm: true. There is no accidental publish, because publishing enrolls real people and sends them real messages. - It is atomic. The previous PUBLISHED version is retired in the same operation that promotes the new one, never a moment where two versions are both live.
- People already mid-journey are unaffected. Each run is pinned to the version it enrolled under, so publishing a new version never changes someone’s path partway through.
journeys_create_draft_from_published, which copies the live version into a new editable draft while the original keeps running untouched. Edit the fork, validate it, and publish it, which then supersedes the version you forked from.
A journey reaches STOPPED two different ways, and they do not mean the same thing. Publishing a replacement supersedes the old version, which keeps running out the people already on it. Stopping it retires it outright. Both show status: STOPPED; only the second sets stoppedAt.
Stopping a journey
Publishing a replacement is not the only way to take a campaign down.journeys_stop retires the live version without putting anything in its place. It takes either a journey id or the initiative id, and needs confirm: true.
- Nobody else enrolls. Both the trigger and the initiative’s live-journey pointer are closed, so a segment backfill still in flight stops producing enrollments too.
- Anyone enrolled but not yet messaged is dropped at their send instead of receiving it. That includes people queued behind a large batch still draining.
- Conversations already under way continue normally. Stopping is not cancelling — it closes the front door and leaves the people inside alone.
journeys_create_draft_from_published and publish it.
Triggers
A journey enters people one of three ways, set on its ENTRY node:- Manual: an operator or an API call adds people directly.
- Segment: anyone who enters the segment enrolls. Pass
includeExisting: trueon publish to also backfill current members once. Backfill takes whoever is a member at that moment, so a segment that has never been evaluated has no members and backfills nobody, with no error to tell you. - CDP event: a person enrolls the moment a matching event arrives and resolves to a known person.
maxEnrollments plus enrollmentWindow, set together or not at all) limits how often the same person can re-enter within a rolling window, useful for a journey that can otherwise re-trigger on repeat events or segment membership. The cap is per person, never a campaign-wide total: maxEnrollments: 1 stops one person entering twice, it does not stop the journey enrolling new people indefinitely.
Troubleshooting
A template placeholder sends blank instead of erroring. It is usually bound to a path that does not resolve for this journey’s trigger. Calljourneys_message_variables for the exact set of paths this journey can use. A custom person attribute binds as person.<key>, not attributes.<key>, that second form is the syntax for DECISION/CASE conditions, not message bindings.
Publish fails because a conversational node follows an email send. An email-send step has no reply lifecycle: only a delay, an exit, or another non-conversational node may come after it. Route any reply-driven path around it instead of through it.
Publish fails with validation errors you did not expect. journeys_publish always validates before publishing and refuses on any error-severity issue, it does not publish “mostly working” journeys. Run journeys_validate while you iterate so you see the same issues before you attempt to go live.
A time-limited campaign keeps enrolling people after its date has passed. Nothing stops it on its own: a published journey stays live until something takes it down, a frequency cap only limits one person’s re-entry, and a DELAY set to a date that has already gone by resolves immediately rather than holding people back. Take it down with journeys_stop.
Related
Use MCP
Connect an AI tool to author and run journeys conversationally.
Template variables
The full variable catalog a SEND_MESSAGE binding can reference, and what resolves per trigger.
Events
Record the CDP events that trigger a journey or feed a DECISION condition.
One uniform surface
Why every journey tool here has a matching REST endpoint.