Update a journey

PATCH/api/public/journeys/{journeyId}

Update a customer journey's settings and steps. Sending "steps" replaces the whole list, so read the journey first and send every step you want to keep: steps you send back with their id are updated in place, steps you leave out are removed, and steps without an id are added. Editing steps reschedules pending sends for trainees already enrolled.

Authentication

Requires an API key, sent as Authorization: Bearer cp_live_....

API keys carry scopes. Get the catalog of scopes and webhook events lists every scope.

Path parameters

Path parameters
NameTypeDescription
journeyIdrequiredstring

Header parameters

Header parameters
NameTypeDescription
Idempotency-Keystring

Optional. Send a unique key (e.g. a UUID) to make this POST safe to retry. The same key within 24h returns the original result instead of creating a duplicate.

Request body

application/json, required

Request body fields
NameTypeDescription
titlestring
descriptionstring
isActiveboolean

Activate or pause the journey.

autoAssignboolean
autoAssignPriorityinteger
anchorTypestring

Allowed values: escort_start enrollment

filterLabelsstring[]

Maximum items: 100

filterEscortTypesstring[]

Maximum items: 100

filterGenderstring[]

Maximum items: 100

durationWeeksinteger

Minimum: 1

matchByDurationboolean
stepsobject[]

The complete ordered list of steps the journey should have after the update.

Maximum items: 50

steps[].idstring

Id of an existing step, as returned by GET /journeys/:journeyId. Send it back to update that step in place; omit it to add a new one.

steps[].orderrequiredinteger

Position of the step within the journey, starting at 1.

Minimum: 1

steps[].titlerequiredstring

Maximum length: 200

steps[].triggerTyperequiredstring

Whether the step fires on a day, on a week, or on an event.

Allowed values: day week event

steps[].triggerValuerequiredinteger

Day number for triggerType "day", week number for "week". Counted from the journey anchor, starting at 1.

Minimum: 1

steps[].timeOfDaystring

Local send time as HH:mm, e.g. "09:00".

steps[].eventTypestring

Required when triggerType is "event".

Allowed values: weight_stall trainee_inactive form_submitted task_completed

steps[].eventThresholdinteger

Minimum: 1

steps[].conditionobject

Optional gate: the step only fires for trainees who match it.

steps[].condition.typestring

Allowed values: workouts_completed_in_last_days nutrition_logs_in_last_days forms_submitted_since_enrollment has_label no_label

steps[].condition.operatorstring

Allowed values: gte lte eq

steps[].condition.valuenumber
steps[].condition.timeframeDaysinteger

Minimum: 1

steps[].condition.labelIdstring
steps[].actionsobject[]

Maximum items: 50

steps[].actions[].idstring

Id of an existing action on this step. Send it back to keep the action, omit it to create a new one.

steps[].actions[].typerequiredstring

What this action does when the step fires.

Allowed values: notification guide training_plan nutrition_menu task whatsapp add_label remove_label send_form

steps[].actions[].notificationDataobject

For type "notification": { title, message, type: "push" | "popup" | "both", popupData? }.

steps[].actions[].guideIdstring

For type "guide": the guide to reveal.

steps[].actions[].trainingPlanIdstring

For type "training_plan": the plan to assign.

steps[].actions[].nutritionMenuIdstring

For type "nutrition_menu": the menu to assign.

steps[].actions[].taskDataobject

For type "task": { title, type, priority: "low" | "medium" | "high", visibleToTrainee, dueDateOffsetDays? }.

steps[].actions[].whatsappDataobject

For type "whatsapp": { message, mediaUrl?, mediaType?, caption? }.

steps[].actions[].labelIdstring

For types "add_label" and "remove_label": the label to apply or clear.

steps[].actions[].replacePreviousLabelsboolean
steps[].actions[].formDataobject

For type "send_form": { formId, expiresAfterDays? }.

Request examples

cURL
curl --request PATCH \
  --url 'https://api.coach-platform.com/api/public/journeys/<journeyId>' \
  --header 'Authorization: Bearer cp_live_...' \
  --header 'Content-Type: application/json' \
  --data '{
  "title": "<string>"
}'
JavaScript (fetch)
const response = await fetch('https://api.coach-platform.com/api/public/journeys/<journeyId>', {
  method: 'PATCH',
  headers: {
    Authorization: 'Bearer cp_live_...',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "title": "<string>"
  }),
});

const data = await response.json();

Responses

200 OK

Successful response

Example body (application/json)
{
  "data": {}
}
Response fields (1)
Response fields
NameTypeDescription
dataobject

Error responses

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 409 Conflict
  • 429 Too Many Requests
  • 500 Internal Server Error

These statuses share the same response body.

Example body (application/json)
{
  "error": {
    "code": "<string>",
    "message": "<string>",
    "fix": "<string>",
    "details": {},
    "retryAfterMs": 123
  }
}
Error fields (6)
Error fields
NameTypeDescription
errorobject
error.codestring
error.messagestring
error.fixstring | null
error.detailsobject | null
error.retryAfterMsnumber | null

This page is also available as Markdown. Browse it in the interactive explorer or download the OpenAPI spec.