# List training plans

`GET https://api.coach-platform.com/api/public/training-plans`

List training plans. Filter by traineeId or escortId.

- Resource: Training Plans
- Authentication: API key in the `Authorization: Bearer cp_live_...` header
- HTML version: https://www.coach-platform.com/docs/api/reference/get-training-plans
- OpenAPI spec: https://www.coach-platform.com/openapi.json

## Query parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `page` | integer | No | Page number (1-based, default 1) Minimum: `1`. |
| `limit` | integer | No | Number of items to return (default 25, max 500) Minimum: `1`. Maximum: `500`. |
| `traineeId` | string | No |   |
| `escortId` | string | No |   |

## Responses

| Status | Description |
|---|---|
| `200` OK | Successful response |
| `400` Bad Request |  |
| `401` Unauthorized |  |
| `403` Forbidden |  |
| `429` Too Many Requests |  |
| `500` Internal Server Error |  |

### 200 OK

Content type: `application/json`

| Field | Type | Description |
|---|---|---|
| `data` | object[] |   |
| `data[].id` | string |   |
| `data[].coach` | string |   |
| `data[].escorts` | string[] |   |
| `data[].title` | string |   |
| `data[].notes` | string |   |
| `data[].level` | string | Allowed values: `Beginner`, `Intermediate`, `Advanced`. |
| `data[].maxDuration` | number | Target session length in minutes. |
| `data[].isTemplate` | boolean | True when the plan is a reusable template. |
| `data[].workouts` | object[] |   |
| `data[].workouts[].trainingName` | string | Display name of the day, e.g. "Day A — Push". |
| `data[].workouts[].trainingType` | string | Day label, e.g. "A", "B", "FullBody". Allowed values: `A`, `B`, `C`, `D`, `E`, `FullBody`, `CrossFit`, `Tabata`, `HIIT`, `EMOM`, `AMRAP`, `Circuit`, `ForTime`. |
| `data[].workouts[].exerciseOrder` | string | How exercises are performed. Defaults to Sequential. Allowed values: `Sequential`, `Circuit`, `Superset`, `Complex`. |
| `data[].workouts[].notes` | string | Free-text note for the whole day. |
| `data[].workouts[].timeBasedDetails` | object | Timing configuration for circuit-style days (Tabata, HIIT, EMOM, AMRAP). Seconds unless noted. |
| `data[].workouts[].timeBasedDetails.totalRounds` | number |   |
| `data[].workouts[].timeBasedDetails.timeLimit` | number |   |
| `data[].workouts[].timeBasedDetails.workInterval` | number |   |
| `data[].workouts[].timeBasedDetails.restInterval` | number |   |
| `data[].workouts[].timeBasedDetails.restBetweenRounds` | number |   |
| `data[].workouts[].exercises` | object[] |   |
| `data[].workouts[].exercises[].exerciseDetails` | object | The exercise catalog entry. On write, pass exerciseDetails as the catalog id string (from GET /exercises). |
| `data[].workouts[].exercises[].exerciseDetails.id` | string |   |
| `data[].workouts[].exercises[].exerciseDetails.name` | string |   |
| `data[].workouts[].exercises[].setsNumber` | string | Number of sets, e.g. "3". |
| `data[].workouts[].exercises[].repsNumber` | string | Reps per set, e.g. "10" or "8-12". |
| `data[].workouts[].exercises[].restTime` | string | Rest between sets in seconds, e.g. "90". |
| `data[].workouts[].exercises[].isDurationBased` | boolean | True for timed exercises (e.g. plank) instead of reps. |
| `data[].workouts[].exercises[].setDuration` | string | Duration per set in seconds when isDurationBased is true. |
| `data[].workouts[].exercises[].weightPercentage` | number | Working weight as % of 1RM, e.g. 75. |
| `data[].workouts[].exercises[].customNotes` | string | Free-text note shown to the trainee for this exercise. |
| `data[].workouts[].exercises[].weight` | number | Working weight in kg for the exercise. |
| `data[].workouts[].exercises[].sets` | object[] | Per-set prescription. Takes precedence over setsNumber/repsNumber when present. |
| `data[].workouts[].exercises[].sets[].setNumber` | number | 1-based position of the set. |
| `data[].workouts[].exercises[].sets[].reps` | string | Reps for this set, e.g. "8". |
| `data[].workouts[].exercises[].sets[].weight` | number | Working weight for this set. |
| `data[].workouts[].exercises[].sets[].restTime` | string | Rest after this set in seconds. |
| `data[].workouts[].exercises[].sets[].intensityValue` | number | Intensity for this set, read against intensityType. |
| `data[].workouts[].exercises[].sets[].dropSet` | string | Allowed values: `DropSet`, `DoubleDropSet`, `TripleDropSet`. |
| `data[].workouts[].exercises[].sets[].isWarmupSet` | boolean | Warmup sets are not counted towards working volume. |
| `data[].workouts[].exercises[].superSet` | boolean | True when this exercise belongs to a superset. |
| `data[].workouts[].exercises[].superSetGroup` | string | Shared identifier grouping the exercises performed together in one superset. |
| `data[].workouts[].exercises[].dropSet` | string | Allowed values: `DropSet`, `DoubleDropSet`, `TripleDropSet`. |
| `data[].workouts[].exercises[].restPause` | boolean | Rest-pause technique. |
| `data[].workouts[].exercises[].cluster` | boolean | Cluster-set technique. |
| `data[].workouts[].exercises[].trackingType` | string | What the trainee logs for this exercise. Allowed values: `weight_reps`, `reps_only`, `duration`, `completion`. |
| `data[].workouts[].exercises[].intensityType` | string | How intensityValue is interpreted. Allowed values: `Percentage`, `RPE`, `RIR`. |
| `data[].workouts[].exercises[].intensityValue` | number | Intensity target. |
| `data[].workouts[].exercises[].tempo` | object | Tempo in seconds per phase of the lift. |
| `data[].workouts[].exercises[].tempo.eccentric` | number |   |
| `data[].workouts[].exercises[].tempo.hold` | number |   |
| `data[].workouts[].exercises[].tempo.concentric` | number |   |
| `data[].workouts[].exercises[].tempo.rest` | number |   |
| `data[].workouts[].exercises[].distance` | number | Distance for cardio exercises. |
| `data[].workouts[].exercises[].distanceUnit` | string | Allowed values: `meters`, `km`, `miles`, `yards`. |
| `data[].workouts[].exercises[].specificAlternativeExercises` | string[] | Catalog ids the trainee may swap in for this exercise. |
| `data[].createdAt` | string<date-time> |   |
| `pagination` | object |   |
| `pagination.page` | number |   |
| `pagination.limit` | number |   |
| `pagination.total` | number \| null | Total number of matching items. null when the underlying source cannot report an exact count for this page; use hasMore to keep paging. |
| `pagination.hasMore` | boolean |   |
| `pagination.truncated` | boolean | Present and true when the result set exceeded the in-memory scan cap and was truncated. Narrow your filters to page through all items. |

Example:

```json
{
  "data": [
    {
      "id": "<string>",
      "coach": "<string>",
      "escorts": [
        "<string>"
      ],
      "title": "<string>",
      "notes": "<string>",
      "level": "Beginner",
      "maxDuration": 123,
      "isTemplate": true,
      "workouts": [
        {
          "trainingName": "<string>",
          "trainingType": "A",
          "exerciseOrder": "Sequential",
          "notes": "<string>",
          "timeBasedDetails": {
            "totalRounds": 123,
            "timeLimit": 123,
            "workInterval": 123,
            "restInterval": 123,
            "restBetweenRounds": 123
          },
          "exercises": [
            {
              "exerciseDetails": {
                "id": "<string>",
                "name": "<string>"
              },
              "setsNumber": "<string>",
              "repsNumber": "<string>",
              "restTime": "<string>",
              "isDurationBased": true,
              "setDuration": "<string>",
              "weightPercentage": 123,
              "customNotes": "<string>",
              "weight": 123,
              "sets": [
                {
                  "setNumber": 123,
                  "reps": "<string>",
                  "weight": 123,
                  "restTime": "<string>",
                  "intensityValue": 123,
                  "dropSet": "DropSet",
                  "isWarmupSet": true
                }
              ],
              "superSet": true,
              "superSetGroup": "<string>",
              "dropSet": "DropSet",
              "restPause": true,
              "cluster": true,
              "trackingType": "weight_reps",
              "intensityType": "Percentage",
              "intensityValue": 123,
              "tempo": {
                "eccentric": 123,
                "hold": 123,
                "concentric": 123,
                "rest": 123
              },
              "distance": 123,
              "distanceUnit": "meters",
              "specificAlternativeExercises": [
                "<string>"
              ]
            }
          ]
        }
      ],
      "createdAt": "<date-time>"
    }
  ],
  "pagination": {
    "page": 123,
    "limit": 123,
    "total": 123,
    "hasMore": true,
    "truncated": true
  }
}
```

### Error responses 400, 401, 403, 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 GET \
  --url 'https://api.coach-platform.com/api/public/training-plans' \
  --header 'Authorization: Bearer cp_live_...'
```

### JavaScript (fetch)

```js
const response = await fetch('https://api.coach-platform.com/api/public/training-plans', {
  method: 'GET',
  headers: {
    Authorization: 'Bearer cp_live_...',
  },
});

const data = await response.json();
```

## Related endpoints

- [Create a training plan](https://www.coach-platform.com/docs/api/reference/post-training-plans/index.md): `POST /api/public/training-plans`. Create a training plan.
- [Get a training plan](https://www.coach-platform.com/docs/api/reference/get-training-plans-plan-id/index.md): `GET /api/public/training-plans/{planId}`. Get a training plan by id.
- [Update a training plan](https://www.coach-platform.com/docs/api/reference/patch-training-plans-plan-id/index.md): `PATCH /api/public/training-plans/{planId}`. Partially update a training plan.
- [Delete a training plan](https://www.coach-platform.com/docs/api/reference/delete-training-plans-plan-id/index.md): `DELETE /api/public/training-plans/{planId}`. Delete a training plan permanently.
- [Get a trainee's active training plan](https://www.coach-platform.com/docs/api/reference/get-trainees-trainee-id-active-training-plan/index.md): `GET /api/public/trainees/{traineeId}/active-training-plan`. Get a trainee's currently active training plan (resolved via the active coaching period).
- [Duplicate a training plan](https://www.coach-platform.com/docs/api/reference/post-training-plans-plan-id-duplicate/index.md): `POST /api/public/training-plans/{planId}/duplicate`. Copy an existing training plan, including every exercise detail (per-set prescriptions, supersets, tempo, intensity, drop sets, alternatives).
- Previous: [Start a coaching period](https://www.coach-platform.com/docs/api/reference/post-escorts/index.md): `POST /api/public/escorts`. Start a new coaching period (escort) for a trainee.
- Next: [Create a training plan](https://www.coach-platform.com/docs/api/reference/post-training-plans/index.md): `POST /api/public/training-plans`. Create a training plan.
