pex

Journeys API

CRUD + lifecycle endpoints for Adaptive Journeys. All endpoints require workspace authentication. Routes under /api/journeys/internal/ are reserved for the runtime (Step Functions dispatcher, GDPR sweep) and authenticate via shared-secret bearer.

List journeys

GET/api/journeys

List all journeys (drafts + published) for the current workspace

Returns the list of journeys in the workspace. Each entry includes the latest version + draft pointer.

curl https://your-instance.com/api/journeys \ -H "Cookie: session=<your-session>"

Create a journey (draft)

POST/api/journeys

Create a new draft journey. Returns the new journey with version=draft.

ParameterTypeDescription
namerequiredstringDisplay name in the dashboard. Required.
descriptionstringFree-form description shown in the canvas info sidebar.
audienceIdstringID of the audience this journey is scoped to. If omitted, all matching subjects are eligible.
triggerContractIdstringID of the trigger contract the journey listens to. If omitted, the journey is manually-triggered only.
goalEventNamestringEvent name that counts as goal completion for calibrated impact.
goalEventWindowDaysnumberAttribution window in days. Defaults to workspace default (7).
stepsJourneyStep[]Initial step graph. Defaults to a single 'exit' step.

Update a journey draft

PATCH/api/journeys/[id]

Mutate the draft. Cannot modify a published version — bump to a new draft first.

Same body shape as POST. Setting goalEventName or goalEventWindowDays here updates the journey-level optimization goal.

Concurrent edits are detected via a conditional write on the updatedAt timestamp. If two clients edit the same draft, the second client gets a 409.

Publish a journey

POST/api/journeys/[id]/publish

Promote the draft to a new immutable version + advance the latest pointer.

Validates:

  • Every send step references a marketing communication. Transactional comms are refused (400 send_step_uses_transactional_comm).
  • Workspace tier maxJourneys count is not exceeded. (Lifted as of 2026-05-15 while pricing is reworked toward usage-based billing — every workspace gets unlimited published journeys regardless of tier. The 402 path will return once gates are re-enabled.)
  • The draft is internally consistent (every next reference resolves, no cycles).

On success returns the new version pointer:

{ "id": "act-onb-2026", "version": 4 }

In-flight executions on prior versions stay on their pinned version. New executions pick up the latest at trigger time.

Pause / resume / archive

POST/api/journeys/[id]/pause

Pause the journey. Stops new executions; in-flight executions continue.

POST/api/journeys/[id]/resume

Resume a paused journey.

POST/api/journeys/[id]/archive

Archive permanently. Cannot be reversed via the dashboard (DDB record is preserved).

Audit log

GET/api/journeys/[id]/audit

Append-only audit timeline (authoring + runtime events).

Returns up to 200 most recent audit entries. Each entry has timestamp, actor, action, and optional metadata. See Debugging journeys for the full action catalog.

Live executions

GET/api/journeys/[id]/executions

Last 50 executions with their current state.

Powers the live executions panel on the journey detail page. Reads from the JEXEC# index (DynamoDB) for execution pointers, then enriches with sfn.DescribeExecution for live status.

[
  {
    "executionArn": "arn:aws:states:us-east-1:0:execution:disp:act-onb-2026__v3__usr_a__evt_b",
    "endUserId": "usr_a",
    "status": "RUNNING",
    "startedAt": "2026-04-30T13:00:00.000Z",
    "currentStepId": "wait-3d"
  }
]

Branch performance

GET/api/journeys/[id]/branch-performance

Per-arm reach + goal-event rate for every adaptive branch in the journey.

Returns:

[
  {
    "stepId": "branch-2",
    "arms": [
      {
        "armId": "discount",
        "subjectsReached": 1240,
        "goalEvents": 89,
        "rate": 0.0718,
        "credibleInterval95": [0.0568, 0.0892]
      },
      {
        "armId": "education",
        "subjectsReached": 1187,
        "goalEvents": 54,
        "rate": 0.0455,
        "credibleInterval95": [0.0331, 0.0598]
      }
    ]
  }
]

Cold-start arms (below the min-sample floor of 200) emit coldStart: true and don't yet have a credible interval.

Calibrated impact

GET/api/journeys/[id]/calibrated-impact

Triggered + converted counts split by exposed/holdout cohort.

{
  "triggered": { "exposed": 4500, "holdout": 240 },
  "converted": { "exposed": 312, "holdout": 9 },
  "exposureRate": 0.0693,
  "holdoutRate": 0.0375,
  "lift": 0.848,
  "underpowered": false,
  "dailyTrend": [ /* 30 daily buckets */ ]
}

underpowered: true is set when either cohort has n < 100. See Calibrated Impact for the methodology.

Step stats

GET/api/journeys/[id]/step-stats

Per-step executed / skipped / failed counts. Powers the canvas transparency badges.

Simulation

POST/api/journeys/[id]/simulate

Dry-run trace for a chosen subject without sending.

ParameterTypeDescription
subjectIdstringReal end-user ID. Mutually exclusive with subjectAttributes.
subjectAttributesobjectSynthetic profile attributes (used when subjectId is omitted).
overridesstring[]Workspace-owner-only. Bypass gates: 'opt_out' | 'suppression' | 'frequency_cap' | 'holdout'.

Returns the full trace with eligibility decisions, rendered template output (PII-masked), and branch / wait simulations. See Dry-run guide for usage patterns.

Internal endpoints (runtime + admin)

These endpoints authenticate via Authorization: Bearer ${SYNC_API_KEY} and are not intended for customer use. They exist for completeness:

  • POST /api/journeys/internal/dispatch — called by the Step Functions dispatcher Lambda.
  • POST /api/journeys/internal/start-execution — called by the trigger evaluator on inbound events.
  • POST /api/journeys/internal/forget-end-user — GDPR erasure sweep.
  • POST /api/journeys/internal/translate-pinpoint — Pinpoint export → Apex bundle translator.
  • POST /api/journeys/internal/import-bundle — applies a translated import bundle.