Lyfta Developer API

API Access

Generate credentials, authenticate requests, and understand the workout and exercise data returned by the Lyfta API.

Base URLhttps://my.lyfta.app
60requests per minute
5,000requests per day
100max workouts per page
Credentials

Generate an API key

Shown once

Your API key provides programmatic access to your Lyfta data. Use the button below to generate an API key.

Important Notes:

  • Generating a new API key will automatically revoke and replace any previously active key.
  • Your API key is displayed only once upon generation. Please copy and store it in a safe place immediately. You will not be able to retrieve it again.
1

Generate your key

Create an API key above. A new key revokes and replaces any previously active key.

2

Add the bearer header

Send your key in the authorization header on every request.

3

Page through data

Use limit and page to control list responses.

Usage

Rate Limits

429 on exceed

You can make up to 60 requests per minute and 5,000 requests per day. Exceeding these limits will result in a 429 Too Many Requests response.

Reference

Endpoints

Base URL: https://my.lyfta.app

All requests must include the following header:

Authorization header
Authorization: Bearer YOUR_API_KEY
Write

Create Collection

Use POST /api/v1/collections to create a new program/collection. Send the same Authorization: Bearer YOUR_API_KEY header and a JSON body with Content-Type: application/json.

Request body

The request body must include a collection object. Coaches can optionally include client_id at the top level to create the collection in a client's library instead of their own.

Required fields:

  • collection.title — must be a non-empty string after trimming. Returns "Title is required" if missing or blank.

Optional fields:

  • collection.description — program description.
  • collection.goal — program goal.
  • collection.image — cover image as a base64-encoded string.
  • client_id — coach only. The client's client_id from GET /api/v1/clients. Omit to create in your own library.

Regular API

Creates a collection in the authenticated user's library.

POST /api/v1/collections request
{
  "collection": {
    "title": "My Program",
    "description": "Optional program description",
    "goal": "Optional goal, e.g. strength or hypertrophy",
    "image": "/9j/4AAQSkZJRg...base64-encoded image data..."
  }
}

Coach API

Add client_id to create the collection in an active client's library. Requires a paid Coach or Scale plan and a linked client with status "1".

POST /api/v1/collections request (coach)
{
  "client_id": "dj152auh",
  "collection": {
    "title": "Client Program",
    "description": "Optional program description",
    "goal": "Optional goal",
    "image": "/9j/4AAQSkZJRg...base64-encoded image data..."
  }
}

Response

On success, the API returns the created collection in data, including the new id.

Success response
{
  "status": true,
  "data": {
    "id": 12345,
    "title": "My Program",
    "description": "Optional program description",
    "goal": "Optional goal, e.g. strength or hypertrophy",
    "image": "https://cdnlyfta.com/images/original/example.jpeg"
  }
}

Error when title is missing:

Error response
{
  "status": false,
  "message": "Title is required"
}

Image handling:

  • collection.image must be a base64-encoded image string. URLs are not accepted.
  • The collection is created first, then the image is uploaded and the returned data.image contains the final hosted URL.
  • Omit collection.image to create a collection without a cover image.

Python examples

Python — create collection (regular)
import requests
import json
import base64

API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://my.lyfta.app'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json',
}

with open('cover.jpg', 'rb') as image_file:
    image_base64 = base64.b64encode(image_file.read()).decode('utf-8')

payload = {
    'collection': {
        'title': 'My Program',
        'description': 'Optional program description',
        'goal': 'strength',
        'image': image_base64,
    },
}

response = requests.post(
    f'{BASE_URL}/api/v1/collections',
    headers=headers,
    json=payload,
)

if response.status_code == 200:
    print(json.dumps(response.json(), indent=2))
else:
    print(f"Error {response.status_code}:", response.text)
Python — create collection (coach)
import requests
import json
import base64

API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://my.lyfta.app'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json',
}

with open('cover.jpg', 'rb') as image_file:
    image_base64 = base64.b64encode(image_file.read()).decode('utf-8')

payload = {
    'client_id': 'dj152auh',  # from GET /api/v1/clients
    'collection': {
        'title': 'Client Program',
        'description': 'Optional program description',
        'goal': 'hypertrophy',
        'image': image_base64,
    },
}

response = requests.post(
    f'{BASE_URL}/api/v1/collections',
    headers=headers,
    json=payload,
)

if response.status_code == 200:
    print(json.dumps(response.json(), indent=2))
else:
    print(f"Error {response.status_code}:", response.text)
Write

Create Template

Use POST /api/v1/templates to create a workout template and append it to an existing collection. The template is stored in timeline_templates.data and always linked to the top-level collectionId.

Headers

Required headers
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Top-level fields

FieldTypeRequiredDescription
collectionIdintegerYesCollection that must already exist for the authenticated user (or resolved client). Template is appended to this collection’s workouts list.
clientIdstringNoCoach only. Client public_id (e.g. "dj152auh"). If omitted, template is created for the API key owner.
workoutobjectYesTemplate payload (see below).

workout object

Processed by handleTemplateData(). Stored as JSON in timeline_templates.data.

FieldTypeRequiredDefaultDescription
titlestringNo"My Routine #N"Template name. Auto-generated if empty, "undefined", or "null".
descriptionstringNo""Template description.
notestringNo""Template note.
colorstringNorandom palette colorHex color (e.g. "#178B76"). If omitted, server picks from internal palette.
picturestringNo""Cover image. Base64 data URI (data:image/jpeg;base64,...) uploads to S3, or existing https:// URL. Non-CDN URLs may be cleared by sanitization.
exercisesarrayNo[]List of exercises (order preserved).

Ignored / server-set on create:

  • id — assigned by server after insert
  • user_id — set from auth (or resolved clientId)
  • create_date / update_date — default to current time if omitted

workout.exercises[]

When adding exercises to a template, copy values from the Lyfta exercise catalog (GET /api/v1/exercises) into the template fields below. Four fields must match exactly:

FieldCatalog fieldTypeRequiredDefaultDescription
exercise_ididintegerYes0Must match the catalog id from GET /api/v1/exercises.
excercise_namenamestringYes""Must match the catalog name. Field name uses excercise (legacy spelling).
exercise_typeexercise_typestringYes""Must match the catalog exercise_type (e.g. weight_reps, duration).
exercise_imageimage_namestringYes""Must match the catalog image_name URL.
exercise_notestringNo""Per-exercise note.
exercise_rest_timeintegerNo0Rest time (seconds).
exercise_superset_idintegerNo0Groups supersets; 0 = not in a superset.
is_rep_range_activebooleanNofalseWhether rep range mode is enabled.
workout_idintegerNo0Legacy; not needed on create.
date_createdstringNonowISO/datetime string.
date_updatedstringNonowISO/datetime string.
setsarrayNo[]List of sets for this exercise.

workout.exercises[].sets[]

All set fields are stored as strings (except set_type_id).

FieldTypeRequiredDefaultDescription
set_type_idintegerNo0Set type (e.g. normal vs warmup). 0 = default/normal.
repsstringNo""Reps (e.g. "10").
from_repsstringNo""Rep range lower bound (when range mode is used).
to_repsstringNo""Rep range upper bound.
weightstringNo""Weight value as string (e.g. "60").
rirstringNo""Reps in reserve.
durationstringNo""Duration (for time-based exercises).
distancestringNo""Distance (for distance-based exercises).

Example requests

Minimal (strength template, one exercise, three sets)

Minimal request
{
  "collectionId": 42,
  "workout": {
    "title": "Push day",
    "description": "Chest and shoulders",
    "exercises": [
      {
        "exercise_id": 123,
        "excercise_name": "Bench Press",
        "exercise_type": "weight_reps",
        "exercise_rest_time": 90,
        "sets": [
          { "set_type_id": 0, "reps": "10", "weight": "60" },
          { "set_type_id": 0, "reps": "8", "weight": "65" },
          { "set_type_id": 0, "reps": "6", "weight": "70" }
        ]
      }
    ]
  }
}

With rep range

Rep range request
{
  "collectionId": 42,
  "workout": {
    "title": "Hypertrophy pull",
    "exercises": [
      {
        "exercise_id": 456,
        "excercise_name": "Lat Pulldown",
        "exercise_type": "weight_reps",
        "is_rep_range_active": true,
        "sets": [
          { "from_reps": "10", "to_reps": "12", "weight": "45" },
          { "from_reps": "10", "to_reps": "12", "weight": "45" },
          { "from_reps": "10", "to_reps": "12", "weight": "45" }
        ]
      }
    ]
  }
}

Duration-based exercise

Duration request
{
  "collectionId": 42,
  "workout": {
    "title": "Cardio finisher",
    "exercises": [
      {
        "exercise_id": 789,
        "excercise_name": "Treadmill Run",
        "exercise_type": "duration",
        "sets": [
          { "duration": "600" }
        ]
      }
    ]
  }
}

Coach creating for a client

Coach request
{
  "clientId": "dj152auh",
  "collectionId": 42,
  "workout": {
    "title": "Assigned leg day",
    "exercises": []
  }
}

With cover image (base64)

Cover image request
{
  "collectionId": 42,
  "workout": {
    "title": "Push day",
    "picture": "data:image/jpeg;base64,/9j/4AAQ...",
    "exercises": []
  }
}

Response

On success, data mirrors what is stored in timeline_templates.data (same shape as GetSingleTemplate / GetTemplates).

Success response
{
  "status": true,
  "message": "Template created successfully",
  "collectionId": 42,
  "data": {
    "id": 9812,
    "title": "Push day",
    "description": "Chest and shoulders",
    "note": "",
    "color": "#178B76",
    "picture": "https://cdnlyfta.com/images/original/example.jpeg",
    "user_id": 1001,
    "create_date": "2026-06-15 10:30:00",
    "update_date": "2026-06-15 10:30:00",
    "exercises": []
  }
}

Example error:

Error response
{
  "status": false,
  "message": "collectionId is required"
}

Validation & errors

ConditionResponse
Missing/invalid API keyInvalid API key
Missing workoutworkout is required
Missing collectionIdcollectionId is required
Collection not found for userCollection not found
Invalid clientId (coach)Not allowed to view this user
Rate limit exceededHTTP 429

Notes for integrators:

  • exercise_id, excercise_name, exercise_type, and exercise_image must match the catalog id, name, exercise_type, and image_name from GET /api/v1/exercises.
  • excercise_name spelling is intentional in the stored JSON (legacy app field).
  • weight / reps are strings in storage — send "60" not 60 if you want consistency with the app.
  • exercises can be an empty array (template with no exercises yet).
  • Template is always linked to collectionId; there is no Favorites fallback on this API.
  • picture: prefer base64 upload or an existing Lyfta CDN URL (apilyfta / cdnlyfta hosts).

Python examples

Python — create template (regular)
import requests
import json

API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://my.lyfta.app'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json',
}

payload = {
    'collectionId': 42,
    'workout': {
        'title': 'Push day',
        'description': 'Chest and shoulders',
        'exercises': [
            {
                'exercise_id': 123,
                'excercise_name': 'Bench Press',
                'exercise_type': 'weight_reps',
                'exercise_rest_time': 90,
                'sets': [
                    {'set_type_id': 0, 'reps': '10', 'weight': '60'},
                    {'set_type_id': 0, 'reps': '8', 'weight': '65'},
                    {'set_type_id': 0, 'reps': '6', 'weight': '70'},
                ],
            },
        ],
    },
}

response = requests.post(
    f'{BASE_URL}/api/v1/templates',
    headers=headers,
    json=payload,
)

if response.status_code == 200:
    print(json.dumps(response.json(), indent=2))
else:
    print(f"Error {response.status_code}:", response.text)
Python — create template (coach)
import requests
import json

API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://my.lyfta.app'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json',
}

payload = {
    'clientId': 'dj152auh',  # client_id from GET /api/v1/clients
    'collectionId': 42,
    'workout': {
        'title': 'Assigned leg day',
        'exercises': [],
    },
}

response = requests.post(
    f'{BASE_URL}/api/v1/templates',
    headers=headers,
    json=payload,
)

if response.status_code == 200:
    print(json.dumps(response.json(), indent=2))
else:
    print(f"Error {response.status_code}:", response.text)
Lists

Pagination

List endpoints support pagination via the optional limit and page query parameters. You can request up to 100 workouts per call. Requests specifying a higher limit will be capped at 100.

Example

Python Example

Python
import requests
import json

API_KEY = 'YOUR_API_KEY' # Replace with your actual API key
BASE_URL = 'https://my.lyfta.app' # 

headers = {
    'Authorization': f'Bearer {API_KEY}',
}

# Example: Fetch first page of workouts with up to 10 per page
params = {
    'limit': 10,
    'page': 1,
}

response = requests.get(f'{BASE_URL}/api/v1/workouts', headers=headers, params=params)

if response.status_code == 200:
    data = response.json()
    print("Workouts:")
    print(json.dumps(data, indent=2)) # Pretty print
else:
    print(f"Error {response.status_code}:", response.text)
Schemas

Data Structures

Workout Data Structure

The API returns a list of detailed workouts in the following structure. This is the typical response for GET /api/v1/workouts:

GET /api/v1/workouts response
{
  "status": boolean,
  "count": int,
  "total_records": int,
  "total_pages": int,
  "current_page": int,
  "limit": int,
  "workouts": [
    {
      "id": int,
      "title": string,
      "body_weight": int,
      "workout_perform_date": string, // ISO date or datetime
      "total_volume": int,
      "totalLiftedWeight": int,
      "user": {
        "username": string
      },
      "exercises": [
        {
          "exercise_id": int,
          "excercise_name": string,
          "exercise_type": string, // e.g. "weight_reps"
          "exercise_image": string, // URL
          "exercise_rest_time": int,
          "sets": [
            {
              "id": string,
              "weight": string, // or float as string
              "reps": string, // or int as string
              "rir": string,
              "duration": string,
              "distance": string,
              "set_type_id": string,
              "is_completed": boolean,
              "record_type": string,
              "record_level": string,
              "record_value": string
            }
            // ... more sets ...
          ]
        }
        // ... more exercises ...
      ]
    }
    // ... more workouts ...
  ]
}

Notes:

  • The top-level object contains pagination and status fields, and a workouts array.
  • Each workout contains summary fields, a user object, and an exercises array.
  • Each exercise contains its own sets array, with minimal set fields.
  • Some fields may be optional or null depending on the workout type.

Workout Summary Data Structure

The GET /api/v1/workouts/summary endpoint returns a list of workout summaries with up to 1000 records per call. The structure is as follows:

GET /api/v1/workouts/summary response
{
  "status": boolean,
  "count": int,
  "total_records": int,
  "total_pages": int,
  "current_page": int,
  "limit": int,
  "workouts": [
    {
      "id": string, // or int
      "title": string,
      "description": string | null,
      "workout_duration": string, // e.g. "01:06:25"
      "total_volume": string, // or int as string
      "workout_perform_date": string // ISO date or datetime, e.g. "2025-07-15 06:42:09"
    }
    // ... more workouts ...
  ]
}

Notes:

  • The summary object omits exercise and set details, providing only high-level workout information.
  • All fields are strings except for status, count, total_records, total_pages, current_page, and limit.
  • Use limit to control the number of records returned (up to 1000 per call).

Exercise Data Structure

The GET /api/v1/exercises endpoint returns a list of performed exercises in the following structure:

GET /api/v1/exercises response
{
  "status": true,
  "count": 10,
  "current_page": 1,
  "limit": 10,
  "exercises": [
    {
      "id": "31",
      "name": "Rear Lunge",
      "image_name": "https://apilyfta.com/static/GymvisualPNG/00781101-Barbell-Rear-Lunge_Thighs_small.png",
      "equipment_id": "[\"1\"]",
      "body_part_id": "[\"19\",\"1\"]",
      "Target_muscles_id": "[\"13\",\"27\"]",
      "Synergist_muscles_id": "[\"3\",\"32\"]",
      "exercise_type": "weight_reps"
    },
    // ... more exercises ...
  ]
}

Notes:

  • The exercises array contains objects for each exercise performed.
  • IDs may be strings or numbers depending on the source.
  • Fields like equipment_id, body_part_id, Target_muscles_id, and Synergist_muscles_id are JSON-encoded arrays of IDs.
  • Some fields may be optional or null depending on the exercise.

Exercise Library Search

Use GET /api/v1/exercises/library to search the Lyfta exercise catalog by name. Send the same Authorization: Bearer YOUR_API_KEY header as the other public API endpoints.

Query Parameters:

  • search (optional): Search text, for example bench press.
  • limit (optional): Number of catalog exercises to return.
  • offset (optional): Zero-based offset for pagination.

The response contains catalog exercise records in data.results and cursor-style pagination metadata in data.pagination.

GET /api/v1/exercises/library response
{
  "status": true,
  "data": {
    "results": [
      {
        "id": "2657",
        "name": "Band Bench Press",
        "image_name": "https://apilyfta.com/static/GymvisualPNG/12541101-Band-Bench-Press_Chest_small.png",
        "equipment_id": "[\"11\"]",
        "body_part_id": "[\"2\"]",
        "Target_muscles_id": "[\"24\",\"25\"]",
        "Synergist_muscles_id": "[\"8\",\"44\"]",
        "exercise_type": null
      }
      // ... more catalog exercises ...
    ],
    "pagination": {
      "limit": 10,
      "offset": 0,
      "total": 108,
      "hasMore": true
    }
  }
}

Python example

Python - search exercise library
import requests
import json

API_KEY = 'YOUR_API_KEY' # Replace with your actual API key
BASE_URL = 'https://my.lyfta.app'

headers = {
    'Authorization': f'Bearer {API_KEY}',
}

# Example: Search the Lyfta exercise catalog
params = {
    'search': 'bench press',
    'limit': 10,
    'offset': 0,
}

response = requests.get(
    f'{BASE_URL}/api/v1/exercises/library',
    headers=headers,
    params=params,
)

if response.status_code == 200:
    data = response.json()
    print("Exercise library results:")
    print(json.dumps(data, indent=2)) # Pretty print
else:
    print(f"Error {response.status_code}:", response.text)

Exercise ID Mappings

Exercise metadata fields such as equipment_id, body_part_id, Target_muscles_id, and Synergist_muscles_id are returned as JSON-encoded arrays of IDs. Parse the string first, then map each ID using the tables below.

Example decoded values

FieldRaw valueDecoded value
equipment_id["1"]Barbell
body_part_id["19","1"]Quadriceps, Thighs
Target_muscles_id["13","27"]Gluteus Maximus, Quadriceps
Synergist_muscles_id["3","32"]Adductor Magnus, Soleus

Equipment IDs

Used by equipment_id.

IDName
1Barbell
2Body weight
3Cable
4Dumbbell
5EZ Barbell
6Leverage machine
7Sled machine
8Smith machine
9Weighted
10Assisted
11Band
12Battling Rope
13Bosu ball
14Hammer
15Kettlebell
16Medicine Ball
17Olympic barbell
18Power Sled
19Resistance Band
20Roll
21Rollball
22Rope
23Stability ball
24Stick
25Suspension
26Trap bar
27Vibrate Plate
28Wheel roller

Body Part IDs

Used by body_part_id.

IDName
1Thighs
2Chest
3Hips
4Back
5Upper Arms
6Shoulders
7Forearms
8Calves
9Neck
10Cardio
11Full body
12Waist
13Plyometrics
14Weightlifting
15Yoga
16Stretching
17Biceps
18Triceps
19Quadriceps
20Hamstrings

Muscle IDs

Used by Target_muscles_id and Synergist_muscles_id.

IDName
2Adductor Longus
3Adductor Magnus
4Biceps Brachii
5Brachialis
6Brachioradialis
7Deep Hip External Rotators
8Deltoid Anterior
9Deltoid Lateral
10Deltoid Posterior
11Erector Spinae
12Gastrocnemius
13Gluteus Maximus
14Gluteus Medius
15Gluteus Minimus
16Gracilis
17Hamstrings
18Iliopsoas
19Infraspinatus
20Latissimus Dorsi
21Levator Scapulae
22Obliques
23Pectineous
24Pectoralis Major Clavicular Head
25Pectoralis Major Sternal Head
26Popliteus
27Quadriceps
28Rectus Abdominis
29Sartorius
30Serratus Ante
31Serratus Anterior
32Soleus
33Splenius
34Sternocleidomastoid
35Subscapularis
36Tensor Fasciae Latae
37Teres Major
38Teres Minor
39Tibialis Anterior
40Transverse Abdominis
41Trapezius Lower Fibers
42Trapezius Middle Fibers
43Trapezius Upper Fibers
44Triceps Brachii
45Wrist Extensors
46Wrist Flexors

Coach API (Beta)

Coaches on a paid Coach or Scale plan can use the same API key generated above to access client workout and exercise data programmatically. Authenticate with the same Authorization: Bearer YOUR_API_KEY header on every request.

List active clients

Call GET /api/v1/clients to retrieve your coaching clients. Each client object includes a client_id you will pass to the other endpoints. Active clients have status set to "1"; pending invitations use "0".

GET /api/v1/clients response
{
  "status": true,
  "data": [
    {
      "username": "Hemant (test user)1",
      "photo": "https://cdnlyfta.com/images/original/profilePic_69933e5d8a0836.499124082785.jpeg",
      "first": "Hemant",
      "last": "(test user)1",
      "status": "1",
      "client_id": "dj152auh"
    }
    // ... more clients ...
  ]
}

Fetch client data

Add the client_id query parameter to any of the existing workout and exercise endpoints to return data for that client instead of your own account:

  • GET /api/v1/workouts
  • GET /api/v1/workouts/summary
  • GET /api/v1/exercises
  • GET /api/v1/exercises/progress (also requires exercise_id and duration)
  • POST /api/v1/collections — include client_id in the JSON body (see Create Collection)
  • POST /api/v1/templates — include clientId in the JSON body (see Create Template)

Example params object:

Params with client_id
params = {
  'client_id': 'dj152auh', // from GET /api/v1/clients
  'limit': 10,
  'page': 1,
}

Notes:

  • Omit client_id to fetch your own data, as before.
  • You can only request data for clients linked to your coach account.
  • Response shapes match the data structures documented above.

Python example

Python — list clients and fetch workouts
import requests
import json

API_KEY = 'YOUR_API_KEY' # Same key as the personal data endpoints
BASE_URL = 'https://my.lyfta.app'

headers = {
    'Authorization': f'Bearer {API_KEY}',
}

# Step 1: Fetch active clients and collect their client_id values
clients_response = requests.get(f'{BASE_URL}/api/v1/clients', headers=headers)

if clients_response.status_code != 200:
    print(f"Error {clients_response.status_code}:", clients_response.text)
    exit()

clients_data = clients_response.json()
active_clients = [
    client for client in clients_data.get('data', [])
    if str(client.get('status')) == '1'
]

for client in active_clients:
    client_id = client['client_id']
    print(f"Active client: {client.get('username')} (client_id={client_id})")

    # Step 2: Pass client_id to other endpoints to fetch that client's data
    params = {
        'client_id': client_id,
        'limit': 10,
        'page': 1,
    }

    workouts_response = requests.get(
        f'{BASE_URL}/api/v1/workouts',
        headers=headers,
        params=params,
    )

    if workouts_response.status_code == 200:
        print(json.dumps(workouts_response.json(), indent=2))
    else:
        print(f"Error {workouts_response.status_code}:", workouts_response.text)

Exercise Progress Data Structure

The GET /api/v1/exercises/progress endpoint returns progress data for a specific exercise in the following structure:

GET /api/v1/exercises/progress response
{
  "status": true,
  "weight_unit": "kg",
  "data": [
    {
      "date": "2025-07-21",
      "best_weight": 110,
      "best_reps": 15,
      "best_volume": 800,
      "estimated_rm": "128"
    },
    {
      "date": "2025-07-14",
      "best_weight": 120,
      "best_reps": 15,
      "best_volume": 1000,
      "estimated_rm": "133"
    },
    {
      "date": "2025-06-30",
      "best_weight": 80,
      "best_reps": 20,
      "best_volume": 1600,
      "estimated_rm": "133"
    }
    // ... more records ...
  ]
}

Query Parameters:

  • duration (required): Number of days to include in the progress data (e.g., 365 for one year).
  • exercise_id (required): The ID of the exercise to fetch progress for (from the performed exercise list IDs).

Example params object for a request:

Params
params = {
  'duration': 365, // in days
  'exercise_id': 2, // from the performed exercise list ids
}
  • Both parameters are required for the endpoint to return data.

Notes:

  • The data array contains progress records for the exercise, typically grouped by date.
  • best_weight, best_reps, and best_volume represent the best set or total for that day.
  • estimated_rm is the estimated one-rep max, usually as a string.
  • weight_unit indicates the unit for weight values (e.g., kg or lb).