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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/equations?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62&exerciseId=1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7&isSelected=true',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/equations?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62&exerciseId=1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7&isSelected=true",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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.
isSelectedbooleantruefor the profiles the app uses,falsefor the others.limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- The list has no
equationSeries. FetchGET /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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/equations/ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/equations/ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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.
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
}
]
}'const response = await fetch(
'https://api-next.vitruve.fit/v1/equations',
{
method: 'POST',
headers: {
'X-API-Key': process.env.VITRUVE_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': 'YOUR_OPERATION_ID'
},
body: JSON.stringify({
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
}
]
})
}
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.request(
"POST",
"https://api-next.vitruve.fit/v1/equations",
headers={
"X-API-Key": os.environ["VITRUVE_API_KEY"],
"Idempotency-Key": "YOUR_OPERATION_ID",
},
json={
"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,
},
],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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 answers400. 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:
weightin kg andvelocityin 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.
400when the athlete, the exercise or the metric doesn’t qualify.messagenames each field.- Send an
Idempotency-Keyheader 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.
| Field | Type | Description |
|---|---|---|
name | string or null | Profile name, up to 255 characters. |
a | number | Only 0: profiles are linear. Any other value answers 400. |
b | number | Slope: load as % of 1RM = b·velocity (m/s) + c. |
c | number | Intercept, in %1RM. |
r2 | number or null | Goodness of fit, 0–1. |
isSelected | boolean | Only true: makes this the athlete’s selected profile for the exercise and unselects the others. To unselect a profile, select another one. |
equationSeries | object[] | The tested sets, in order, at most 100: weight in kg and velocity in m/s, both 0 or more. Replaces the current points. |
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"
}'const response = await fetch(
'https://api-next.vitruve.fit/v1/equations/ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063',
{
method: 'PATCH',
headers: {
'X-API-Key': process.env.VITRUVE_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Back squat LVP, March'
})
}
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.request(
"PATCH",
"https://api-next.vitruve.fit/v1/equations/ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
json={
"name": "Back squat LVP, March",
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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 answers400. 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:
weightin kg andvelocityin 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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/equations/b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428',
{
method: 'DELETE',
headers: {
'X-API-Key': process.env.VITRUVE_API_KEY
}
}
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.request(
"DELETE",
"https://api-next.vitruve.fit/v1/equations/b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/leaderboards?exerciseId=1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/leaderboards?exerciseId=1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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.
limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- Rankings are not computed here. Get them from
GET /analytics/rankingwith the leaderboard’smetricId,exerciseIdand its athletes asuserIds. - 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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/leaderboards/17b9d4e2-60a5-4c83-bf19-4a8e3d0c6f25',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/leaderboards/17b9d4e2-60a5-4c83-bf19-4a8e3d0c6f25",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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/rankingwith the leaderboard’smetricId,exerciseIdand its athletes asuserIds. - 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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/wellness-tests?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62&from=2026-03-01&to=2026-03-31',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/wellness-tests?userId=3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62&from=2026-03-01&to=2026-03-31",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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-DDor an ISO 8601 datetime. A bare date starts at 00:00 intimezone, or at the change on a day whose midnight a daylight-saving change skips. todate- Inclusive upper bound:
YYYY-MM-DDor an ISO 8601 datetime. A bare date covers that whole day intimezone. timezonestringdefaultUTC- IANA time zone, such as
Europe/Madrid. A barefrom/todate covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes withZor an offset are taken as given. limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom 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/tofilter on it. questions[]object[]- Questions with their answers, sorted by
order. questions[].questionstringnullable- Question text as shown to the athlete.
questions[].typestringnullablenumeric(answer inintegerValue) ortext(answer instringValue).questions[].integerValueintegernullable- Numeric answer, between
minValueandmaxValue(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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/wellness-tests/c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/wellness-tests/c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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/tofilter on it. questions[]object[]- Questions with their answers, sorted by
order. questions[].questionstringnullable- Question text as shown to the athlete.
questions[].typestringnullablenumeric(answer inintegerValue) ortext(answer instringValue).questions[].integerValueintegernullable- Numeric answer, between
minValueandmaxValue(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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/injury-reports?recovered=false',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/injury-reports?recovered=false",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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.
recoveredbooleanfalsefor open injuries,truefor recovered ones.fromdate- Inclusive lower bound:
YYYY-MM-DDor an ISO 8601 datetime. A bare date starts at 00:00 intimezone, or at the change on a day whose midnight a daylight-saving change skips. todate- Inclusive upper bound:
YYYY-MM-DDor an ISO 8601 datetime. A bare date covers that whole day intimezone. timezonestringdefaultUTC- IANA time zone, such as
Europe/Madrid. A barefrom/todate covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes withZor an offset are taken as given. limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- Sorted and date-filtered by
createdAt(when the report was filed), not byrecoveryEstimatedDate. - 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).
sidestringnullableleft,rightornull.severitystringlow,midorhigh.recoveryEstimatedDatedatetime- Expected return date.
recoveredboolean- Whether the athlete has been marked as recovered.
notesstringnullable- Coach notes.
createdAtdatetime- When the report was filed.
from/tofilter on it.
Failures are described in error codes.
Get an injury report
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/injury-reports/8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60',
{ headers: { 'X-API-Key': process.env.VITRUVE_API_KEY } }
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.get(
"https://api-next.vitruve.fit/v1/injury-reports/8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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).
sidestringnullableleft,rightornull.severitystringlow,midorhigh.recoveryEstimatedDatedatetime- Expected return date.
recoveredboolean- Whether the athlete has been marked as recovered.
notesstringnullable- Coach notes.
createdAtdatetime- When the report was filed.
from/tofilter on it.
Failures are described in error codes.
Create an injury report
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."
}'const response = await fetch(
'https://api-next.vitruve.fit/v1/injury-reports',
{
method: 'POST',
headers: {
'X-API-Key': process.env.VITRUVE_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': 'YOUR_OPERATION_ID'
},
body: JSON.stringify({
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.'
})
}
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.request(
"POST",
"https://api-next.vitruve.fit/v1/injury-reports",
headers={
"X-API-Key": os.environ["VITRUVE_API_KEY"],
"Idempotency-Key": "YOUR_OPERATION_ID",
},
json={
"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.",
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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 benull. sideleft | rightnullable- Injured side.
recoveredbooleandefaultfalse- Whether the athlete has recovered.
notesstringnullable- Notes, up to 2,000 characters.
Notes
400whenuserIdis not an athlete of your organization, orcreatedByis not one of its coaches or its owner.- Send an
Idempotency-Keyheader 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.
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
}'const response = await fetch(
'https://api-next.vitruve.fit/v1/injury-reports/8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60',
{
method: 'PATCH',
headers: {
'X-API-Key': process.env.VITRUVE_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
recovered: true
})
}
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.request(
"PATCH",
"https://api-next.vitruve.fit/v1/injury-reports/8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
json={
"recovered": True,
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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 benull. 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
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"const response = await fetch(
'https://api-next.vitruve.fit/v1/injury-reports/5a0d8e36-f1b7-4c92-b4a5-e86c2d71f093',
{
method: 'DELETE',
headers: {
'X-API-Key': process.env.VITRUVE_API_KEY
}
}
)
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.message}`)
console.log(body.data)import os
import requests
response = requests.request(
"DELETE",
"https://api-next.vitruve.fit/v1/injury-reports/5a0d8e36-f1b7-4c92-b4a5-e86c2d71f093",
headers={"X-API-Key": os.environ["VITRUVE_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])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.