# Create a journey

`POST https://api.coach-platform.com/api/public/journeys`

Create a customer journey, optionally with its ordered steps. Trainees are only enrolled once the journey is active.

- Resource: Journeys
- Authentication: API key in the `Authorization: Bearer cp_live_...` header
- HTML version: https://www.coach-platform.com/docs/api/reference/post-journeys
- OpenAPI spec: https://www.coach-platform.com/openapi.json

## Header parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `Idempotency-Key` | string | No | 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

Content type: `application/json`. Required.

| Field | Type | Required | Description |
|---|---|---|---|
| `title` | string | Yes | Journey name shown to the coach. |
| `description` | string | No |   |
| `autoAssign` | boolean | No | Automatically enroll trainees that match the filters below. |
| `autoAssignPriority` | integer | No | Lower runs first when several journeys match. |
| `anchorType` | string | No | Whether day counting starts from the escort start date or from the moment the trainee is enrolled. Allowed values: `escort_start`, `enrollment`. |
| `filterLabels` | string[] | No | Only auto-enroll trainees with these label ids. Maximum items: `100`. |
| `filterEscortTypes` | string[] | No | Maximum items: `100`. |
| `filterGender` | string[] | No | Maximum items: `100`. |
| `durationWeeks` | integer | No | Minimum: `1`. |
| `matchByDuration` | boolean | No |   |
| `steps` | object[] | No | The ordered steps of the journey. Omit to create an empty journey and add its steps later. Maximum items: `50`. |
| `steps[].id` | string | No | 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[].order` | integer | Yes | Position of the step within the journey, starting at 1. Minimum: `1`. |
| `steps[].title` | string | Yes | Maximum length: `200`. |
| `steps[].triggerType` | string | Yes | Whether the step fires on a day, on a week, or on an event. Allowed values: `day`, `week`, `event`. |
| `steps[].triggerValue` | integer | Yes | Day number for triggerType "day", week number for "week". Counted from the journey anchor, starting at 1. Minimum: `1`. |
| `steps[].timeOfDay` | string | No | Local send time as HH:mm, e.g. "09:00". |
| `steps[].eventType` | string | No | Required when triggerType is "event". Allowed values: `weight_stall`, `trainee_inactive`, `form_submitted`, `task_completed`. |
| `steps[].eventThreshold` | integer | No | Minimum: `1`. |
| `steps[].condition` | object | No | Optional gate: the step only fires for trainees who match it. |
| `steps[].condition.type` | string | No | Allowed values: `workouts_completed_in_last_days`, `nutrition_logs_in_last_days`, `forms_submitted_since_enrollment`, `has_label`, `no_label`. |
| `steps[].condition.operator` | string | No | Allowed values: `gte`, `lte`, `eq`. |
| `steps[].condition.value` | number | No |   |
| `steps[].condition.timeframeDays` | integer | No | Minimum: `1`. |
| `steps[].condition.labelId` | string | No |   |
| `steps[].actions` | object[] | No | Maximum items: `50`. |
| `steps[].actions[].id` | string | No | Id of an existing action on this step. Send it back to keep the action, omit it to create a new one. |
| `steps[].actions[].type` | string | Yes | 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[].notificationData` | object | No | For type "notification": { title, message, type: "push" \| "popup" \| "both", popupData? }. |
| `steps[].actions[].guideId` | string | No | For type "guide": the guide to reveal. |
| `steps[].actions[].trainingPlanId` | string | No | For type "training_plan": the plan to assign. |
| `steps[].actions[].nutritionMenuId` | string | No | For type "nutrition_menu": the menu to assign. |
| `steps[].actions[].taskData` | object | No | For type "task": { title, type, priority: "low" \| "medium" \| "high", visibleToTrainee, dueDateOffsetDays? }. |
| `steps[].actions[].whatsappData` | object | No | For type "whatsapp": { message, mediaUrl?, mediaType?, caption? }. |
| `steps[].actions[].labelId` | string | No | For types "add_label" and "remove_label": the label to apply or clear. |
| `steps[].actions[].replacePreviousLabels` | boolean | No |   |
| `steps[].actions[].formData` | object | No | For type "send_form": { formId, expiresAfterDays? }. |

## Responses

| Status | Description |
|---|---|
| `201` Created |  |
| `400` Bad Request |  |
| `401` Unauthorized |  |
| `403` Forbidden |  |
| `404` Not Found |  |
| `409` Conflict |  |
| `429` Too Many Requests |  |
| `500` Internal Server Error |  |

### 201 Created

Content type: `application/json`

| Field | 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 |   |

Example:

```json
{
  "data": {},
  "warnings": [
    {
      "field": "<string>",
      "message": "<string>"
    }
  ]
}
```

### Error responses 400, 401, 403, 404, 409, 429, 500

Content type: `application/json`

| Field | Type | Description |
|---|---|---|
| `error` | object |   |
| `error.code` | string |   |
| `error.message` | string |   |
| `error.fix` | string \| null |   |
| `error.details` | object \| null |   |
| `error.retryAfterMs` | number \| null |   |

Example:

```json
{
  "error": {
    "code": "<string>",
    "message": "<string>",
    "fix": "<string>",
    "details": {},
    "retryAfterMs": 123
  }
}
```

## Examples

### cURL

```bash
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>"
}'
```

### JavaScript (fetch)

```js
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();
```

## Related endpoints

- [List journeys](https://www.coach-platform.com/docs/api/reference/get-journeys/index.md): `GET /api/public/journeys`. List customer journeys (automation templates) with search and pagination, including how many trainees are actively enrolled in each.
- [List journey enrollments](https://www.coach-platform.com/docs/api/reference/get-journeys-enrollments/index.md): `GET /api/public/journeys/enrollments`. List trainee enrollments across journeys, filterable by journey, escort and status, with trainee, escort and journey resolved.
- [Get a journey](https://www.coach-platform.com/docs/api/reference/get-journeys-journey-id/index.md): `GET /api/public/journeys/{journeyId}`. Get a single customer journey with its full step structure: triggers, timing and the actions each step runs.
- [Update a journey](https://www.coach-platform.com/docs/api/reference/patch-journeys-journey-id/index.md): `PATCH /api/public/journeys/{journeyId}`. Update a customer journey's settings and steps.
- [Get journey analytics](https://www.coach-platform.com/docs/api/reference/get-journeys-journey-id-analytics/index.md): `GET /api/public/journeys/{journeyId}/analytics`. Enrollment and completion statistics for a single customer journey.
- [Enroll a trainee in a journey](https://www.coach-platform.com/docs/api/reference/post-journeys-journey-id-enroll/index.md): `POST /api/public/journeys/{journeyId}/enroll`. Enroll one trainee into an active journey.
- [Get a trainee's journey progress](https://www.coach-platform.com/docs/api/reference/get-trainees-trainee-id-journey-progress/index.md): `GET /api/public/trainees/{traineeId}/journey-progress`. Where a trainee stands in their customer journey(s): current effective day and week, completed versus upcoming steps, and each journey's status.
- Previous: [List journeys](https://www.coach-platform.com/docs/api/reference/get-journeys/index.md): `GET /api/public/journeys`. List customer journeys (automation templates) with search and pagination, including how many trainees are actively enrolled in each.
- Next: [List journey enrollments](https://www.coach-platform.com/docs/api/reference/get-journeys-enrollments/index.md): `GET /api/public/journeys/enrollments`. List trainee enrollments across journeys, filterable by journey, escort and status, with trainee, escort and journey resolved.
