Create a journey
POST/api/public/journeys
Create a customer journey, optionally with its ordered steps. Trainees are only enrolled once the journey is active.
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.
Header parameters
| Name | Type | Description |
|---|---|---|
Idempotency-Key | string | 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
| Name | Type | Description |
|---|---|---|
titlerequired | string | Journey name shown to the coach. |
description | string | |
autoAssign | boolean | Automatically enroll trainees that match the filters below. |
autoAssignPriority | integer | Lower runs first when several journeys match. |
anchorType | string | Whether day counting starts from the escort start date or from the moment the trainee is enrolled. |
filterLabels | string[] | Only auto-enroll trainees with these label ids. |
filterEscortTypes | string[] | |
filterGender | string[] | |
durationWeeks | integer | |
matchByDuration | boolean | |
steps | object[] | The ordered steps of the journey. Omit to create an empty journey and add its steps later. |
steps[].id | string | Id of an existing step, as returned by |
steps[].orderrequired | integer | Position of the step within the journey, starting at 1. |
steps[].titlerequired | string | |
steps[].triggerTyperequired | string | Whether the step fires on a day, on a week, or on an event. |
steps[].triggerValuerequired | integer | Day number for triggerType "day", week number for "week". Counted from the journey anchor, starting at 1. |
steps[].timeOfDay | string | Local send time as HH:mm, e.g. "09:00". |
steps[].eventType | string | Required when triggerType is "event". |
steps[].eventThreshold | integer | |
steps[].condition | object | Optional gate: the step only fires for trainees who match it. |
steps[].condition.type | string | |
steps[].condition.operator | string | |
steps[].condition.value | number | |
steps[].condition.timeframeDays | integer | |
steps[].condition.labelId | string | |
steps[].actions | object[] | |
steps[].actions[].id | string | Id of an existing action on this step. Send it back to keep the action, omit it to create a new one. |
steps[].actions[].typerequired | string | What this action does when the step fires. |
steps[].actions[].notificationData | object | For type "notification": { title, message, type: "push" | "popup" | "both", popupData? }. |
steps[].actions[].guideId | string | For type "guide": the guide to reveal. |
steps[].actions[].trainingPlanId | string | For type "training_plan": the plan to assign. |
steps[].actions[].nutritionMenuId | string | For type "nutrition_menu": the menu to assign. |
steps[].actions[].taskData | object | For type "task": { title, type, priority: "low" | "medium" | "high", visibleToTrainee, dueDateOffsetDays? }. |
steps[].actions[].whatsappData | object | For type "whatsapp": { message, mediaUrl?, mediaType?, caption? }. |
steps[].actions[].labelId | string | For types "add_label" and "remove_label": the label to apply or clear. |
steps[].actions[].replacePreviousLabels | boolean | |
steps[].actions[].formData | object | For type "send_form": { formId, expiresAfterDays? }. |
Request examples
curl --request POST \
--url 'https://api.coach-platform.com/api/public/journeys' \
--header 'Authorization: Bearer cp_live_...' \
--header 'Content-Type: application/json' \
--data '{
"title": "<string>"
}'const response = await fetch('https://api.coach-platform.com/api/public/journeys', {
method: 'POST',
headers: {
Authorization: 'Bearer cp_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"title": "<string>"
}),
});
const data = await response.json();Responses
201 Created
{
"data": {},
"warnings": [
{
"field": "<string>",
"message": "<string>"
}
]
}Response fields (4)
| Name | Type | Description |
|---|---|---|
data | object | |
warnings | object[] | Non-fatal problems with follow-up writes. The resource was created, but each listed field was not applied. |
warnings[].field | string | |
warnings[].message | string |
Error responses
400Bad Request401Unauthorized403Forbidden404Not Found409Conflict429Too Many Requests500Internal Server Error
These statuses share the same response body.
{
"error": {
"code": "<string>",
"message": "<string>",
"fix": "<string>",
"details": {},
"retryAfterMs": 123
}
}Error fields (6)
| Name | Type | Description |
|---|---|---|
error | object | |
error.code | string | |
error.message | string | |
error.fix | string | null | |
error.details | object | null | |
error.retryAfterMs | number | null |
More Journeys endpoints
This page is also available as Markdown. Browse it in the interactive explorer or download the OpenAPI spec.