Journeys

The Journeys app runs the automated flows of a shop. A contact enters a journey when something happens, moves through its steps, and leaves by finishing, reaching the goal or exiting.

This page is the API reference for developers who build or read journeys: the flows that follow a cart, an order, a sign-up or a date.

A journey is a versioned graph of steps. A trigger enrols a contact, and each enrollment waits, branches, sends or acts step by step until it finishes, reaches the goal or exits. Steps can send mail, SMS, WhatsApp and review requests, act in the CRM (a sales-rep task, a lifecycle stage, a lead score, a static audience, loyalty points) or start an Integration Studio workflow. A send always asks the marketing consents app first. A refused send is skipped with the reason; if that app cannot be reached, the step is tried again later, and the enrollment fails after six attempts. A journey is a draft until it is published. Once live, its version is frozen: a later edit becomes a new draft. The app ships seven templates that a shop can copy.

The app also keeps the figures of each journey: the per-step counts of a report, the enrollment timeline and the step counters.

Objects

ObjectWhat it holds
JourneyThe name, status (draft, live, paused or archived), the trigger, the goal, the re-entry rule, the campaign, the live and draft version, the live period, the counters, and the six trash fields.
VersionOne graph of a journey: draft, live or retired.
StepOne step of a version, with its next, yes and no edges.
EnrollmentOne person in one version: the current step, due_at, the state, the exit reason and the trigger payload.
Enrollment eventOne entry on the timeline of an enrollment.
Step counterThe counters of one step of one version, with the reasons behind the report.
TemplateOne of the seven shipped flows.
Stock watchA "notify me when available" request for one product.

Base path: https://api.revenexx.com/v1/journeys.

Scopes

A key calls these routes with the capability key of each route. The App's manifest names one per operation, in the form journeys.<group>.<operation>, and the API keys page explains that a key holds capability keys or a namespace such as journeys.*. The scope names are listed in the tables below. A call that needs a scope the key does not hold is refused with 403.

Journeys

OperationScopeWhat it does
GET /v1/journeys/journeysjourneys.journeys.listLists the journeys of the tenant. The trash is left out unless trashed asks for it.
POST /v1/journeys/journeysjourneys.journeys.createCreates a journey as a draft with version 1.
GET /v1/journeys/journeys/{id}journeys.journeys.getReads one journey.
PUT /v1/journeys/journeys/{id}journeys.journeys.updateCorrects a journey: name, description, currency, re-entry, campaign, trigger, goal and metadata.
DELETE /v1/journeys/journeys/{id}journeys.journeys.deleteMoves a journey into the trash, if it was never live and has no enrollment (see below). A second DELETE deletes it for good, unless something still needs it (409 with delete_blocked).
POST /v1/journeys/journeys/{id}/restorejourneys.journeys.restoreTakes a journey back out of the trash.
POST /v1/journeys/journeys/trash/emptyjourneys.journeys.empty-trashDeletes every journey in the trash for good. A journey something still blocks stays in the trash and is listed under blocked with its reason.
POST /v1/journeys/journeys/trash/purgejourneys.journeys.purgeDeletes the journeys that have been in the trash longer than the tenant's trash retention (90 days unless the tenant set another). It is the nightly purge, callable by hand. When the retention cannot be read, nothing is deleted.
  • GET /v1/journeys/journeys filters: status, trigger_kind, campaign_ref, template_code, trashed (exclude, only or include) and further plain columns. limit takes 1 to 200 (default 50), with offset and order.
  • POST /v1/journeys/journeys body: required name. Optional: description, trigger_kind, trigger_config, goal_config, reenrol, reenrol_gap_days, campaign_ref, currency, steps, entry and metadata. A status sent by the caller is never written: the journey stays a draft. The answer carries problems, which lists what stands between the draft and going live.
  • trigger_kind values: event, audience_join, lifecycle_stage or date_field. The trigger and the goal are frozen while the journey is live: pause it first. Re-entry and campaign can change on a live journey, and so can the name.
  • DELETE on a journey: only a journey that was never live and has no enrollment goes into the trash. Any other is refused with 409 and trash_blocked, naming the blocker journey_published. Archive it instead. A trashed journey takes no changes: 409 with in_trash.
  • restore error: 409 with not_in_trash when the journey is not in the trash.
  • Errors on create and update: 400 for a missing name on create, an emptied name on update, or a value of the wrong shape. 409 with journey_live when a frozen trigger or goal is changed on a live journey, and journey_archived for any change on an archived one except campaign_ref and metadata.
  • Deleting for good: the second DELETE, trash/empty and trash/purge are refused for a storefront contact with 403 (not_permitted on DELETE, purge_not_allowed on the trash routes). A second DELETE also answers 409 with delete_blocked while something still needs the journey.

Versions and canvas

OperationScopeWhat it does
GET /v1/journeys/journeys/{id}/graphjourneys.journeys.graphReads the steps and edges of one version, the trigger, the goal and the problems that would refuse publishing.
PUT /v1/journeys/journeys/{id}/graphjourneys.journeys.save-graphWrites the draft.
GET /v1/journeys/versionsjourneys.versions.listLists the versions. Filter ?journey_id=.
GET /v1/journeys/versions/{id}journeys.versions.getReads one version.
  • Canvas: GET .../graph?version= takes draft (default: the draft, else the live version), live or a version number. 400 for any other value, 404 for a number the journey does not have.
  • PUT .../graph body: required steps. Optional: entry and notes. A graph with problems is saved; publishing refuses it.
  • Draft rule: when the journey has no draft, PUT .../graph creates the next version as the draft. A live version is never edited.
  • PUT .../graph errors: 400 for a value of the wrong shape or more than 200 steps, 404 when no journey has the id, 409 with journey_archived on an archived journey and in_trash on a trashed one.

Lifecycle

OperationScopeWhat it does
POST /v1/journeys/journeys/{id}/publishjourneys.journeys.publishChecks the draft, the trigger and the goal, then makes the draft the live version. The version before is retired.
POST /v1/journeys/journeys/{id}/pausejourneys.journeys.pausePauses a live journey. Nobody enters and nobody moves.
POST /v1/journeys/journeys/{id}/resumejourneys.journeys.resumeResumes a paused journey.
POST /v1/journeys/journeys/{id}/archivejourneys.journeys.archiveArchives a journey. Nobody enters again.

The status moves only through these four operations. The status draft lasts until the first publish. Each call names its errors below.

  • Publish: 409 with no_draft when there is no draft, and 409 with journey_archived on an archived journey (copy it instead). 422 with not_ready when the draft has problems: the body lists every problem by step. Running enrollments finish on the version they started on. A paused journey stays paused after publish.
  • Pause: 409 with not_live unless the journey is live. Waits that pass during a pause run after the resume, in the job's budgeted chunks.
  • Resume: 409 with not_paused unless the journey is paused.
  • Archive: everyone still inside leaves with the exit reason journey_archived, up to 500 at once; the rest leave with the next runs. Archiving an archived journey does nothing and answers the journey as it is.
  • Errors on all four: 404 when no journey has the id, 401 and 403 as for every route.

Running, reporting and timelines

OperationScopeWhat it does
POST /v1/journeys/journeys/{id}/enroljourneys.journeys.enrolPuts one person into the live version now, under the same re-enrolment rules as a trigger. For a test or for support.
POST /v1/journeys/journeys/{id}/runjourneys.journeys.runProcesses the due steps of one live journey now. It also ends the active enrollments of archived journeys in the tenant (see below).
GET /v1/journeys/journeys/{id}/reportjourneys.journeys.reportReads the per-step counts and the per-version totals: enrolled, completed, goal reached, exited, failed and conversion.
GET /v1/journeys/journeys/{id}/timelinejourneys.journeys.timelineReads the entries and the goals reached per day, over all versions.
  • enrol body: contact_id or email names the person (400 otherwise, and when contact_id names no contact). Optional: data (the payload the steps read), market, and key, which makes a resent request enrol only once.
  • enrol answers: 201 with the enrollment on success. Otherwise 409, with the reason as code: already_enrolled, reenrol_off, reenrol_gap, cap_reached, duplicate (the same key sent again) or not_live (the journey is not live: draft, paused or archived, or it has no live version). The body carries reason and enrollment_id.
  • run: on a journey that is not live it processes no steps. The call still ends the active enrollments of archived journeys across the tenant, in capped batches (exit reason journey_archived), because that sweep runs before the per-journey filter.
  • timeline: reads the tenant time zone and covers at most the latest 60 days.

Enrollments and events

OperationScopeWhat it does
GET /v1/journeys/enrollmentsjourneys.enrollments.listLists enrollments. Filters: journey_id, state, contact_id and current_step.
GET /v1/journeys/enrollments/{id}journeys.enrollments.getReads one enrollment.
POST /v1/journeys/enrollments/{id}/exitjourneys.enrollments.exitTakes a person out of a journey.
GET /v1/journeys/enrollment-eventsjourneys.timeline.listLists enrollment events. Filter enrollment_id for one person's timeline.
GET /v1/journeys/enrollment-events/{id}journeys.timeline.getReads one enrollment event.
  • Exit: 409 with enrollment_ended when the enrollment has already ended, and 409 with enrollment_moved when it moved on while it was being removed. Try again.
  • Exit reasons on an ended enrollment: exit_step, withdrawn, journey_archived, removed, failed or unresolvable.

Steps and step counters

OperationScopeWhat it does
GET /v1/journeys/stepsjourneys.steps.listLists step rows. Filter journey_version_id, or journey_id with version.
GET /v1/journeys/steps/{id}journeys.steps.getReads one step row.
GET /v1/journeys/step-statsjourneys.stats.listLists step counters.
GET /v1/journeys/step-stats/{id}journeys.stats.getReads one step counter.

Templates

OperationScopeWhat it does
GET /v1/journeys/templatesjourneys.templates.listLists the seven shipped flows.
GET /v1/journeys/templates/{id}journeys.templates.getReads one template.
POST /v1/journeys/templates/{code}/copyjourneys.templates.copyCopies a template into a new draft journey. Optional body field name. An unknown code answers 404 (not_found).

Stock watches

A storefront posts a stock watch from a sold-out product page. The back-in-stock trigger enrols the people who wait for the product when it is back.

OperationScopeWhat it does
GET /v1/journeys/stock-watchesjourneys.watches.listLists notification requests. Filter product_id and state=waiting.
POST /v1/journeys/stock-watchesjourneys.watches.createAsks to be told when a product is back.
GET /v1/journeys/stock-watches/{id}journeys.watches.getReads one notification request.
DELETE /v1/journeys/stock-watches/{id}journeys.watches.deleteWithdraws a notification request.
  • POST body: a person (contact_id or email) and a product (product_id or sku) are required; 400 otherwise, and for an email without @ or an id that is not a UUID. Optional: market and source. A new request answers 201; a person already waiting for the product gets the existing request back with 200.

Jobs

OperationScopeWhat it does
POST /v1/journeys/steps/runjourneys.jobs.stepsRuns the step job once: due steps of all live journeys, oldest first, within the budget. Optional body field budget_ms can only shorten the tenant's step budget.
POST /v1/journeys/triggers/runjourneys.jobs.triggersRuns the date triggers due today, then the three-hour sweep over carts, orders, subscriptions and audience joins. Optional body field force.

The step job also runs on a five-minute schedule and the trigger job hourly. A caller can run either one by hand.

Vocabularies

OperationScopeWhat it does
GET /v1/journeys/vocabulariesjourneys.vocabularies.listLists the closed vocabularies the app enforces.
GET /v1/journeys/vocabularies/{name}journeys.vocabularies.getReads one vocabulary with its values and labels. 404 when there is no such vocabulary.
  • Audiences: the audience a journey's trigger names, and the members a journey can enter.
  • Marketing consents: the consent a send checks before it goes out.
  • Reviews: a review link is handed out through a journey step.
Was this page helpful?