KinesteX

Workouts

A workout is an ordered sequence of exercises and rest periods, with its own difficulty, calorie estimate, and duration.




List workouts


text
1GET /api/workouts/client

ParameterTypeDefaultMatches
searchstringnonePartial, case-insensitive match on the English title
categorystringnoneSingle value. Whole-string, case-insensitive match
dif_levelstringnoneSingle value. Whole-string, case-insensitive match
body_partsstring[]noneBody part name, case-insensitive
translation_languagesstring[]noneOnly workouts translated into one of these language codes
include_exercisesboolfalsetrue expands every workout with its full exercise sequence
include_shared_librarybooltruefalse returns only your company's own workouts
langstringenLanguage of the returned text
limitint10Page size, clamped to 100
offsetint0Rows to skip

bash
1curl "https://data.kinestex.com/api/workouts/client?category=Strength&dif_level=easy&body_parts=Chest,Triceps&limit=2" \
2  -H "x-api-key: YOUR_API_KEY" \
3  -H "Language: en"

json
1{
2  "workouts": [
3    {
4      "id": 88,
5      "category": "Strength",
6      "calories": 250,
7      "type": "Upper Body",
8      "body_img_url": "https://firebasestorage.googleapis.com/.../body.png?alt=media",
9      "dif_level": "Easy",
10      "desc_img_url": "https://firebasestorage.googleapis.com/.../desc.png?alt=media",
11      "total_time": 1800,
12      "body_parts": ["Chest", "Triceps"],
13      "translation": {
14        "id": 201,
15        "workout_id": 88,
16        "language": "en",
17        "title": "Upper Body Starter",
18        "description": "A short push-focused session."
19      },
20      "translation_languages": ["en", "es", "de"],
21      "created_by": { "id": 1 },
22      "created_at": "2026-01-14T10:00:00Z",
23      "updated_at": "2026-02-02T08:30:00Z"
24    }
25  ],
26  "pagination": {
27    "total": 12,
28    "limit": 2,
29    "offset": 0,
30    "total_pages": 6,
31    "current_page": 1,
32    "has_next": true,
33    "has_prev": false
34  }
35}

Workout fields (list view)


FieldTypeDescription
idnumberWorkout identifier
categorystringFree-text category set per workout
caloriesnumberEstimated calories burned
typestring or nullOptional content type label
dif_levelstringDifficulty as stored, usually capitalized
body_img_urlstring or nullBody-map image
desc_img_urlstring or nullCover / preview image
total_timenumberDuration in seconds
body_partsstring[]Targeted body parts
translationobject or nullLocalized title and description for the requested language
translation_languagesstring[]Every language code this workout has
workout_sequencesarrayPresent only with include_exercises=true
created_byobject{ "id": <company id> }
created_at / updated_atstringISO 8601 timestamps

The workout title is not a root-level field. Always read translation.title.

translation is null when the requested language has no row for that workout, because this endpoint does not fall back to English. translation_languages always lists what does exist, so use it to decide whether to re-request in another language. Passing include_exercises=true switches to the detail builder, which does fall back to English.

include_exercises=true adds a workout_sequences array to every item with full exercise and AI-model detail. It is a much larger payload: use it for a workout player, not for a browsing list.




Get one workout


text
1GET /api/workouts/client/{id}

{id} accepts a numeric ID (88), a legacy 20-character Firestore ID, or a title (Upper Body Starter). Titles are normalized before matching, so spacing, hyphens, and casing do not matter. URL-encode spaces as %20.


ParameterTypeDefaultDescription
langstringenLanguage code, overrides the headers
include_audiobooltruefalse omits generated coaching audio URLs

This endpoint always returns the full exercise sequence. There is no include_exercises toggle on it.


bash
1curl "https://data.kinestex.com/api/workouts/client/88?include_audio=false" \
2  -H "x-api-key: YOUR_API_KEY"

json
1{
2  "id": 88,
3  "created_at": "2026-01-14T10:00:00Z",
4  "updated_at": "2026-02-02T08:30:00Z",
5  "category": "Strength",
6  "calories": 250,
7  "type": "Upper Body",
8  "dif_level": "Easy",
9  "desc_img_url": "https://firebasestorage.googleapis.com/.../desc.png?alt=media",
10  "total_time": 1800,
11  "total_minutes": 30,
12  "body_parts": ["Chest", "Triceps"],
13  "translation": {
14    "id": 201,
15    "language": "en",
16    "title": "Upper Body Starter",
17    "description": "A short push-focused session.",
18    "dif_level": "Easy"
19  },
20  "auto_calculate": false,
21  "turn_off_time_reminder": false,
22  "turn_off_sound_reminder": false,
23  "created_by": { "id": 1 },
24  "workout_sequences": [
25    {
26      "id": 100,
27      "workout_id": 88,
28      "exercise_id": 0,
29      "order": 1,
30      "countdown": 10,
31      "repeats": null,
32      "video_url": null,
33      "thumbnail_url": null,
34      "is_rest_sequence": true,
35      "created_at": "2026-01-14T10:00:00Z",
36      "updated_at": "2026-01-14T10:00:00Z"
37    },
38    {
39      "id": 101,
40      "workout_id": 88,
41      "exercise_id": 412,
42      "order": 2,
43      "countdown": null,
44      "repeats": 12,
45      "video_url": null,
46      "thumbnail_url": null,
47      "is_rest_sequence": false,
48      "created_at": "2026-01-14T10:00:00Z",
49      "updated_at": "2026-01-14T10:00:00Z",
50      "exercise": {
51        "id": "412",
52        "ai_model": { "id": "57" },
53        "repeats": 12,
54        "countdown": null,
55        "thumbnail_url": "https://firebasestorage.googleapis.com/.../thumb.png?alt=media",
56        "video_url": "https://firebasestorage.googleapis.com/.../video.mp4?alt=media",
57        "difficulty_level": "easy",
58        "position": "lying",
59        "calories_per_rep": 0.32,
60        "body_parts": ["Chest", "Triceps"],
61        "categories": ["Strength"],
62        "is_active": true,
63        "correct_second": 1.5,
64        "translation": {
65          "title": "Push Ups",
66          "language": "en",
67          "description": "A pushing movement for chest and triceps."
68        },
69        "created_by": { "id": 1 }
70      }
71    }
72  ]
73}

Detail-only fields


FieldTypeDescription
total_minutesnumbertotal_time divided by 60, for display
auto_calculateboolCalories are recomputed from the exercise list
turn_off_time_reminderboolTime reminders disabled for this workout
turn_off_sound_reminderboolSound reminders disabled for this workout
workout_sequencesarrayOrdered entries, see below

Workout sequence entry


FieldTypeDescription
ordernumberPosition in the workout, ascending
is_rest_sequencebooltrue for a rest block; exercise is then absent
countdownnumber or nullTimer length in seconds, for timed entries and rests
repeatsnumber or nullRepetition target, for rep-based entries
video_url / thumbnail_urlstring or nullPer-sequence overrides of the exercise assets
exerciseobjectFull exercise detail, same shape as GET /api/exercises/client/{id}
exercise_idnumber0 on rest entries
translationobjectRest-period speech text and audio, when the sequence has one

Not found returns 404 { "error": "Workout not found" }.


A workout deactivated in the KinesteX library disappears from the list but stays fetchable by ID, so plans that already reference it keep working.