---
title: "What got better, and what changed"
method: GET
path: "/training/progress"
tags: ["Training"]
---

# What got better, and what changed

`GET /training/progress`

## Request

- Base URL: `https://bodylab.lol/api/v1`
- URL: `https://bodylab.lol/api/v1/training/progress`
- Auth: HTTP bearer

## Query parameters

- `sinceDays` integer: How far back a reading still counts as news. Defaults to 90 days.
- `limit` integer: How many notes at most. Defaults to 24.

## Headers

- `X-Client-Platform` string
- `X-Client-Version` string

## Response `200`

OK

- object
  - `units` 'metric' | 'imperial', required: How to display quantities; the API always speaks SI.
  - `since` string, date, required: The oldest measurement date returned. Readings before it were still read — they are what a best is measured against — but are not reported as news, so a newly connected provider's years of history set the standing bests instead of arriving as dozens of breakthroughs.
  - `notes` object[], required: Ranked: `best` first, then newest week first (counted back from today), then by how far past the floor the move went within a week.
    - `kind` 'best' | 'change' | 'first', required: What kind of note this is, which decides what it is allowed to claim. `best` is a new extreme in a metric training is meant to move — FTP, mean-maximal power, a lift, chronic load, the longest session — so the sentence may call it an improvement. `change` is a move larger than that metric's own normal within-person variation, and the sentence says only that. Body mass, body composition, blood pressure, resting heart rate, HRV, threshold heart rate and every blood marker are always `change`: the app does not assert which direction is better for them, because it has no weight goal to measure a body mass against and because interpreting a pressure or a blood result would be medical advice. `first` is the first time something was recorded.
    - `metric` string, required: A stable key for the metric. Fixed metrics use their own name (`ftp_w`, `resting_hr`); the open families are prefixed — `power_1200s`, `speed_720s`, `heaviest:<exerciseId>`, `distance:<sport>`, `duration:<sport>`, `lab:<marker>`.
    - `label` string, required: The metric's name, capitalised to start a sentence.
    - `unit` string, required: How to write the value out. Values on the wire are always SI — kilograms, metres, seconds, metres per second — and this says which unit a client converts into and prints. `pace` is a speed in metres per second written as minutes per kilometre or mile, so a faster value is a smaller printed number. `printed` carries the unit the lab printed, in `printedUnit`. Known values: watts, mass, bpm, pressure, percent, vo2max, speed, pace, distance, duration, load, density, count, printed. Treat unknown values as "other".
    - `printedUnit` string, nullable, required: For `printed`, the unit the source printed, carried through verbatim.
    - `on` string, date, required: The date of the reading this note is about.
    - `value` number, required: The reading, in SI.
    - `previousValue` number, nullable, required: What it is compared with, in SI. Null for a `first`.
    - `previousOn` string, date, nullable, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
    - `deltaSi` number, nullable, required: Signed difference in the stored unit. Null for a `first`.
    - `fraction` number, nullable, required: Signed difference as a fraction of the earlier value. Null for a `first`, and where the earlier value was zero.
    - `spanDays` integer, nullable, required: Calendar days between the two readings.
    - `improvement` boolean, required: Whether Body Lab asserts this direction is an improvement. True only for `best`. False on every `change`, including ones a reader might assume are good news: a lower blood marker, a lower pressure, a smaller body mass. A client must not add praise where this is false.
    - `floorBasis` 'measured' | 'chosen', required: Where the threshold this note had to clear came from. `measured` is a published within-person coefficient of variation — in practice only blood markers, whose CV(I) comes from the EFLM Biological Variation Database. `chosen` is a threshold Body Lab picked so that measurement noise doesn't read as achievement. Surfaced so a client never implies a number was measured when it was decided.
    - `text` string, required: The sentence to show as written. It cites the numbers it rests on.
  - `waitingOn` string[], required: Metrics with a single reading, so there is nothing to compare yet. The useful form of an empty state.

## Other responses

- `401`: Error: UNAUTHORIZED.

---

[API](https://skmtc.dev/bodylab/apis/body-lab-api.md) · [All operations](https://skmtc.dev/bodylab/apis/body-lab-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bodylab/apis/body-lab-api/revisions/544c201eaf88?raw)
