Training

Workouts with their full tree of blocks, sets and repetitions, and the programs that schedule them.

Start with the workout data model. List endpoints return workouts and programs without their content. Fetch a single resource for the full tree.

List workouts

GET/workouts

Athlete workouts of your organization, without their content. Templates are excluded; they are served by /templates/workouts. Fetch a workout’s blocks, sets and metrics with GET /workouts/{id}.

Request

curl "https://api-next.vitruve.fit/v1/workouts?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62&from=2026-03-01&to=2026-03-31&limit=2" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": [
    {
      "id": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
      "name": "Lower body strength A",
      "isTemplate": false,
      "rpe": 8,
      "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
      "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
      "scheduledWorkoutId": null,
      "completedAt": "2026-03-17T10:41:52.318Z",
      "startedAt": "2026-03-17T09:58:04.902Z",
      "createdAt": "2026-03-10T16:20:11.004Z",
      "updatedAt": "2026-03-17T10:41:52.877Z",
      "deletedAt": null,
      "testType": null
    },
    {
      "id": "5a0e7c3d-91b4-4f26-8d58-c3e2a1f6b097",
      "name": "Upper body power",
      "isTemplate": false,
      "rpe": 7,
      "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
      "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
      "scheduledWorkoutId": null,
      "completedAt": "2026-03-14T17:32:10.441Z",
      "startedAt": "2026-03-14T16:55:47.019Z",
      "createdAt": "2026-03-14T16:55:46.870Z",
      "updatedAt": "2026-03-14T17:32:10.902Z",
      "deletedAt": null,
      "testType": null
    }
  ],
  "meta": {
    "limit": 2,
    "hasMore": true,
    "nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
  }
}

Query parameters

userIduuid
Only workouts of this athlete.
exerciseIduuid
Only workouts with at least one prescription of this exercise.
statuscompleted | pendingdefault completed
completed for performed workouts, pending for assigned workouts not yet performed.
trainingTypevbt | jump | sprint | reaction
Only workouts with at least one prescription of this training type.
fromdate
Inclusive lower bound: YYYY-MM-DD or an ISO 8601 datetime. A bare date starts at 00:00 in timezone, or at the change on a day whose midnight a daylight-saving change skips.
todate
Inclusive upper bound: YYYY-MM-DD or an ISO 8601 datetime. A bare date covers that whole day in timezone.
timezonestringdefault UTC
IANA time zone, such as Europe/Madrid. A bare from / to date covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes with Z or an offset are taken as given.
limitintegerdefault 50
Page size, 1–100.
cursorstring
meta.nextCursor from the previous page. Omit it to get the first page.

Notes

  • Completed workouts are sorted and filtered by completedAt; pending workouts by createdAt. Both are newest first.
  • from/to therefore apply to completedAt when status=completed and to createdAt when status=pending.
  • trainingType=vbt also matches prescriptions written before trainingType existed, which carry trainingType: null and isVbt: true.
  • With both exerciseId and trainingType, the same prescription must match both: a prescription of that exercise and that training type.
  • Workouts older than the history your plan includes are left out.

Response fields

iduuid
Workout id. Pass it to GET /workouts/{id} for the full tree.
namestring
Workout name.
userIduuid
Athlete the workout belongs to. Resolve with GET /athletes/{id}.
completedAtdatetimenullable
When the athlete finished the workout. null for pending workouts.
startedAtdatetimenullable
When the athlete started the workout.
rpeintegernullable
Session RPE entered by the athlete.
scheduledWorkoutIduuidnullable
Program slot this workout is attached to (phases[].scheduledWorkouts[].id in GET /programs/{id}). Unique: one workout per slot.
testTypestringnullable
Set when the workout is a standardized test (for example vertical_jump, t_test), otherwise null.
createdAtdatetime
When the workout was created or assigned.

Failures are described in error codes.

Get a workout

GET/workouts/{id}

One athlete workout with its full tree: blocks → prescriptions groups → prescriptions → serie prescriptions and series, each series with its values, set-level metrics and repetitions. Templates return 404 here; use GET /templates/workouts/{id}.

Request

curl "https://api-next.vitruve.fit/v1/workouts/f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
    "name": "Lower body strength A",
    "isTemplate": false,
    "rpe": 8,
    "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "scheduledWorkoutId": null,
    "completedAt": "2026-03-17T10:41:52.318Z",
    "startedAt": "2026-03-17T09:58:04.902Z",
    "createdAt": "2026-03-10T16:20:11.004Z",
    "updatedAt": "2026-03-17T10:41:52.877Z",
    "deletedAt": null,
    "testType": null,
    "blocks": [
      {
        "id": "0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79",
        "name": "Main lifts",
        "isTemplate": false,
        "order": 0,
        "workoutId": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
        "createdAt": "2026-03-10T16:20:11.004Z",
        "updatedAt": "2026-03-10T16:20:11.004Z",
        "deletedAt": null,
        "prescriptionsGroups": [
          {
            "id": "4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142",
            "name": "Back squat",
            "isTemplate": false,
            "order": 0,
            "blockId": "0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79",
            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
            "createdAt": "2026-03-10T16:20:11.004Z",
            "updatedAt": "2026-03-10T16:20:11.004Z",
            "deletedAt": null,
            "prescriptions": [
              {
                "id": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                "prescriptionsGroupId": "4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142",
                "name": "Back squat",
                "order": 0,
                "note": "Stop the set if mean velocity drops below 0.55 m/s.",
                "isTemplate": false,
                "isVbt": true,
                "trainingType": "vbt",
                "trainingAlgorithm": null,
                "createdAt": "2026-03-10T16:20:11.004Z",
                "updatedAt": "2026-03-10T16:20:11.004Z",
                "deletedAt": null,
                "seriePrescriptions": [
                  {
                    "id": "e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726",
                    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                    "prescriptionId": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                    "prescriptionTypeId": "3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05",
                    "unitId": "fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78",
                    "order": 0,
                    "isRange": false,
                    "isTopMode": false,
                    "createdAt": "2026-03-10T16:20:11.004Z",
                    "updatedAt": "2026-03-10T16:20:11.004Z",
                    "deletedAt": null
                  },
                  {
                    "id": "9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34",
                    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                    "prescriptionId": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                    "prescriptionTypeId": "62c8a0f4-3d19-4e7b-a5c2-f0b9d14e8a63",
                    "unitId": "b7e05a92-4f3c-4d18-86a1-2c9e7d3b5f40",
                    "order": 1,
                    "isRange": false,
                    "isTopMode": false,
                    "createdAt": "2026-03-10T16:20:11.004Z",
                    "updatedAt": "2026-03-10T16:20:11.004Z",
                    "deletedAt": null
                  }
                ],
                "series": [
                  {
                    "id": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                    "prescriptionId": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                    "order": 0,
                    "completedAt": "2026-03-17T10:06:30.512Z",
                    "createdAt": "2026-03-10T16:20:11.004Z",
                    "updatedAt": "2026-03-17T10:06:30.512Z",
                    "deletedAt": null,
                    "serieValues": [
                      {
                        "id": "0f6d2b84-a7e1-4c39-b05d-e9a3c8f1724b",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "seriePrescriptionId": "e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726",
                        "valuePrescriptedInf": null,
                        "valuePrescriptedSup": null,
                        "valuePrescripted": 100,
                        "valueExecuted": 100,
                        "createdAt": "2026-03-10T16:20:11.004Z",
                        "updatedAt": "2026-03-17T10:06:30.512Z",
                        "deletedAt": null
                      },
                      {
                        "id": "c5a19e37-04bd-4f62-8e7a-3b2d6f0c9a18",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "seriePrescriptionId": "9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34",
                        "valuePrescriptedInf": null,
                        "valuePrescriptedSup": null,
                        "valuePrescripted": 5,
                        "valueExecuted": 5,
                        "createdAt": "2026-03-10T16:20:11.004Z",
                        "updatedAt": "2026-03-17T10:06:30.512Z",
                        "deletedAt": null
                      }
                    ],
                    "metricValues": [
                      {
                        "id": "71e4c0a9-5d36-4b82-a1f7-9c8e2b4d0563",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
                        "value": 0.61,
                        "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                        "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                        "repetitionId": null,
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "createdAt": "2026-03-17T10:06:30.512Z",
                        "updatedAt": "2026-03-17T10:06:30.512Z",
                        "deletedAt": null
                      }
                    ],
                    "repetitions": [
                      {
                        "id": "e19a4d83-5b60-4c27-a8f1-0d7c3e52b946",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "type": "concentric",
                        "repNumber": 1,
                        "repIndex": 0,
                        "createdAt": "2026-03-17T10:05:58.140Z",
                        "updatedAt": "2026-03-17T10:05:58.140Z",
                        "deletedAt": null,
                        "metricValues": [
                          {
                            "id": "86a1c4e7-3b05-4d9f-92e8-5f1d7c0a3b94",
                            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                            "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
                            "value": 0.64,
                            "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                            "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                            "repetitionId": "e19a4d83-5b60-4c27-a8f1-0d7c3e52b946",
                            "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                            "createdAt": "2026-03-17T10:05:58.140Z",
                            "updatedAt": "2026-03-17T10:05:58.140Z",
                            "deletedAt": null
                          },
                          {
                            "id": "3c7e9b20-a5f1-4d86-b2c4-71d0e8f3a659",
                            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                            "metricId": "2a9c6e41-b0d8-4f73-9e15-84d3c7a0b2f6",
                            "value": 1.12,
                            "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                            "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                            "repetitionId": "e19a4d83-5b60-4c27-a8f1-0d7c3e52b946",
                            "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                            "createdAt": "2026-03-17T10:05:58.140Z",
                            "updatedAt": "2026-03-17T10:05:58.140Z",
                            "deletedAt": null
                          }
                        ]
                      },
                      {
                        "id": "48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "type": "concentric",
                        "repNumber": 2,
                        "repIndex": 1,
                        "createdAt": "2026-03-17T10:06:03.377Z",
                        "updatedAt": "2026-03-17T10:06:03.377Z",
                        "deletedAt": null,
                        "metricValues": [
                          {
                            "id": "d9c2a5e0-8b17-4f4d-a36e-5e0b7c1f9d84",
                            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                            "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
                            "value": 0.62,
                            "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                            "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                            "repetitionId": "48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2",
                            "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                            "createdAt": "2026-03-17T10:06:03.377Z",
                            "updatedAt": "2026-03-17T10:06:03.377Z",
                            "deletedAt": null
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • Every level is ordered by order, then id; repetitions by repIndex, then id. Deleted rows are never returned.
  • serieValues are returned in the unitId of their serie prescription, as the app shows them (for example lb when the parameter is in lb).
  • metricValues[].value is in the metric’s own unit, see GET /metrics/{id}. Repetition metrics appear only under repetitions[], never in the set’s metricValues.
  • Prescriptions written before trainingType existed carry trainingType: null and isVbt: true for VBT.
  • A workout older than the history your plan includes answers 404.
  • Pending workouts have completedAt: null and usually no valueExecuted, metrics or repetitions yet.
  • Raw encoder data is not exposed.

Response fields

namestring
Workout name.
userIduuid
Athlete the workout belongs to. Resolve with GET /athletes/{id}.
completedAtdatetimenullable
When the athlete finished the workout. null for pending workouts.
startedAtdatetimenullable
When the athlete started the workout.
rpeintegernullable
Session RPE entered by the athlete.
scheduledWorkoutIduuidnullable
Program slot this workout is attached to (phases[].scheduledWorkouts[].id in GET /programs/{id}). Unique: one workout per slot.
testTypestringnullable
Set when the workout is a standardized test (for example vertical_jump, t_test), otherwise null.
createdAtdatetime
When the workout was created or assigned.
blocks[]object[]
Blocks, ordered by order.
blocks[].prescriptionsGroups[]object[]
Groups, ordered by order. A group with more than one prescription is a superset.
blocks[].prescriptionsGroups[].prescriptions[]object[]
One exercise each, ordered by order.
…prescriptions[].exerciseIduuid
Exercise performed. Resolve with GET /exercises/{id}.
…prescriptions[].trainingTypestringnullable
vbt, jump, sprint or reaction. null on rows written before the field existed; read isVbt then.
…prescriptions[].trainingAlgorithmstringnullable
Variant within the training type, for example 10-5 for jump or go-no-go for reaction.
…prescriptions[].notestringnullable
Coach note for the exercise.
…prescriptions[].seriePrescriptions[]object[]
The prescribed parameters (load, reps, velocity target…), ordered by order.
…seriePrescriptions[].prescriptionTypeIduuid
What the parameter is. Resolve with GET /prescription-types/{id}.
…seriePrescriptions[].unitIduuid
Unit the parameter’s serieValues are expressed in. Resolve with GET /units/{id}.
…seriePrescriptions[].isRangebooleannullable
When true, the target is valuePrescriptedInf–valuePrescriptedSup instead of valuePrescripted.
…prescriptions[].series[]object[]
Sets, ordered by order.
…series[].completedAtdatetimenullable
When the set was completed.
…series[].serieValues[]object[]
One value per serie prescription, linked by seriePrescriptionId.
…serieValues[].valuePrescriptednumbernullable
Prescribed value, in the unitId of its serie prescription.
…serieValues[].valuePrescriptedInfnumbernullable
Lower bound of a prescribed range, same unit.
…serieValues[].valuePrescriptedSupnumbernullable
Upper bound of a prescribed range, same unit.
…serieValues[].valueExecutednumbernullable
Value actually performed, same unit. null until the set is done.
…series[].metricValues[]object[]
Metrics captured for the whole set (repetitionId: null).
…metricValues[].metricIduuid
Metric measured. Resolve with GET /metrics/{id}.
…metricValues[].valuenumber
Measured value, in the metric’s unitId.
…series[].repetitions[]object[]
Repetitions, ordered by repIndex.
…repetitions[].repNumberinteger
Repetition number as shown in the app.
…repetitions[].repIndexinteger
Zero-based position of the repetition in the set.
…repetitions[].typestringnullable
concentric or eccentric. null on older rows: read it as “not eccentric”.
…repetitions[].metricValues[]object[]
Metrics captured for this repetition.

Failures are described in error codes.

List active workouts

GET/active-workouts

Sessions your athletes are performing right now, without their content. A session leaves this list when the athlete finishes it (it is then in GET /workouts) or discards it. Fetch one with GET /active-workouts/{id}.

Request

curl "https://api-next.vitruve.fit/v1/active-workouts?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": [
    {
      "id": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
      "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
      "version": 12,
      "createdAt": "2026-03-17T09:58:05.114Z",
      "updatedAt": "2026-03-17T10:21:37.502Z"
    }
  ],
  "meta": {
    "limit": 50,
    "hasMore": true,
    "nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
  }
}

Query parameters

userIduuid
Only the sessions of this athlete.
limitintegerdefault 50
Page size, 1–100.
cursorstring
meta.nextCursor from the previous page. Omit it to get the first page.

Notes

  • Newest first, by createdAt.
  • A session the app stopped saving long ago may still be listed until Vitruve discards it; read updatedAt.

Response fields

iduuid
Session id. It keeps this id as a workout once finished. Pass it to GET /active-workouts/{id} for its sets so far.
userIduuid
Athlete performing the session.
versioninteger
Grows by one every time the app saves the session.
createdAtdatetime
When the app first saved the session.
updatedAtdatetime
When the app last saved the session.

Failures are described in error codes.

Get an active workout

GET/active-workouts/{id}

One session in progress as the app last saved it, in the same tree as GET /workouts/{id}: the sets done so far with their values, set-level metrics and repetitions.

Request

curl "https://api-next.vitruve.fit/v1/active-workouts/f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
    "name": "Lower body strength A",
    "isTemplate": false,
    "rpe": 8,
    "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "scheduledWorkoutId": null,
    "completedAt": null,
    "startedAt": "2026-03-17T09:58:04.902Z",
    "createdAt": "2026-03-10T16:20:11.004Z",
    "updatedAt": "2026-03-17T10:21:37.502Z",
    "deletedAt": null,
    "testType": null,
    "blocks": [
      {
        "id": "0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79",
        "name": "Main lifts",
        "isTemplate": false,
        "order": 0,
        "workoutId": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
        "createdAt": "2026-03-10T16:20:11.004Z",
        "updatedAt": "2026-03-10T16:20:11.004Z",
        "deletedAt": null,
        "prescriptionsGroups": [
          {
            "id": "4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142",
            "name": "Back squat",
            "isTemplate": false,
            "order": 0,
            "blockId": "0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79",
            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
            "createdAt": "2026-03-10T16:20:11.004Z",
            "updatedAt": "2026-03-10T16:20:11.004Z",
            "deletedAt": null,
            "prescriptions": [
              {
                "id": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                "prescriptionsGroupId": "4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142",
                "name": "Back squat",
                "order": 0,
                "note": "Stop the set if mean velocity drops below 0.55 m/s.",
                "isTemplate": false,
                "isVbt": true,
                "trainingType": "vbt",
                "trainingAlgorithm": null,
                "createdAt": "2026-03-10T16:20:11.004Z",
                "updatedAt": "2026-03-10T16:20:11.004Z",
                "deletedAt": null,
                "seriePrescriptions": [
                  {
                    "id": "e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726",
                    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                    "prescriptionId": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                    "prescriptionTypeId": "3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05",
                    "unitId": "fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78",
                    "order": 0,
                    "isRange": false,
                    "isTopMode": false,
                    "createdAt": "2026-03-10T16:20:11.004Z",
                    "updatedAt": "2026-03-10T16:20:11.004Z",
                    "deletedAt": null
                  },
                  {
                    "id": "9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34",
                    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                    "prescriptionId": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                    "prescriptionTypeId": "62c8a0f4-3d19-4e7b-a5c2-f0b9d14e8a63",
                    "unitId": "b7e05a92-4f3c-4d18-86a1-2c9e7d3b5f40",
                    "order": 1,
                    "isRange": false,
                    "isTopMode": false,
                    "createdAt": "2026-03-10T16:20:11.004Z",
                    "updatedAt": "2026-03-10T16:20:11.004Z",
                    "deletedAt": null
                  }
                ],
                "series": [
                  {
                    "id": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                    "prescriptionId": "a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8",
                    "order": 0,
                    "completedAt": "2026-03-17T10:06:30.512Z",
                    "createdAt": "2026-03-10T16:20:11.004Z",
                    "updatedAt": "2026-03-17T10:06:30.512Z",
                    "deletedAt": null,
                    "serieValues": [
                      {
                        "id": "0f6d2b84-a7e1-4c39-b05d-e9a3c8f1724b",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "seriePrescriptionId": "e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726",
                        "valuePrescriptedInf": null,
                        "valuePrescriptedSup": null,
                        "valuePrescripted": 100,
                        "valueExecuted": 100,
                        "createdAt": "2026-03-10T16:20:11.004Z",
                        "updatedAt": "2026-03-17T10:06:30.512Z",
                        "deletedAt": null
                      },
                      {
                        "id": "c5a19e37-04bd-4f62-8e7a-3b2d6f0c9a18",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "seriePrescriptionId": "9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34",
                        "valuePrescriptedInf": null,
                        "valuePrescriptedSup": null,
                        "valuePrescripted": 5,
                        "valueExecuted": 5,
                        "createdAt": "2026-03-10T16:20:11.004Z",
                        "updatedAt": "2026-03-17T10:06:30.512Z",
                        "deletedAt": null
                      }
                    ],
                    "metricValues": [
                      {
                        "id": "71e4c0a9-5d36-4b82-a1f7-9c8e2b4d0563",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
                        "value": 0.61,
                        "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                        "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                        "repetitionId": null,
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "createdAt": "2026-03-17T10:06:30.512Z",
                        "updatedAt": "2026-03-17T10:06:30.512Z",
                        "deletedAt": null
                      }
                    ],
                    "repetitions": [
                      {
                        "id": "e19a4d83-5b60-4c27-a8f1-0d7c3e52b946",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "type": "concentric",
                        "repNumber": 1,
                        "repIndex": 0,
                        "createdAt": "2026-03-17T10:05:58.140Z",
                        "updatedAt": "2026-03-17T10:05:58.140Z",
                        "deletedAt": null,
                        "metricValues": [
                          {
                            "id": "86a1c4e7-3b05-4d9f-92e8-5f1d7c0a3b94",
                            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                            "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
                            "value": 0.64,
                            "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                            "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                            "repetitionId": "e19a4d83-5b60-4c27-a8f1-0d7c3e52b946",
                            "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                            "createdAt": "2026-03-17T10:05:58.140Z",
                            "updatedAt": "2026-03-17T10:05:58.140Z",
                            "deletedAt": null
                          },
                          {
                            "id": "3c7e9b20-a5f1-4d86-b2c4-71d0e8f3a659",
                            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                            "metricId": "2a9c6e41-b0d8-4f73-9e15-84d3c7a0b2f6",
                            "value": 1.12,
                            "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                            "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                            "repetitionId": "e19a4d83-5b60-4c27-a8f1-0d7c3e52b946",
                            "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                            "createdAt": "2026-03-17T10:05:58.140Z",
                            "updatedAt": "2026-03-17T10:05:58.140Z",
                            "deletedAt": null
                          }
                        ]
                      },
                      {
                        "id": "48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2",
                        "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                        "type": "concentric",
                        "repNumber": 2,
                        "repIndex": 1,
                        "createdAt": "2026-03-17T10:06:03.377Z",
                        "updatedAt": "2026-03-17T10:06:03.377Z",
                        "deletedAt": null,
                        "metricValues": [
                          {
                            "id": "d9c2a5e0-8b17-4f4d-a36e-5e0b7c1f9d84",
                            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
                            "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
                            "value": 0.62,
                            "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
                            "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
                            "repetitionId": "48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2",
                            "serieId": "68c2e5b1-0d47-4a93-9f6e-b13a7d84c250",
                            "createdAt": "2026-03-17T10:06:03.377Z",
                            "updatedAt": "2026-03-17T10:06:03.377Z",
                            "deletedAt": null
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ],
    "version": 12
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • Same units, order and fields as GET /workouts/{id}: serieValues in the unit of their serie prescription, deleted rows left out, raw encoder data never exposed.
  • To poll a session, send the last ETag you received back as If-None-Match: while the app hasn’t saved again the answer is 304 Not Modified with no body, and it doesn’t read the session.
  • A finished or discarded session answers 404; read a finished one with GET /workouts/{id}.

Response fields

versioninteger
Grows by one every time the app saves the session. Also sent as the ETag header.
updatedAtdatetime
When the app last saved the session.
blocks[]object[]
The same tree as GET /workouts/{id}. Sets not done yet have completedAt: null.

Failures are described in error codes.

List programs

GET/programs

Programs of your organization, newest first, each with the ids of its assigned athletes.

Request

curl "https://api-next.vitruve.fit/v1/programs?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62&isTemplate=false" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": [
    {
      "id": "2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53",
      "name": "Pre-season strength block",
      "isTemplate": false,
      "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
      "startedAt": "2026-03-02T00:00:00.000Z",
      "createdAt": "2026-02-24T11:05:42.610Z",
      "updatedAt": "2026-03-01T18:12:09.233Z",
      "deletedAt": null,
      "users": [
        {
          "id": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"
        },
        {
          "id": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"
        }
      ]
    }
  ],
  "meta": {
    "limit": 50,
    "hasMore": true,
    "nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
  }
}

Query parameters

isTemplateboolean
true for program templates only, false for programs that are not templates. Omit for both.
userIduuid
Only programs assigned to this athlete.
searchstring
Case-insensitive match on the program name.
limitintegerdefault 50
Page size, 1–100.
cursorstring
meta.nextCursor from the previous page. Omit it to get the first page.

Notes

  • Sorted by createdAt, newest first.

Response fields

iduuid
Program id. Pass it to GET /programs/{id} for its phases.
namestring
Program name.
isTemplatebooleannullable
true for templates. Older rows store null, which means not a template.
startedAtdatetimenullable
Start date of the program’s first phase.
users[].iduuid
Assigned athletes. Resolve with GET /athletes/{id}.

Failures are described in error codes.

Get a program

GET/programs/{id}

One program with its assigned athletes and its phases, each with its scheduled workouts and the workout row they point to.

Request

curl "https://api-next.vitruve.fit/v1/programs/2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53",
    "name": "Pre-season strength block",
    "isTemplate": false,
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "startedAt": "2026-03-02T00:00:00.000Z",
    "createdAt": "2026-02-24T11:05:42.610Z",
    "updatedAt": "2026-03-01T18:12:09.233Z",
    "deletedAt": null,
    "users": [
      {
        "id": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"
      },
      {
        "id": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"
      }
    ],
    "phases": [
      {
        "id": "b45e0c97-1a68-4d32-9c7f-82f3d6a1e0b4",
        "name": "Accumulation",
        "isTemplate": false,
        "order": 0,
        "weeks": 4,
        "programId": "2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53",
        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
        "createdAt": "2026-02-24T11:05:42.610Z",
        "updatedAt": "2026-02-24T11:05:42.610Z",
        "deletedAt": null,
        "scheduledWorkouts": [
          {
            "id": "73d9f1c8-e526-4a0b-b4d3-9e8a2c5f6710",
            "color": "#4C8BF5",
            "phaseId": "b45e0c97-1a68-4d32-9c7f-82f3d6a1e0b4",
            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
            "include": [],
            "exclude": [
              14
            ],
            "recurrence": [
              0,
              3
            ],
            "createdAt": "2026-02-24T11:05:42.610Z",
            "updatedAt": "2026-02-24T11:05:42.610Z",
            "deletedAt": null,
            "workout": {
              "id": "a3d81f6c-07e5-4b29-9c4a-e5f2b0d7c813",
              "name": "Lower body strength A",
              "isTemplate": false,
              "rpe": null,
              "userId": null,
              "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
              "scheduledWorkoutId": "73d9f1c8-e526-4a0b-b4d3-9e8a2c5f6710",
              "completedAt": null,
              "startedAt": null,
              "createdAt": "2026-02-24T11:05:42.610Z",
              "updatedAt": "2026-02-24T11:05:42.610Z",
              "deletedAt": null,
              "testType": null
            }
          },
          {
            "id": "f0a7d3c6-29e8-4b51-9c04-a6b1e8d2f375",
            "color": null,
            "phaseId": "b45e0c97-1a68-4d32-9c7f-82f3d6a1e0b4",
            "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
            "include": [
              26
            ],
            "exclude": [],
            "recurrence": [],
            "createdAt": "2026-02-24T11:07:15.032Z",
            "updatedAt": "2026-02-24T11:07:15.032Z",
            "deletedAt": null,
            "workout": {
              "id": "e86b2c47-d150-4f3a-a8e9-2f7c4d06b5a1",
              "name": "Jump test",
              "isTemplate": false,
              "rpe": null,
              "userId": null,
              "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
              "scheduledWorkoutId": "f0a7d3c6-29e8-4b51-9c04-a6b1e8d2f375",
              "completedAt": null,
              "startedAt": null,
              "createdAt": "2026-02-24T11:07:15.032Z",
              "updatedAt": "2026-02-24T11:07:15.032Z",
              "deletedAt": null,
              "testType": "vertical_jump"
            }
          }
        ]
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • recurrence, include and exclude are returned as the Vitruve planner stores them. A slot falls on phase day d when d is in include, or when d % 7 is in recurrence and d is not in exclude.
  • A phase starts at startedAt plus the weeks × 7 days of every earlier phase.
  • Scheduled workouts whose workout was deleted are left out.
  • GET /workouts/{id} only serves workouts that have a userId and are not templates, and GET /templates/workouts/{id} only templates. A slot’s workout with userId: null and isTemplate: false is returned here without its content.

Response fields

users[].iduuid
Assigned athletes. Resolve with GET /athletes/{id}.
phases[]object[]
Phases, ordered by order. They run back to back from startedAt.
phases[].weeksintegernullable
Phase length in weeks.
phases[].scheduledWorkouts[]object[]
Workouts placed in the phase, oldest first.
phases[].scheduledWorkouts[].includeinteger[]
Single occurrences, as day offsets from the phase start (0 = first day of the phase).
phases[].scheduledWorkouts[].recurrenceinteger[]
Weekly repeat, as days 0–6 of each week counted from the phase start (not calendar weekdays). Repeats for every week of the phase.
phases[].scheduledWorkouts[].excludeinteger[]
Day offsets from the phase start removed from the weekly repeat.
phases[].scheduledWorkouts[].workoutobject
The workout row the slot points to, without its content.

Failures are described in error codes.

Get a program's attendance

GET/programs/{id}/attendance

How far a program’s athletes are keeping to it: every planned session that is already due, matched to the sessions they performed, per athlete, per team and per planned session. The same figures as the program page of the Vitruve app.

Request

curl "https://api-next.vitruve.fit/v1/programs/2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53/attendance?timezone=Europe%2FMadrid" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "programId": "2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53",
    "asOf": "2026-03-25",
    "startDateKey": "2026-02-24",
    "endDateKey": "2026-04-21",
    "overall": {
      "athletesCount": 2,
      "due": 18,
      "fulfilled": 15,
      "missed": 3,
      "rate": 0.8333
    },
    "completion": {
      "total": 32,
      "completed": 15,
      "remaining": 17
    },
    "athletes": [
      {
        "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
        "due": 9,
        "fulfilled": 9,
        "missed": 0,
        "rate": 1,
        "unplanned": 1
      },
      {
        "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
        "due": 9,
        "fulfilled": 6,
        "missed": 3,
        "rate": 0.6667,
        "unplanned": 0
      }
    ],
    "teams": [
      {
        "teamId": "9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64",
        "name": "First team",
        "athletesCount": 2,
        "due": 18,
        "fulfilled": 15,
        "missed": 3,
        "rate": 0.8333
      }
    ],
    "occurrences": [
      {
        "scheduledWorkoutId": "73d9f1c8-e526-4a0b-b4d3-9e8a2c5f6710",
        "name": "Lower body strength A",
        "dateKey": "2026-02-24",
        "due": 2,
        "fulfilled": 2,
        "rate": 1
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Query parameters

timezonestringdefault UTC
IANA time zone, such as Europe/Madrid. Decides what “today” is, and so which sessions are already due.

Notes

  • A planned session counts as performed when the athlete completed it from the program, on its day or one day either side. One that is still today’s, or yesterday’s, is not due yet: it is neither performed nor missed.
  • Only athletes still in the organization count, in every figure.
  • Templates and programs of another organization answer 404.

Response fields

asOfstring
Today in timezone (YYYY-MM-DD): the figures count the sessions due up to it.
startDateKeystringnullable
First day of the program. null when it hasn’t been started: nothing is due.
endDateKeystringnullable
The day after the last day of its last phase.
overallobject
The program’s athletes together: due (planned sessions already due), fulfilled (performed), missed, and rate (fulfilled / due, null while nothing is due).
completionobject
Progress through the whole plan: total planned sessions, including those not due yet, completed and remaining.
athletes[]object[]
One row per athlete of the program, in roster order, with the same counts. unplanned counts sessions performed during the program that weren’t started from a program session.
teams[]object[]
Each team with at least one of the program’s athletes, totalled over those athletes only.
occurrences[]object[]
Each planned session that is due (scheduledWorkoutId from GET /programs/{id}, its workout name, its dateKey), with how many of its athletes performed it. Oldest first.

Failures are described in error codes.

Get a program's effectiveness

GET/programs/{id}/effectiveness

How a program’s athletes are progressing towards its goals: each goal (a metric, how it is aggregated, increase, decrease or reach, and a target) evaluated per athlete and for the group, with where the group should be by now. The same figures as the program page of the Vitruve app.

Request

curl "https://api-next.vitruve.fit/v1/programs/2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53/effectiveness?timezone=Europe%2FMadrid" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "programId": "2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53",
    "asOf": "2026-03-25",
    "startDateKey": "2026-02-24",
    "endDateKey": "2026-04-21",
    "timeShare": 0.5179,
    "goals": [
      {
        "goal": {
          "id": "d8c41f27-5a9e-4b03-a6f2-0e7b3c95d184",
          "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
          "calculation": "max",
          "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
          "condition": "increase",
          "target": 5
        },
        "athletes": [
          {
            "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
            "baseline": 0.92,
            "current": 0.97,
            "changePct": 5.43,
            "achieved": true,
            "progress": 1,
            "ratio": 1.087
          },
          {
            "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
            "baseline": 0.88,
            "current": 0.9,
            "changePct": 2.27,
            "achieved": false,
            "progress": 0.4545,
            "ratio": 0.4545
          }
        ],
        "summary": {
          "evaluated": 2,
          "achieved": 1,
          "achievedShare": 0.5,
          "meanChangePct": 3.85,
          "meanProgress": 0.7273
        },
        "expectedProgress": 0.5179,
        "series": {
          "points": [
            {
              "dateKey": "2026-02-24",
              "value": 0
            },
            {
              "dateKey": "2026-03-02",
              "value": 0.21
            },
            {
              "dateKey": "2026-03-25",
              "value": 0.7273
            }
          ],
          "projection": [
            {
              "dateKey": "2026-02-24",
              "value": 0
            },
            {
              "dateKey": "2026-04-20",
              "value": 1
            }
          ]
        }
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Query parameters

timezonestringdefault UTC
IANA time zone, such as Europe/Madrid. Decides what “today” is and which calendar day each measurement falls on.

Notes

  • The baseline is the four weeks before the start. An athlete with no data in them is measured from their first two program weeks instead.
  • Only athletes still in the organization count, in every figure.
  • Templates and programs of another organization answer 404.

Response fields

asOfstring
Today in timezone (YYYY-MM-DD). Once the program is over, its goals are judged on its last day.
startDateKeystringnullable
First day of the program. null when it hasn’t been started: goals is empty.
endDateKeystringnullable
The day after the last day of its last phase.
timeSharenumbernullable
Share of the program elapsed by the end of asOf, from 0 to 1.
goals[]object[]
One entry per goal of the program, in its order. Empty before the start, or when the program has no goals.
goals[].athletes[]object[]
One row per athlete of the program, in roster order: baseline and current (the goal’s calculation over comparable windows, in the metric’s base unit), changePct, achieved, progress (towards the target, from -1 to 1) and ratio (unclamped). null where the athlete has no data.
goals[].summaryobject
The athletes together: evaluated, achieved, achievedShare, meanChangePct and meanProgress (the mean of the clamped progress).
goals[].expectedProgressnumber
Where the group should be by now if it progresses evenly. summary.meanProgress below it means behind schedule.
goals[].seriesobject
For a chart: points, the group progress at the end of every program week and on the evaluated day, and projection, the planned progress from 0 at the start to 1 on the last day.
goals[].errorstring
Present when this goal could not be read. The other goals are still evaluated.

Failures are described in error codes.

On this page