# Get a training plan

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

Get a training plan by id.

- 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-plan-id
- OpenAPI spec: https://www.coach-platform.com/openapi.json

## Path parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `planId` | string | Yes |   |

## Responses

| Status | Description |
|---|---|
| `200` OK | Successful response |
| `400` Bad Request |  |
| `401` Unauthorized |  |
| `403` Forbidden |  |
| `404` Not Found |  |
| `409` Conflict |  |
| `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> |   |

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

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

### JavaScript (fetch)

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

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

## Related endpoints

- [List training plans](https://www.coach-platform.com/docs/api/reference/get-training-plans/index.md): `GET /api/public/training-plans`. List training plans.
- [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.
- [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: [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.
- Next: [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.
