Catalogs
Exercises, muscles, metrics, prescription types and units: the reference data that ids in workouts and metric values point to.
Muscles, metrics, prescription types, units and Vitruve's exercise library are the same for every customer. Load them once with any customer key, cache them for a day, and resolve ids locally. Exercises a customer created themselves (source=organization) are cached per customer.
List exercises
Vitruve’s global exercise library plus the exercises your organization created, ordered by name. Each exercise carries its primary and secondary muscles and your organization’s exerciseMetadata.
Request
curl "https://api-integrations-next.vitruve.fit/v1/exercises?limit=2&search=squat&source=global" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/exercises?limit=2&search=squat&source=global',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/exercises?limit=2&search=squat&source=global",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": [
{
"id": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
"name": "Back Squat",
"organizationId": null,
"isMain": true,
"isJump": false,
"isReaction": false,
"isSprint": false,
"equipment": "barbell",
"force": "push",
"level": "intermediate",
"mechanic": "compound",
"instructions": "Set the bar across your upper back and unrack it with feet shoulder-width apart. Bend at the hips and knees until the thighs are at least parallel, then drive up through the whole foot to stand.",
"category": "strength",
"youtubeUrl": "https://www.youtube.com/results?search_query=how%20to%20do%20Back%20Squat",
"googleUrl": "https://www.google.com/search?q=how%20to%20do%20Back%20Squat",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null,
"primaryMuscles": [
{
"id": "5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52",
"name": "quadriceps",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
}
],
"secondaryMuscles": [
{
"id": "2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264",
"name": "glutes",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
},
{
"id": "e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035",
"name": "hamstrings",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
}
],
"exerciseMetadata": [
{
"id": "9d5c2a71-e4f8-4b36-8c0d-6a1e3f7b9c52",
"exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
"organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
"videoUrl": "https://videos.northgate.example/back-squat.mp4",
"createdAt": "2025-10-03T11:12:40.000Z",
"updatedAt": "2025-10-03T11:12:40.000Z"
}
]
}
],
"meta": {
"limit": 2,
"hasMore": true,
"nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
}
}Query parameters
searchstring- Case-insensitive match on the exercise name.
categorystring- Exact, case-sensitive match on
category, e.g.strengthorplyometrics. sourceall | global | organizationdefaultallglobalreturns only Vitruve’s library,organizationonly your own exercises,allboth.limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- Global exercises have
organizationId: null. Other organizations’ exercises are never returned. - Deleted muscles are left out of
primaryMusclesandsecondaryMuscles. - Catalogs change rarely. Cache them and refresh once a day rather than resolving ids one request at a time.
Response fields
iduuid- Exercise id. Matches
exerciseIdon prescriptions, metric values, equations and leaderboards. namestring- Exercise name.
organizationIduuidnullablenullfor Vitruve’s global library; your organization id for exercises your coaches created.isMainbooleannullable- Whether the exercise is flagged as a main lift.
isJumpbooleannullable- Jump exercise.
isReactionandisSprintflag reaction and sprint exercises the same way. categorystringnullable- Free-text category. The global library uses
strength,plyometrics,stretching,powerlifting,olympic weightlifting,cardio,strongmanandtest. equipmentstringnullable- Equipment, e.g.
barbell.force,levelandmechanicare free-text descriptors too. instructionsstringnullable- How to perform the exercise.
youtubeUrlstringnullable- Search link for demonstration videos.
googleUrlis the same for a web search. primaryMuscles[]object[]- Main muscles worked, as full muscle objects (see
GET /muscles). secondaryMuscles[]object[]- Supporting muscles, same shape.
exerciseMetadata[]object[]- Your organization’s custom video for the exercise, if one was set. At most one entry; other organizations’ metadata is never included.
exerciseMetadata[].videoUrlstring- Video URL set by your organization.
Failures are described in error codes.
Get an exercise
One global exercise or one of your organization’s exercises, with its muscles and your organization’s exerciseMetadata.
Request
curl "https://api-integrations-next.vitruve.fit/v1/exercises/1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/exercises/1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/exercises/1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": {
"id": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
"name": "Back Squat",
"organizationId": null,
"isMain": true,
"isJump": false,
"isReaction": false,
"isSprint": false,
"equipment": "barbell",
"force": "push",
"level": "intermediate",
"mechanic": "compound",
"instructions": "Set the bar across your upper back and unrack it with feet shoulder-width apart. Bend at the hips and knees until the thighs are at least parallel, then drive up through the whole foot to stand.",
"category": "strength",
"youtubeUrl": "https://www.youtube.com/results?search_query=how%20to%20do%20Back%20Squat",
"googleUrl": "https://www.google.com/search?q=how%20to%20do%20Back%20Squat",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null,
"primaryMuscles": [
{
"id": "5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52",
"name": "quadriceps",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
}
],
"secondaryMuscles": [
{
"id": "2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264",
"name": "glutes",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
},
{
"id": "e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035",
"name": "hamstrings",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
}
],
"exerciseMetadata": [
{
"id": "9d5c2a71-e4f8-4b36-8c0d-6a1e3f7b9c52",
"exerciseId": "1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7",
"organizationId": "7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10",
"videoUrl": "https://videos.northgate.example/back-squat.mp4",
"createdAt": "2025-10-03T11:12:40.000Z",
"updatedAt": "2025-10-03T11:12:40.000Z"
}
]
}
}Path parameters
iduuidrequired- Resource id.
Notes
- An exercise owned by another organization returns
404, as does a deleted one.
Response fields
iduuid- Exercise id. Matches
exerciseIdon prescriptions, metric values, equations and leaderboards. namestring- Exercise name.
organizationIduuidnullablenullfor Vitruve’s global library; your organization id for exercises your coaches created.isMainbooleannullable- Whether the exercise is flagged as a main lift.
isJumpbooleannullable- Jump exercise.
isReactionandisSprintflag reaction and sprint exercises the same way. categorystringnullable- Free-text category. The global library uses
strength,plyometrics,stretching,powerlifting,olympic weightlifting,cardio,strongmanandtest. equipmentstringnullable- Equipment, e.g.
barbell.force,levelandmechanicare free-text descriptors too. instructionsstringnullable- How to perform the exercise.
youtubeUrlstringnullable- Search link for demonstration videos.
googleUrlis the same for a web search. primaryMuscles[]object[]- Main muscles worked, as full muscle objects (see
GET /muscles). secondaryMuscles[]object[]- Supporting muscles, same shape.
exerciseMetadata[]object[]- Your organization’s custom video for the exercise, if one was set. At most one entry; other organizations’ metadata is never included.
exerciseMetadata[].videoUrlstring- Video URL set by your organization.
Failures are described in error codes.
List muscles
Every muscle exercises can reference (see primaryMuscleIds / secondaryMuscleIds), ordered by name. Names are lowercase, e.g. quadriceps, lower back.
Request
curl "https://api-integrations-next.vitruve.fit/v1/muscles?limit=2" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/muscles?limit=2',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/muscles?limit=2",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": [
{
"id": "2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264",
"name": "glutes",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
},
{
"id": "e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035",
"name": "hamstrings",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
}
],
"meta": {
"limit": 2,
"hasMore": true,
"nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
}
}Query parameters
limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- Catalogs change rarely. Cache them and refresh once a day rather than resolving ids one request at a time.
Response fields
iduuid- Muscle id. Matches the ids in an exercise’s
primaryMusclesandsecondaryMuscles. namestring- Lowercase muscle name.
Failures are described in error codes.
Get a muscle
One muscle.
Request
curl "https://api-integrations-next.vitruve.fit/v1/muscles/5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/muscles/5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/muscles/5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": {
"id": "5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52",
"name": "quadriceps",
"updatedAt": "2026-05-04T07:30:00.000Z",
"createdAt": "2024-01-15T09:00:00.000Z",
"deletedAt": null
}
}Path parameters
iduuidrequired- Resource id.
Failures are described in error codes.
List metrics
Metric definitions, ordered by order. Use them to name and unit the values inside workouts.
Request
curl "https://api-integrations-next.vitruve.fit/v1/metrics?limit=1&group=Velocity&isRepetitionMetric=true" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/metrics?limit=1&group=Velocity&isRepetitionMetric=true',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/metrics?limit=1&group=Velocity&isRepetitionMetric=true",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": [
{
"id": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
"name": "Mean Propulsive Velocity",
"key": "mean-propulsive-velocity",
"group": "Velocity",
"dimension": null,
"unitId": "fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78",
"order": 0,
"isMainVelocityMetric": true,
"isRepetitionMetric": true,
"isSerieMetric": false,
"isQuickStartMetric": true,
"isEquationMetric": true,
"isUserMetric": false,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null
}
],
"meta": {
"limit": 1,
"hasMore": true,
"nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
}
}Query parameters
groupGeneral | Weight | Time | Distance | Velocity | Fatigue | Percentage | Power | Force | Acceleration | Scale | Heart Rate | Temperature | Pressure | Energy | Volume | Pace | Oxygen Consumption | Concentration- Only metrics in this group. Exact, case-sensitive match.
isRepetitionMetricboolean- Only metrics recorded per repetition (
true) or not (false). isSerieMetricboolean- Only metrics recorded per set (
true) or not (false). isUserMetricboolean- Only athlete metrics such as body weight (
true) or not (false). isEquationMetricboolean- Only metrics usable in equations (
true) or not (false). limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- Boolean filters accept only
trueorfalse; any other value is a400. - Metrics are global: every organization sees the same set.
- Catalogs change rarely. Cache them and refresh once a day rather than resolving ids one request at a time.
Response fields
iduuid- Metric id. Matches
metricIdon metric values, equations and leaderboards. namestring- Display name.
keystring- Stable slug for the metric, e.g.
mean-propulsive-velocity. groupstring- What the metric measures, e.g.
Velocity,Power,Fatigue. dimensionstringnullable- Legacy column superseded by
group. Do not rely on it. unitIduuid- Unit the metric’s values are stored in. Resolve with
GET /units/{id}. orderinteger- Display order within the group, lowest first. Lists are sorted by it.
isMainVelocityMetricboolean- The primary velocity read of a VBT set.
isRepetitionMetricboolean- Values are recorded per repetition.
isSerieMetricboolean- Values are recorded per set.
isUserMetricboolean- Values belong to the athlete rather than a session, e.g. body weight.
isEquationMetricboolean- The metric can be used in equations (see
GET /equations). isQuickStartMetricboolean- Shown by default in the app’s quick-start mode.
Failures are described in error codes.
Get a metric
One metric definition.
Request
curl "https://api-integrations-next.vitruve.fit/v1/metrics/d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/metrics/d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/metrics/d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": {
"id": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
"name": "Mean Propulsive Velocity",
"key": "mean-propulsive-velocity",
"group": "Velocity",
"dimension": null,
"unitId": "fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78",
"order": 0,
"isMainVelocityMetric": true,
"isRepetitionMetric": true,
"isSerieMetric": false,
"isQuickStartMetric": true,
"isEquationMetric": true,
"isUserMetric": false,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null
}
}Path parameters
iduuidrequired- Resource id.
Response fields
iduuid- Metric id. Matches
metricIdon metric values, equations and leaderboards. namestring- Display name.
keystring- Stable slug for the metric, e.g.
mean-propulsive-velocity. groupstring- What the metric measures, e.g.
Velocity,Power,Fatigue. dimensionstringnullable- Legacy column superseded by
group. Do not rely on it. unitIduuid- Unit the metric’s values are stored in. Resolve with
GET /units/{id}. orderinteger- Display order within the group, lowest first. Lists are sorted by it.
isMainVelocityMetricboolean- The primary velocity read of a VBT set.
isRepetitionMetricboolean- Values are recorded per repetition.
isSerieMetricboolean- Values are recorded per set.
isUserMetricboolean- Values belong to the athlete rather than a session, e.g. body weight.
isEquationMetricboolean- The metric can be used in equations (see
GET /equations). isQuickStartMetricboolean- Shown by default in the app’s quick-start mode.
Failures are described in error codes.
List prescription types
The parameters a coach can prescribe for a set (weight, repetitions, velocity targets, fatigue limits…), ordered by name. Use them to read seriePrescriptions in workouts, programs and templates.
Request
curl "https://api-integrations-next.vitruve.fit/v1/prescription-types?limit=2" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/prescription-types?limit=2',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/prescription-types?limit=2",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": [
{
"id": "b8d24f6a-0c97-4e35-a1f8-5d3e9c7b2a16",
"name": "Fatigue [MPV]",
"label": "Fatigue [MPV]",
"metricId": "4c9e7b20-d1a5-4f83-b6e2-a07f3d58c914",
"primaryMetricId": "d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63",
"group": "VBT",
"prescriptionGroup": null,
"trainingModality": "vbt",
"valueType": "int",
"placeholder": "0",
"formatRegex": "^(100|\\d{0,2})?$",
"hasRange": false,
"hasTopMode": false,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null
},
{
"id": "3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05",
"name": "Weight",
"label": "Weight",
"metricId": "62f0d8a4-b3c9-4e17-8a5d-0e4c7f1b9d28",
"primaryMetricId": null,
"group": "General",
"prescriptionGroup": null,
"trainingModality": null,
"valueType": "float",
"placeholder": "0",
"formatRegex": "^\\d{0,5}(\\.\\d{0,2})?$",
"hasRange": true,
"hasTopMode": false,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null
}
],
"meta": {
"limit": 2,
"hasMore": true,
"nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
}
}Query parameters
groupGeneral | VBT | Velocity | Jump | Sprint | Reaction | Time | Test | Other- Only prescription types in this group. Exact, case-sensitive match.
trainingModalityvbt | jump | sprint | reaction- Only prescription types for this modality. Types that apply to any modality have none and are left out.
limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- The units a prescription type can be entered in are not included in the response.
- Catalogs change rarely. Cache them and refresh once a day rather than resolving ids one request at a time.
Response fields
iduuid- Prescription type id. Matches
prescriptionTypeIdon a workout’sseriePrescriptions. namestring- Name of the parameter, e.g.
Weight,Fatigue [MPV]. labelstring- Short label shown next to the value.
groupstring- Grouping used in the app, e.g.
General,VBT,Jump. prescriptionGroupstringnullable- Legacy column superseded by
group. Do not rely on it. trainingModalitystringnullablevbt,jump,sprintorreaction.nullfor parameters that apply to any modality, such as weight.metricIduuidnullable- Metric the prescribed value is compared against. Resolve with
GET /metrics/{id}. primaryMetricIduuidnullable- Underlying repetition metric, when the parameter is derived from one (e.g. a fatigue target built on Mean Propulsive Velocity).
valueTypestring- How the value is entered:
float,int,time,tempoorselect. formatRegexstring- Pattern the app validates entered values against.
hasRangeboolean- Whether a coach can prescribe a min–max range instead of one value.
hasTopModeboolean- Whether the parameter supports “top set” mode.
Failures are described in error codes.
Get a prescription type
One prescription type.
Request
curl "https://api-integrations-next.vitruve.fit/v1/prescription-types/3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/prescription-types/3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/prescription-types/3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": {
"id": "3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05",
"name": "Weight",
"label": "Weight",
"metricId": "62f0d8a4-b3c9-4e17-8a5d-0e4c7f1b9d28",
"primaryMetricId": null,
"group": "General",
"prescriptionGroup": null,
"trainingModality": null,
"valueType": "float",
"placeholder": "0",
"formatRegex": "^\\d{0,5}(\\.\\d{0,2})?$",
"hasRange": true,
"hasTopMode": false,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null
}
}Path parameters
iduuidrequired- Resource id.
Response fields
iduuid- Prescription type id. Matches
prescriptionTypeIdon a workout’sseriePrescriptions. namestring- Name of the parameter, e.g.
Weight,Fatigue [MPV]. labelstring- Short label shown next to the value.
groupstring- Grouping used in the app, e.g.
General,VBT,Jump. prescriptionGroupstringnullable- Legacy column superseded by
group. Do not rely on it. trainingModalitystringnullablevbt,jump,sprintorreaction.nullfor parameters that apply to any modality, such as weight.metricIduuidnullable- Metric the prescribed value is compared against. Resolve with
GET /metrics/{id}. primaryMetricIduuidnullable- Underlying repetition metric, when the parameter is derived from one (e.g. a fatigue target built on Mean Propulsive Velocity).
valueTypestring- How the value is entered:
float,int,time,tempoorselect. formatRegexstring- Pattern the app validates entered values against.
hasRangeboolean- Whether a coach can prescribe a min–max range instead of one value.
hasTopModeboolean- Whether the parameter supports “top set” mode.
Failures are described in error codes.
List units
Units of measure, ordered by name. Each unit converts to its base unit with conversionFactor: base = value × conversionFactor. For pounds the factor is 0.45359237, so 100 lb is 45.359237 kg.
Request
curl "https://api-integrations-next.vitruve.fit/v1/units?dimension=Weight" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/units?dimension=Weight',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/units?dimension=Weight",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": [
{
"id": "09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246",
"name": "Kilograms",
"dimension": "Weight",
"measurementSystem": "metric",
"label": "kg",
"baseUnitId": "09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246",
"pairUnitId": "7b13e9c5-48d2-4a06-b9f1-c2e8a5d4f317",
"conversionFactor": 1,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null,
"prescriptionTypeId": null
},
{
"id": "7b13e9c5-48d2-4a06-b9f1-c2e8a5d4f317",
"name": "Pounds",
"dimension": "Weight",
"measurementSystem": "imperial",
"label": "lb",
"baseUnitId": "09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246",
"pairUnitId": "09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246",
"conversionFactor": 0.45359237,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null,
"prescriptionTypeId": null
}
],
"meta": {
"limit": 50,
"hasMore": true,
"nextCursor": "ZTU2M2ZlYzMtM2IxYy00…"
}
}Query parameters
dimensionAcceleration | Cadence | Distance | Energy | Force | Frequency | Heart Rate | Oxygen Consumption | Pace | Power | Pressure | Temperature | Time | Velocity | Volume | Weight- Only units of this physical quantity. Exact, case-sensitive match.
measurementSystemmetric | imperial- Only metric or only imperial units.
limitintegerdefault50- Page size, 1–100.
cursorstringmeta.nextCursorfrom the previous page. Omit it to get the first page.
Notes
- A base unit has
baseUnitIdequal to its ownidandconversionFactor: 1. - Metric values are stored in the unit of their metric (
unitId). - Catalogs change rarely. Cache them and refresh once a day rather than resolving ids one request at a time.
Response fields
iduuid- Unit id. Matches
unitIdon metrics. namestring- Full name, e.g.
Kilograms. labelstring- Symbol to display next to values, e.g.
kg,m/s. dimensionstringnullable- Physical quantity, e.g.
Weight,Velocity,Distance. measurementSystemstringnullablemetricorimperial.baseUnitIduuidnullable- Unit that
conversionFactorconverts to. A base unit points to itself. conversionFactornumber- Multiplier to the base unit:
base = value × conversionFactor. Returned as a JSON number. pairUnitIduuidnullable- The equivalent unit in the other measurement system, e.g.
lbforkg. prescriptionTypeIduuidnullable- Prescription type the unit is attached to, if any. Resolve with
GET /prescription-types/{id}.
Failures are described in error codes.
Get a unit
One unit, with conversionFactor as a number.
Request
curl "https://api-integrations-next.vitruve.fit/v1/units/fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78" \
-H "X-API-Key: CUSTOMER_INTEGRATION_KEY" \
-H "X-Partner-Secret: YOUR_PARTNER_SECRET"const response = await fetch(
'https://api-integrations-next.vitruve.fit/v1/units/fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78',
{
headers: {
'X-API-Key': customer.vitruveKey,
'X-Partner-Secret': process.env.VITRUVE_PARTNER_SECRET
}
}
)
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-integrations-next.vitruve.fit/v1/units/fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78",
headers={
"X-API-Key": customer.vitruve_key,
"X-Partner-Secret": os.environ["VITRUVE_PARTNER_SECRET"],
},
timeout=30,
)
response.raise_for_status()
print(response.json()["data"])Response 200
{
"ok": true,
"timestamp": 1738247125207,
"data": {
"id": "fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78",
"name": "Meters per Second",
"dimension": "Velocity",
"measurementSystem": "metric",
"label": "m/s",
"baseUnitId": "fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78",
"pairUnitId": null,
"conversionFactor": 1,
"createdAt": "2024-01-15T09:00:00.000Z",
"updatedAt": "2026-05-04T07:30:00.000Z",
"deletedAt": null,
"prescriptionTypeId": null
}
}Path parameters
iduuidrequired- Resource id.
Response fields
iduuid- Unit id. Matches
unitIdon metrics. namestring- Full name, e.g.
Kilograms. labelstring- Symbol to display next to values, e.g.
kg,m/s. dimensionstringnullable- Physical quantity, e.g.
Weight,Velocity,Distance. measurementSystemstringnullablemetricorimperial.baseUnitIduuidnullable- Unit that
conversionFactorconverts to. A base unit points to itself. conversionFactornumber- Multiplier to the base unit:
base = value × conversionFactor. Returned as a JSON number. pairUnitIduuidnullable- The equivalent unit in the other measurement system, e.g.
lbforkg. prescriptionTypeIduuidnullable- Prescription type the unit is attached to, if any. Resolve with
GET /prescription-types/{id}.
Failures are described in error codes.