Skip to main content
PATCH
Update journey
Beta. The Journeys API is in beta. Endpoints and response fields can still change.

Overview

Update an existing Journey programmatically. The request is a JSON Merge Patch (RFC 7396): send only the fields you want to change, and omitted fields are left unchanged. Send state: "active" to activate a draft journey. Editing rules tighten once a journey is active, because it carries in-flight users. See Editing an active journey.
Arrays are replaced wholesale, not merged. Sending nodes replaces the entire node graph. To keep in-flight users on a node, preserve that node’s server-assigned id from a prior View journey fetch. See Preserve node ids.
To change a single node without re-sending the whole graph, use Update journey node.

How to use this API

Authenticate with your App API Key. The authenticated key must have permission to update journeys. Find a journey’s id from the View journeys API or in the dashboard URL. Fetch the journey first with View journey, then send only the fields you are changing. A minimal rename touches only one field:

Merge patch behavior

The request body is merged onto the journey’s current representation:
  • A field you send replaces the current value. Omitted fields are untouched.
  • A null value clears a nullable field. description, schedule, early_exit, and reentry_rules accept null to reset them to their defaults.
  • An individual early-exit rule accepts null. Send early_exit: { "rules": { "on_session": null } } to drop one rule while keeping the others. Clearing the last remaining rule is rejected, since an early_exit with no rule configures nothing; send early_exit: null to remove early exit entirely.
  • Arrays are replaced as a unit. nodes, a node’s branches, and windows are not merged element-wise. Send the full array you want.
  • Changing the audience kind swaps the whole object. The audience is a tagged union identified by its kind. Changing the kind (segmentevent_trigger) is only allowed while the journey is a draft or scheduled; once it is live the audience type is frozen (see Editing an active journey). When you do change it, send only the new variant’s fields; the previous variant’s fields are dropped rather than merged, so you do not need to null them.
On a draft or scheduled journey, swap the entry audience from a segment to an event trigger by sending the new variant alone; the old included_segment_ids and excluded_segment_ids are dropped:

Preserve node ids

Because nodes is an array, a request that includes it replaces the whole graph. A node sent without an id is treated as a new node, so omitting the ids of nodes you meant to keep discards those nodes and recreates them under new ids. Any users in flight on them are lost. Node fields follow the same schema and validation as Create journey. Fetch the journey with View journey first, then send back every node you want to keep, each with the id the server assigned it:
A branching node’s branches array works the same way. Echo each branch’s id to keep it, and note that an active journey’s branches cannot be added or removed at all. To change one node without re-sending the graph, use Update journey node instead. It addresses a single node by its id and leaves every other node untouched.

Optimistic concurrency

To avoid overwriting a concurrent change, pass the concurrency_key returned by a prior View journey fetch. If the journey has changed since that fetch, the request is rejected with 409 journey-stale and nothing is written. Omit concurrency_key to skip the check.
Treat concurrency_key as an opaque token: read it from the journey you are editing and send it back unchanged. Do not construct, parse, or compare it yourself.

Journey states

A journey reports one of five states. draft, scheduled, active, and archived are settable through this endpoint; processing is reported by the server only.

Activate a journey

Set state to transition a journey through its lifecycle. The common case is activating a draft:
  • Only draft journeys can transition to scheduled, and it requires a schedule with a start_at.
  • A journey can return to draft only from scheduled or processing. There is no way to move a running journey back to draft.
  • Send state: "archived" to stop a running journey. Archiving halts all user progress and is permanent: an archived journey can still be read, but it cannot resume sending, and later writes return 422 journey-archived. A draft journey cannot be archived.
  • schedule timestamps must use UTC (Z or +00:00).
Setting state to active starts activation, it does not complete it. The request returns once the activation work is enqueued, so a 200 does not mean the journey is running yet. Until activation finishes, the journey reports state: "processing" and its started_at stays null. Poll View journey until state reads active before you treat the journey as live.

Editing an active journey

An active journey carries in-flight users, so its structure is largely frozen. The API rejects edits that would strand users:
  • Non-structural nodes (such as send_push or wait) can be removed. Users already in flight on a removed node continue forward through the rest of the journey.
  • Structural nodes (split_range, yes_no, wait_until) cannot be removed. A new branching node can be added.
  • An existing branching node’s set of branches cannot change.
  • The schedule start_at is frozen once the journey has left draft or scheduled. Change it while the journey is still a draft or scheduled.
  • The schedule stop_at stays editable in every state, including while active, so you can extend or shorten a running journey’s end date. It must be in the future and later than start_at.
  • A node’s client_node_id is immutable once the journey is live; change it while the journey is still draft or scheduled.
  • The audience type is immutable once the journey is live. That covers both switching between a segment and an event_trigger audience and toggling future_additions_only on a segment audience, since a future-only audience counts as its own type.
  • You can still retarget within the same type: a segment audience’s segments, or an event-trigger audience’s event name and attributes. The one exception is a future-only segment audience, whose segment set is frozen once live.
Edits that violate these rules return 400 with a field-level error describing the conflict.

Response

A successful request returns 200 OK with the full updated journey, including server-assigned id fields and a concurrency_key. Pass that concurrency_key unchanged on a later update to avoid overwriting a concurrent change.

Error responses

Coded errors use the shape { "errors": [{ "code", "title", "meta" }] }; for validation errors the failing field is in meta.attribute, with meta.path for the offending property.

Headers

Authorization
string
default:Key YOUR_APP_API_KEY
required

Your App API key with prefix Key. See Keys & IDs.

Content-Type
string
default:application/json; charset=utf-8
required

Path Parameters

app_id
string
default:YOUR_APP_ID
required

Your OneSignal App ID in UUID v4 format. See Keys & IDs.

id
string
default:YOUR_JOURNEY_ID
required

UUID of the journey to update.

Body

application/json
name
string

Journey name.

description
string | null

Journey description. Send null to clear it.

audience
segment · object

The journey entry audience. Either a segment-based or event-triggered audience.

early_exit
object | null

Conditions that remove a user from the journey before it completes. At least one rule must be set under rules; an early_exit that configures no rule is rejected. Send null to remove early exit entirely, or null for an individual rule to drop just that rule.

reentry_rules
object | null

Controls whether and how soon a user can re-enter the journey. null means re-entry is not allowed.

schedule
object | null

Optional future start and/or stop time. null means no scheduled activation.

nodes
object[]

Full ordered list of nodes, which replaces the existing graph wholesale. Preserve each node's server-assigned id from a prior fetch to keep in-flight users on that node; omit id to add a new node.

A journey node. The kind field selects the shape. Branching nodes (split_range, yes_no, wait_until) nest their sub-graphs inline via branches[].nodes.

state
enum<string>

Target state. Set active to activate a draft journey, or scheduled together with a future schedule.start_at to activate it later. Set archived to stop a running journey; archiving is permanent, and later writes return 422 journey-archived. Only scheduled and processing journeys can return to draft.

Available options:
draft,
scheduled,
active,
archived
concurrency_key
string | null

Optional optimistic-concurrency token. Pass the concurrency_key from a prior fetch to reject the update with 409 if the journey changed in the meantime. Omit to skip the check.

Response

200

Full journey representation returned by the detail and create endpoints.

id
string

Journey UUID. Read-only.

app_id
string

UUID of the app the journey belongs to. Read-only.

name
string

Journey name, up to 300 characters.

description
string | null

Journey description, up to 1024 characters. Defaults to an empty string.

state
enum<string>

Journey state. Read-only. New journeys are created as draft. processing is a transient state while an activation is in progress, and archived is a journey that has been stopped. Change it through the state field on Update journey.

Available options:
draft,
scheduled,
processing,
active,
archived
created_at
string

ISO 8601 creation time. Read-only.

updated_at
string

ISO 8601 last-update time. Read-only.

started_at
string | null

ISO 8601 time the journey was activated, or null. Read-only. May stay null briefly after you set state to active: activation is enqueued for processing, and started_at populates once the journey finishes processing and becomes active.

archived_at
string | null

ISO 8601 time the journey was archived, or null. Read-only.

created_source
string | null

Origin of the journey, for example public_api or dashboard. Read-only.

audience
segment · object

The journey entry audience. Either a segment-based or event-triggered audience.

early_exit
object | null

Conditions that remove a user from the journey before it completes. At least one rule must be set under rules; an early_exit that configures no rule is rejected. Send null to remove early exit entirely, or null for an individual rule to drop just that rule.

reentry_rules
object | null

Controls whether and how soon a user can re-enter the journey. null means re-entry is not allowed.

schedule
object | null

Optional future start and/or stop time. null means no scheduled activation.

nodes
object[]

Ordered list of journey nodes.

A journey node. The kind field selects the shape. Branching nodes (split_range, yes_no, wait_until) nest their sub-graphs inline via branches[].nodes.

concurrency_key
string

Opaque optimistic-concurrency token. Read-only. Pass it back on update to guard against overwriting a concurrent change (409 journey-stale). Send it back exactly as read from this response; do not construct or parse it.