Measurements

Load-velocity profiles, leaderboards, wellness questionnaires and injury reports. Load-velocity profiles and injury reports can also be written.

These endpoints read what is derived from workouts and recorded beside them. Resolve metricId, exerciseId and unitId with the catalogs.

Load-velocity profiles and injury reports can also be created, updated and deleted. The writes need your organization's own API key and follow the write rules.

List load-velocity profiles

GET/equations

Load-velocity profiles of your organization’s athletes, newest first: the fitted coefficients without the points they were fitted on.

Request

curl "https://api-next.vitruve.fit/v1/equations?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62&exerciseId=1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7&isSelected=true" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": [
    {
      "id": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
      "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
      "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
      "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
      "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
      "name": "Back squat LVP",
      "a": 0,
      "b": -64.286,
      "c": 119.286,
      "r2": 0.987,
      "isSelected": true,
      "createdAt": "2026-02-04T09:12:00.000Z",
      "updatedAt": "2026-02-04T09:12:00.000Z",
      "deletedAt": null
    }
  ],
  "meta": {
    "limit": 50,
    "hasMore": true,
    "nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
  }
}

Query parameters

userIduuid
Only profiles of this athlete.
exerciseIduuid
Only profiles of this exercise.
metricIduuid
Only profiles fitted on this velocity metric.
isSelectedboolean
true for the profiles the app uses, false for the others.
limitintegerdefault 50
Page size, 1–100.
cursorstring
meta.nextCursor from the previous page. Omit it to get the first page.

Notes

  • The list has no equationSeries. Fetch GET /equations/{id} for the points.

Response fields

iduuid
Equation id.
userIduuidnullable
Athlete the profile belongs to. Resolve with GET /athletes/{id}.
exerciseIduuidnullable
Exercise profiled. Resolve with GET /exercises/{id}.
metricIduuidnullable
Velocity metric the profile is fitted on. Resolve with GET /metrics/{id}.
anumbernullable
Always 0: profiles are linear. Load as % of 1RM = b·v + c, with v the velocity in m/s.
bnumbernullable
Slope, in %1RM per m/s.
cnumbernullable
Intercept, in %1RM.
r2numbernullable
Goodness of fit, 0–1.
isSelectedboolean
Whether this is the profile the app uses for the athlete and exercise.

Failures are described in error codes.

Get a load-velocity profile

GET/equations/{id}

One load-velocity profile with the points it was fitted on (equationSeries), in order.

Request

curl "https://api-next.vitruve.fit/v1/equations/ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
    "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
    "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
    "name": "Back squat LVP",
    "a": 0,
    "b": -64.286,
    "c": 119.286,
    "r2": 0.987,
    "isSelected": true,
    "createdAt": "2026-02-04T09:12:00.000Z",
    "updatedAt": "2026-02-04T09:12:00.000Z",
    "deletedAt": null,
    "equationSeries": [
      {
        "id": "5a9c2e71-d4b8-4f06-a3e9-17c0b6d8f2a4",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 60,
        "velocity": 1.14,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 0
      },
      {
        "id": "c38f0b5d-7e2a-4c91-b6d4-e09a3f1c7b58",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 80,
        "velocity": 0.9,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 1
      },
      {
        "id": "81d6a4f3-0c5e-4b27-9a8f-d3e2b7c05a19",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 100,
        "velocity": 0.66,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 2
      },
      {
        "id": "e72b9c08-3f1d-4a65-8e4b-6c0d9a2f7b31",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 115,
        "velocity": 0.48,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 3
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Response fields

iduuid
Equation id.
userIduuidnullable
Athlete the profile belongs to. Resolve with GET /athletes/{id}.
exerciseIduuidnullable
Exercise profiled. Resolve with GET /exercises/{id}.
metricIduuidnullable
Velocity metric the profile is fitted on. Resolve with GET /metrics/{id}.
anumbernullable
Always 0: profiles are linear. Load as % of 1RM = b·v + c, with v the velocity in m/s.
bnumbernullable
Slope, in %1RM per m/s.
cnumbernullable
Intercept, in %1RM.
r2numbernullable
Goodness of fit, 0–1.
isSelectedboolean
Whether this is the profile the app uses for the athlete and exercise.
equationSeries[]object[]
Fitted points, sorted by order.
equationSeries[].weightnumber
Load lifted, in kg.
equationSeries[].velocitynumber
Velocity at that load, in m/s.

Failures are described in error codes.

Create a load-velocity profile

An athlete has one selected profile per exercise: the one Vitruve uses to estimate loads. A new profile becomes the selected one. Profiles are linear: load as % of 1RM = b·velocity (m/s) + c.

POST/equations

Creates a load-velocity profile and makes it the athlete’s selected one for the exercise. Answers it in the shape of GET /equations/{id}.

Request

curl -X POST "https://api-next.vitruve.fit/v1/equations" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: YOUR_OPERATION_ID" \
  -d '{
    "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
    "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
    "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
    "name": "Back squat LVP",
    "b": -61.9,
    "c": 117.4,
    "r2": 0.991,
    "equationSeries": [
      {
        "weight": 70,
        "velocity": 1.02
      },
      {
        "weight": 90,
        "velocity": 0.81
      },
      {
        "weight": 110,
        "velocity": 0.57
      }
    ]
  }'

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
    "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
    "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
    "name": "Back squat LVP",
    "a": 0,
    "b": -61.9,
    "c": 117.4,
    "r2": 0.991,
    "isSelected": true,
    "createdAt": "2026-10-13T09:42:17.551Z",
    "updatedAt": "2026-10-13T09:42:17.551Z",
    "deletedAt": null,
    "equationSeries": [
      {
        "id": "0f6a2d94-7c1e-4b38-a5d0-93e7b1c4f826",
        "equationId": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
        "weight": 70,
        "velocity": 1.02,
        "createdAt": "2026-10-13T09:42:17.551Z",
        "updatedAt": "2026-10-13T09:42:17.551Z",
        "order": 0
      },
      {
        "id": "d35b8e10-49f2-4a67-8c1b-2e6f0a9d7c53",
        "equationId": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
        "weight": 90,
        "velocity": 0.81,
        "createdAt": "2026-10-13T09:42:17.551Z",
        "updatedAt": "2026-10-13T09:42:17.551Z",
        "order": 1
      },
      {
        "id": "7e19c4b2-a053-4d8e-b6f7-c0d2915a3e48",
        "equationId": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
        "weight": 110,
        "velocity": 0.57,
        "createdAt": "2026-10-13T09:42:17.551Z",
        "updatedAt": "2026-10-13T09:42:17.551Z",
        "order": 2
      }
    ]
  }
}

Headers

Idempotency-Keystring
Request header. 1 to 255 visible ASCII characters you choose per operation, such as a UUID or your own record’s id. A retry with the same key and the same request returns the first answer instead of creating again.

Body

userIduuidrequired
Athlete of your organization.
exerciseIduuidrequired
A load-velocity exercise, global or your own: not a jump, sprint or reaction one.
metricIduuidrequired
Velocity metric the profile is fitted on. See GET /metrics?isEquationMetric=true.
namestringnullable
Profile name, up to 255 characters.
anumber
Only 0: profiles are linear. Any other value answers 400.
bnumberrequired
Slope: load as % of 1RM = b·velocity (m/s) + c.
cnumberrequired
Intercept, in %1RM.
r2numbernullable
Goodness of fit, 0–1.
equationSeriesobject[]
The tested sets, in order, at most 100: weight in kg and velocity in m/s, both 0 or more.

Notes

  • The athlete’s other profiles for the exercise are unselected: an athlete has one selected profile per exercise, the one Vitruve uses to estimate loads.
  • 400 when the athlete, the exercise or the metric doesn’t qualify. message names each field.
  • Send an Idempotency-Key header to retry the create safely after a timeout: a retry with the same key and body answers the first result instead of creating again.

Failures are described in error codes.

Update a load-velocity profile

Request body: any of these fields, at least one.

FieldTypeDescription
namestring or nullProfile name, up to 255 characters.
anumberOnly 0: profiles are linear. Any other value answers 400.
bnumberSlope: load as % of 1RM = b·velocity (m/s) + c.
cnumberIntercept, in %1RM.
r2number or nullGoodness of fit, 0–1.
isSelectedbooleanOnly true: makes this the athlete’s selected profile for the exercise and unselects the others. To unselect a profile, select another one.
equationSeriesobject[]The tested sets, in order, at most 100: weight in kg and velocity in m/s, both 0 or more. Replaces the current points.
PATCH/equations/{id}

Changes only the fields sent, and answers the updated profile with its points.

Request

curl -X PATCH "https://api-next.vitruve.fit/v1/equations/ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Back squat LVP, March"
  }'

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
    "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
    "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
    "name": "Back squat LVP, March",
    "a": 0,
    "b": -64.286,
    "c": 119.286,
    "r2": 0.987,
    "isSelected": true,
    "createdAt": "2026-02-04T09:12:00.000Z",
    "updatedAt": "2026-10-13T09:44:03.127Z",
    "deletedAt": null,
    "equationSeries": [
      {
        "id": "5a9c2e71-d4b8-4f06-a3e9-17c0b6d8f2a4",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 60,
        "velocity": 1.14,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 0
      },
      {
        "id": "c38f0b5d-7e2a-4c91-b6d4-e09a3f1c7b58",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 80,
        "velocity": 0.9,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 1
      },
      {
        "id": "81d6a4f3-0c5e-4b27-9a8f-d3e2b7c05a19",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 100,
        "velocity": 0.66,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 2
      },
      {
        "id": "e72b9c08-3f1d-4a65-8e4b-6c0d9a2f7b31",
        "equationId": "ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
        "weight": 115,
        "velocity": 0.48,
        "createdAt": "2026-02-04T09:12:00.000Z",
        "updatedAt": "2026-02-04T09:12:00.000Z",
        "order": 3
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Body

namestringnullable
Profile name, up to 255 characters.
anumber
Only 0: profiles are linear. Any other value answers 400.
bnumber
Slope: load as % of 1RM = b·velocity (m/s) + c.
cnumber
Intercept, in %1RM.
r2numbernullable
Goodness of fit, 0–1.
isSelectedboolean
Only true: makes this the athlete’s selected profile for the exercise and unselects the others. To unselect a profile, select another one.
equationSeriesobject[]
The tested sets, in order, at most 100: weight in kg and velocity in m/s, both 0 or more. Replaces the current points.

Notes

  • Rows of an athlete no longer in your organization answer 404.

Failures are described in error codes.

Delete a load-velocity profile

DELETE/equations/{id}

Deletes a load-velocity profile for good and answers it as it was, with its points.

Request

curl -X DELETE "https://api-next.vitruve.fit/v1/equations/b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
    "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
    "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
    "name": "Back squat LVP",
    "a": 0,
    "b": -61.9,
    "c": 117.4,
    "r2": 0.991,
    "isSelected": true,
    "createdAt": "2026-10-13T09:42:17.551Z",
    "updatedAt": "2026-10-13T09:42:17.551Z",
    "deletedAt": null,
    "equationSeries": [
      {
        "id": "0f6a2d94-7c1e-4b38-a5d0-93e7b1c4f826",
        "equationId": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
        "weight": 70,
        "velocity": 1.02,
        "createdAt": "2026-10-13T09:42:17.551Z",
        "updatedAt": "2026-10-13T09:42:17.551Z",
        "order": 0
      },
      {
        "id": "d35b8e10-49f2-4a67-8c1b-2e6f0a9d7c53",
        "equationId": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
        "weight": 90,
        "velocity": 0.81,
        "createdAt": "2026-10-13T09:42:17.551Z",
        "updatedAt": "2026-10-13T09:42:17.551Z",
        "order": 1
      },
      {
        "id": "7e19c4b2-a053-4d8e-b6f7-c0d2915a3e48",
        "equationId": "b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
        "weight": 110,
        "velocity": 0.57,
        "createdAt": "2026-10-13T09:42:17.551Z",
        "updatedAt": "2026-10-13T09:42:17.551Z",
        "order": 2
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • Rows of an athlete no longer in your organization answer 404.

Failures are described in error codes.

List leaderboards

GET/leaderboards

Leaderboard definitions of your organization, newest first, each with the ids of its athletes.

Request

curl "https://api-next.vitruve.fit/v1/leaderboards?exerciseId=1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": [
    {
      "id": "17b9d4e2-60a5-4c83-bf19-4a8e3d0c6f25",
      "name": "Back squat: best mean velocity",
      "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
      "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
      "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
      "createdAt": "2025-11-03T08:00:00.000Z",
      "updatedAt": "2025-11-03T08:00:00.000Z",
      "deletedAt": null,
      "users": [
        {
          "id": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"
        },
        {
          "id": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"
        }
      ]
    }
  ],
  "meta": {
    "limit": 50,
    "hasMore": true,
    "nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
  }
}

Query parameters

metricIduuid
Only leaderboards ranking this metric.
exerciseIduuid
Only leaderboards of this exercise.
userIduuid
Only leaderboards this athlete is on.
limitintegerdefault 50
Page size, 1–100.
cursorstring
meta.nextCursor from the previous page. Omit it to get the first page.

Notes

  • Rankings are not computed here. Get them from GET /analytics/ranking with the leaderboard’s metricId, exerciseId and its athletes as userIds.
  • Deleted users are left out of users.

Response fields

iduuid
Leaderboard id.
namestring
Leaderboard name.
metricIduuid
Metric ranked. Resolve with GET /metrics/{id}.
exerciseIduuid
Exercise ranked. Resolve with GET /exercises/{id}.
users[].iduuid
Athletes on the leaderboard. Resolve with GET /athletes/{id}.

Failures are described in error codes.

Get a leaderboard

GET/leaderboards/{id}

One leaderboard definition with the ids of its athletes.

Request

curl "https://api-next.vitruve.fit/v1/leaderboards/17b9d4e2-60a5-4c83-bf19-4a8e3d0c6f25" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "17b9d4e2-60a5-4c83-bf19-4a8e3d0c6f25",
    "name": "Back squat: best mean velocity",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "metricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
    "exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
    "createdAt": "2025-11-03T08:00:00.000Z",
    "updatedAt": "2025-11-03T08:00:00.000Z",
    "deletedAt": null,
    "users": [
      {
        "id": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"
      },
      {
        "id": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • Rankings are not computed here. Get them from GET /analytics/ranking with the leaderboard’s metricId, exerciseId and its athletes as userIds.
  • Deleted users are left out of users.

Response fields

iduuid
Leaderboard id.
namestring
Leaderboard name.
metricIduuid
Metric ranked. Resolve with GET /metrics/{id}.
exerciseIduuid
Exercise ranked. Resolve with GET /exercises/{id}.
users[].iduuid
Athletes on the leaderboard. Resolve with GET /athletes/{id}.

Failures are described in error codes.

List wellness questionnaires

GET/wellness-tests

Answered wellness questionnaires of your organization’s athletes, newest first, each with its questions and answers.

Request

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

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": [
    {
      "id": "c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3",
      "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
      "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
      "workoutId": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
      "createdAt": "2026-03-18T08:47:12.000Z",
      "updatedAt": "2026-03-18T08:47:12.000Z",
      "deletedAt": null,
      "questions": [
        {
          "id": "2b7e4f90-c613-4d8a-95e2-a0f3d71c6b48",
          "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
          "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
          "baseQuestionId": "7c1d9a35-e840-4f62-b0a7-58e3c2d4f916",
          "wellnessTestId": "c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3",
          "order": 0,
          "question": "How fatigued do you feel?",
          "placeholderMinValue": "Very Fatigated",
          "placeholderMaxValue": "Not Fatigated",
          "minValue": 1,
          "maxValue": 5,
          "integerValue": 4,
          "stringValue": null,
          "isSelected": true,
          "type": "numeric",
          "createdAt": "2026-03-18T08:47:12.000Z",
          "updatedAt": "2026-03-18T08:47:12.000Z",
          "deletedAt": null
        },
        {
          "id": "f05a8c3e-29d7-4b16-a4c9-6e1b7d0f3a82",
          "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
          "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
          "baseQuestionId": "4e8b2d61-a0f5-4c39-8d17-b9c6e3a05f24",
          "wellnessTestId": "c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3",
          "order": 1,
          "question": "Write whatever you want",
          "placeholderMinValue": null,
          "placeholderMaxValue": null,
          "minValue": null,
          "maxValue": null,
          "integerValue": null,
          "stringValue": "Slight tightness in the left calf.",
          "isSelected": true,
          "type": "text",
          "createdAt": "2026-03-18T08:47:12.000Z",
          "updatedAt": "2026-03-18T08:47:12.000Z",
          "deletedAt": null
        }
      ]
    }
  ],
  "meta": {
    "limit": 50,
    "hasMore": true,
    "nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
  }
}

Query parameters

userIduuid
Only questionnaires answered by this athlete.
workoutIduuid
Only the questionnaire answered for this workout.
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

  • Sorted and date-filtered by createdAt.
  • A workout has at most one questionnaire.
  • Rows older than the history your plan includes are left out.

Response fields

iduuid
Questionnaire id.
userIduuidnullable
Athlete who answered. Resolve with GET /athletes/{id}.
workoutIduuidnullable
Workout the questionnaire was answered for, if any. Resolve with GET /workouts/{id}.
createdAtdatetime
When the questionnaire was answered. from / to filter on it.
questions[]object[]
Questions with their answers, sorted by order.
questions[].questionstringnullable
Question text as shown to the athlete.
questions[].typestringnullable
numeric (answer in integerValue) or text (answer in stringValue).
questions[].integerValueintegernullable
Numeric answer, between minValue and maxValue (1–5 by default).
questions[].stringValuestringnullable
Free-text answer.
questions[].placeholderMinValuestringnullable
Label of the lowest value on the scale.
questions[].placeholderMaxValuestringnullable
Label of the highest value on the scale.
questions[].baseQuestionIduuidnullable
The question this answer was created from. Use it to group answers to the same question across questionnaires.

Failures are described in error codes.

Get a wellness questionnaire

GET/wellness-tests/{id}

One answered questionnaire with its questions and answers.

Request

curl "https://api-next.vitruve.fit/v1/wellness-tests/c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
    "workoutId": "f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35",
    "createdAt": "2026-03-18T08:47:12.000Z",
    "updatedAt": "2026-03-18T08:47:12.000Z",
    "deletedAt": null,
    "questions": [
      {
        "id": "2b7e4f90-c613-4d8a-95e2-a0f3d71c6b48",
        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
        "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
        "baseQuestionId": "7c1d9a35-e840-4f62-b0a7-58e3c2d4f916",
        "wellnessTestId": "c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3",
        "order": 0,
        "question": "How fatigued do you feel?",
        "placeholderMinValue": "Very Fatigated",
        "placeholderMaxValue": "Not Fatigated",
        "minValue": 1,
        "maxValue": 5,
        "integerValue": 4,
        "stringValue": null,
        "isSelected": true,
        "type": "numeric",
        "createdAt": "2026-03-18T08:47:12.000Z",
        "updatedAt": "2026-03-18T08:47:12.000Z",
        "deletedAt": null
      },
      {
        "id": "f05a8c3e-29d7-4b16-a4c9-6e1b7d0f3a82",
        "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
        "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
        "baseQuestionId": "4e8b2d61-a0f5-4c39-8d17-b9c6e3a05f24",
        "wellnessTestId": "c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3",
        "order": 1,
        "question": "Write whatever you want",
        "placeholderMinValue": null,
        "placeholderMaxValue": null,
        "minValue": null,
        "maxValue": null,
        "integerValue": null,
        "stringValue": "Slight tightness in the left calf.",
        "isSelected": true,
        "type": "text",
        "createdAt": "2026-03-18T08:47:12.000Z",
        "updatedAt": "2026-03-18T08:47:12.000Z",
        "deletedAt": null
      }
    ]
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • A row older than the history your plan includes answers 404.

Response fields

iduuid
Questionnaire id.
userIduuidnullable
Athlete who answered. Resolve with GET /athletes/{id}.
workoutIduuidnullable
Workout the questionnaire was answered for, if any. Resolve with GET /workouts/{id}.
createdAtdatetime
When the questionnaire was answered. from / to filter on it.
questions[]object[]
Questions with their answers, sorted by order.
questions[].questionstringnullable
Question text as shown to the athlete.
questions[].typestringnullable
numeric (answer in integerValue) or text (answer in stringValue).
questions[].integerValueintegernullable
Numeric answer, between minValue and maxValue (1–5 by default).
questions[].stringValuestringnullable
Free-text answer.
questions[].placeholderMinValuestringnullable
Label of the lowest value on the scale.
questions[].placeholderMaxValuestringnullable
Label of the highest value on the scale.
questions[].baseQuestionIduuidnullable
The question this answer was created from. Use it to group answers to the same question across questionnaires.

Failures are described in error codes.

List injury reports

GET/injury-reports

Injury reports filed for your organization’s athletes, newest first.

Request

curl "https://api-next.vitruve.fit/v1/injury-reports?recovered=false" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": [
    {
      "id": "8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60",
      "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
      "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
      "createdBy": "5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47",
      "injuryType": "Hamstring strain",
      "side": "left",
      "severity": "mid",
      "recoveryEstimatedDate": "2026-04-15T00:00:00.000Z",
      "recovered": false,
      "notes": "Grade 1. Return to running in two weeks.",
      "createdAt": "2026-03-20T16:05:41.000Z",
      "updatedAt": "2026-03-20T16:05:41.000Z",
      "deletedAt": null
    }
  ],
  "meta": {
    "limit": 50,
    "hasMore": true,
    "nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
  }
}

Query parameters

userIduuid
Only reports of this athlete.
recoveredboolean
false for open injuries, true for recovered ones.
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

  • Sorted and date-filtered by createdAt (when the report was filed), not by recoveryEstimatedDate.
  • Rows older than the history your plan includes are left out.

Response fields

iduuid
Injury report id.
userIduuid
Injured athlete. Resolve with GET /athletes/{id}.
createdByuuid
Coach who filed the report. Resolve with GET /coaches/{id}.
injuryTypestring
Injury, as entered by the coach (free text).
sidestringnullable
left, right or null.
severitystring
low, mid or high.
recoveryEstimatedDatedatetime
Expected return date.
recoveredboolean
Whether the athlete has been marked as recovered.
notesstringnullable
Coach notes.
createdAtdatetime
When the report was filed. from / to filter on it.

Failures are described in error codes.

Get an injury report

GET/injury-reports/{id}

One injury report.

Request

curl "https://api-next.vitruve.fit/v1/injury-reports/8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60",
    "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "createdBy": "5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47",
    "injuryType": "Hamstring strain",
    "side": "left",
    "severity": "mid",
    "recoveryEstimatedDate": "2026-04-15T00:00:00.000Z",
    "recovered": false,
    "notes": "Grade 1. Return to running in two weeks.",
    "createdAt": "2026-03-20T16:05:41.000Z",
    "updatedAt": "2026-03-20T16:05:41.000Z",
    "deletedAt": null
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • A row older than the history your plan includes answers 404.

Response fields

iduuid
Injury report id.
userIduuid
Injured athlete. Resolve with GET /athletes/{id}.
createdByuuid
Coach who filed the report. Resolve with GET /coaches/{id}.
injuryTypestring
Injury, as entered by the coach (free text).
sidestringnullable
left, right or null.
severitystring
low, mid or high.
recoveryEstimatedDatedatetime
Expected return date.
recoveredboolean
Whether the athlete has been marked as recovered.
notesstringnullable
Coach notes.
createdAtdatetime
When the report was filed. from / to filter on it.

Failures are described in error codes.

Create an injury report

POST/injury-reports

Files an injury report for an athlete, in the name of the coach or owner in createdBy. Answers it in the shape of GET /injury-reports/{id}.

Request

curl -X POST "https://api-next.vitruve.fit/v1/injury-reports" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: YOUR_OPERATION_ID" \
  -d '{
    "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
    "createdBy": "5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47",
    "injuryType": "Ankle sprain",
    "severity": "low",
    "recoveryEstimatedDate": "2026-10-27",
    "side": "right",
    "notes": "Inversion sprain in training. Back to running in a week."
  }'

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "5a0d8e36-f1b7-4c92-b4a5-e86c2d71f093",
    "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "createdBy": "5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47",
    "injuryType": "Ankle sprain",
    "side": "right",
    "severity": "low",
    "recoveryEstimatedDate": "2026-10-27T00:00:00.000Z",
    "recovered": false,
    "notes": "Inversion sprain in training. Back to running in a week.",
    "createdAt": "2026-10-13T09:45:30.226Z",
    "updatedAt": "2026-10-13T09:45:30.226Z",
    "deletedAt": null
  }
}

Headers

Idempotency-Keystring
Request header. 1 to 255 visible ASCII characters you choose per operation, such as a UUID or your own record’s id. A retry with the same key and the same request returns the first answer instead of creating again.

Body

userIduuidrequired
Injured athlete, one of your organization’s.
createdByuuidrequired
Coach or owner filing the report: the API key has no user of its own. See GET /coaches.
injuryTypestringrequired
The injury, as free text, up to 2,000 characters.
severitylow | mid | highrequired
Severity.
recoveryEstimatedDatedaterequired
Expected return date: YYYY-MM-DD (UTC midnight) or an ISO 8601 datetime with an offset. Can’t be null.
sideleft | rightnullable
Injured side.
recoveredbooleandefault false
Whether the athlete has recovered.
notesstringnullable
Notes, up to 2,000 characters.

Notes

  • 400 when userId is not an athlete of your organization, or createdBy is not one of its coaches or its owner.
  • Send an Idempotency-Key header to retry the create safely after a timeout: a retry with the same key and body answers the first result instead of creating again.

Failures are described in error codes.

Update an injury report

Request body: any of the create fields except userId and createdBy, at least one. For example { "recovered": true } closes an injury.

PATCH/injury-reports/{id}

Changes only the fields sent, for example { "recovered": true }, and answers the updated report. null clears side or notes.

Request

curl -X PATCH "https://api-next.vitruve.fit/v1/injury-reports/8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recovered": true
  }'

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60",
    "userId": "3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "createdBy": "5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47",
    "injuryType": "Hamstring strain",
    "side": "left",
    "severity": "mid",
    "recoveryEstimatedDate": "2026-04-15T00:00:00.000Z",
    "recovered": true,
    "notes": "Grade 1. Return to running in two weeks.",
    "createdAt": "2026-03-20T16:05:41.000Z",
    "updatedAt": "2026-04-13T08:20:11.000Z",
    "deletedAt": null
  }
}

Path parameters

iduuidrequired
Resource id.

Body

injuryTypestring
The injury, as free text, up to 2,000 characters.
severitylow | mid | high
Severity.
recoveryEstimatedDatedate
Expected return date: YYYY-MM-DD (UTC midnight) or an ISO 8601 datetime with an offset. Can’t be null.
sideleft | rightnullable
Injured side.
recoveredboolean
Whether the athlete has recovered.
notesstringnullable
Notes, up to 2,000 characters.

Notes

  • Rows of an athlete no longer in your organization answer 404.

Failures are described in error codes.

Delete an injury report

DELETE/injury-reports/{id}

Deletes an injury report for good and answers it as it was.

Request

curl -X DELETE "https://api-next.vitruve.fit/v1/injury-reports/5a0d8e36-f1b7-4c92-b4a5-e86c2d71f093" \
  -H "X-API-Key: YOUR_API_KEY"

Response 200

{
  "ok": true,
  "timestamp": 1738247125207,
  "data": {
    "id": "5a0d8e36-f1b7-4c92-b4a5-e86c2d71f093",
    "userId": "c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28",
    "organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
    "createdBy": "5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47",
    "injuryType": "Ankle sprain",
    "side": "right",
    "severity": "low",
    "recoveryEstimatedDate": "2026-10-27T00:00:00.000Z",
    "recovered": false,
    "notes": "Inversion sprain in training. Back to running in a week.",
    "createdAt": "2026-10-13T09:45:30.226Z",
    "updatedAt": "2026-10-13T09:45:30.226Z",
    "deletedAt": null
  }
}

Path parameters

iduuidrequired
Resource id.

Notes

  • Rows of an athlete no longer in your organization answer 404.

Failures are described in error codes.

On this page