---
title: "Today as one timeline: the days ahead, today, and what was recorded, with notes"
method: GET
path: "/training/timeline"
tags: ["Training"]
---

# Today as one timeline: the days ahead, today, and what was recorded, with notes

`GET /training/timeline`

## Request

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

Without `before`: the next seven days and events in the next six weeks, today, and the last `days` days, with the notes. With `before`: the `days` days before it, recorded entries and week reviews only.

## Query parameters

- `before` string, date: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
- `days` integer

## Headers

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

## Response `200`

OK

- object
  - `today` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
  - `timeZone` string, required
  - `entries` union[], required: Newest first: the furthest planned day at the top, then today, then the past, back to `from`.
    - union
      - object
        - `type` 'planned', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `day` object, required
          - `date` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
          - `precision` string, required: session: today or tomorrow, the same session as that card. outline: a later day — class, sport and an approximate duration, no targets. Known values: session, outline. Treat unknown values as "other".
          - `sessionClass` 'rest' | 'recovery' | 'easy' | 'build' | 'quality' | 'strength' | 'complete', required
          - `kind` 'endurance' | 'strength' | 'rest', required
          - `modality` string, nullable, required: Sport, from the engine's vocabulary (packages/engine/src/sports.ts), e.g. road_biking, running, hiking, strength_training. Known values: road_biking, running, hiking, strength_training, other. Treat unknown values as "other".
          - `durationMin` number, nullable, required: Exact on a session day, rounded to 5 minutes and approximate on an outline day; null on a rest day.
          - `workoutName` string, nullable, required: The workout's name, on a session day only.
          - `commitment` object, nullable, required: Set when this day's session is one the athlete arranged themselves rather than one Body Lab chose — a club ride, a run with friends — and carrying its name. Present on an outline day too, unlike `workoutName`: the sport and a duration alone are indistinguishable from a session Body Lab invented, and a surface drawing the week should name the athlete's own arrangement so they recognise it. Null on every other day, including a day with a commitment on it that something else took over (a race on the same date, or an illness that replaced the session).
            - `name` string, required: What the athlete called it: "Ride with Nick and Rachael".
          - `alsoCommitted` object[]: The other sessions arranged on this date, beside the one the day is drawn as — the routine after a club ride, a second ride. A strength session here after an endurance day also sets `strengthAfter`. Absent when the date holds one committed session or none.
            - `name` string, required: What the athlete or the app called it.
            - `kind` 'endurance' | 'strength', required
            - `modality` string, nullable, required: Sport, from the engine's vocabulary (packages/engine/src/sports.ts), e.g. road_biking, running, hiking, strength_training. Known values: road_biking, running, hiking, strength_training, other. Treat unknown values as "other".
            - `durationMin` number, required: At the day's precision, like `durationMin`: exact on a session day, rounded to 5 minutes on an outline day.
          - `longest` boolean, required: The week's long session: its longest endurance day, when that's 90 minutes or more.
          - `strengthAfter` boolean, required: A strength session follows the day's endurance session: the strength floor is owed one, and it's offered once the ride or run is done.
          - `deload` boolean, required: A planned volume cut: a recovery week, a taper or post-event recovery.
          - `phase` string, nullable, required: What shapes the day beyond its session. Known values: event_day, taper, recovery, recovery_week. Treat unknown values as "other".
          - `preparation` string, nullable, required: Which part of the run-up to an A event a day sits in. An emphasis worked out each morning from the event's date, not a stored plan. Known values: base, build, specific, taper. Treat unknown values as "other".
          - `events` object[], required: Events on this date, any priority.
            - `id` string, required: Opaque identifier.
            - `name` string, required
            - `priority` 'A' | 'B' | 'C', required: What Body Lab does with the event. A: the plan is built around it — the run-up is shaped into preparation phases, volume tapers into it, the day before is short and easy, and a recovery window is protected after it. B and C: on the athlete's calendar, where they tilt which sport a nearby day picks but change no session; the two behave identically. Any event, at any priority, makes its own date an event day, when nothing is prescribed. The letters come from a coaching convention Body Lab never explains to the athlete, so say what the priority does rather than reading the letter back to them.
          - `assumedHealth` object, nullable, required: An illness or injury still open on this day, which the projection assumes hasn't cleared — nobody knows the day it will. Null today, and on days with none.
            - `illness` string, nullable, required: mild: symptoms above the neck only (runny or blocked nose, sneezing, sore throat). systemic: fever, chest symptoms, body aches or feeling generally unwell. The split is a widely used convention, not an evidence-based threshold. Known values: mild, systemic. Treat unknown values as "other".
            - `injuries` string[], required
          - `estimatedLoad` number, nullable, required: Estimated training load if the day goes as shown, on Body Lab's calibrated scale, rounded to 5: the load the projection counts the day as adding before it decides the next. Null when there's none — a rest day, today once a recording has settled it, and an event day, whose race the projection doesn't estimate.
          - `strain` object, nullable, required: The projected strain this day was decided with, against the athlete's own high; null when there's too little history for one. An estimate, like the rest of the projection.
            - `value` number, required: The projected strain this day was decided with (the last seven completed days' load times their monotony), rounded to 10.
            - `high` number, nullable, required: This day's own personal high, rounded to 10. It can move within the week as the projected days enter the history it's read over; null without enough history.
            - `above` boolean, required: Whether the engine counts this day's strain as above the athlete's high. Its own test, which also needs the week to be monotonous and heavy against chronic load, so a value over `high` can still be false; never compare the two numbers instead.
            - `reliable` boolean, required: False when an event day after today lies inside this day's seven-day window: the race's load is missing from the projection, so the strain understates.
          - `againstWarning` string, nullable, required: Why this day's class goes against a warning showing today. strain_eased: today's strain is above the athlete's high, and by this day the projection takes it back under, so a hard day the strain rule would have held easy is allowed. Only on a training day after today that the athlete didn't arrange, and never past an event the projection can't estimate. Known values: strain_eased. Treat unknown values as "other".
      - object
        - `type` 'event', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `event` object, required
          - `id` string, required: Opaque identifier.
          - `name` string, required
          - `sport` string, required: Sport, from the engine's vocabulary (packages/engine/src/sports.ts), e.g. road_biking, running, hiking, strength_training. Known values: road_biking, running, hiking, strength_training, other. Treat unknown values as "other".
          - `priority` 'A' | 'B' | 'C', required
          - `eventDate` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
          - `daysUntil` integer, required
      - object
        - `type` 'today', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
      - object
        - `type` 'activity', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `at` string, date-time, required: When it started.
        - `activity` object, required: A recorded activity, or a strength session logged on its own (`kind: strength`).
          - `kind` 'activity' | 'strength', required: activity: a recorded or typed-in activity. strength: a logged strength session with no recording.
          - `id` string, required: Opaque identifier.
          - `startTime` string, date-time, required: An instant: ISO-8601 with offset, e.g. 2026-09-13T06:30:00Z.
          - `activityType` string, required: Sport, from the engine's vocabulary (packages/engine/src/sports.ts), e.g. road_biking, running, hiking, strength_training. Known values: road_biking, running, hiking, strength_training, other. Treat unknown values as "other".
          - `label` string, required: The activity's name, or its sport when it has none.
          - `typeLabel` string, required: The sport, for display.
          - `source` string, nullable, required: Where the activity came from. manual (typed in) and file (uploaded) are Body Lab's own; any other value is the service the athlete synced it from.
          - `durationS` number, nullable, required
          - `distanceM` number, nullable, required
          - `load` number, nullable, required: Training load on Body Lab's calibrated scale.
          - `loadSource` string, nullable, required: Which evidence an activity's load was derived from, best first. Known values: provider, stream_trimp, avg_hr_trimp, srpe, duration. Treat unknown values as "other".
          - `hasTrack` boolean, required
          - `hasStrengthLog` boolean, required
        - `route` array[], required: The route, simplified for a card: every turn the card can show is kept and straight stretches are dropped, at most 400 points, start first. Empty without a track, and for a strength session logged on its own.
          - unknown[]: [longitude, latitude] in degrees.
            - unknown
        - `planned` boolean, required: True when this activity is the one a plan for its day was matched to. Always false for a strength session logged on its own, which has no plan pairing.
      - object
        - `type` 'sleep', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `minutes` integer, required: Minutes asleep, as the day's resolved sleep_minutes.
        - `startMin` integer, nullable, required: The sleep period's start, minutes after 12:00 the day before `date` (wellness sleepStartMin).
        - `endMin` integer, nullable, required: Its end, on the same scale. Both or neither.
        - `endAt` string, date-time, nullable, required: An instant: ISO-8601 with offset, e.g. 2026-09-13T06:30:00Z.
        - `source` string, nullable, required: Where the night's numbers came from.
      - object
        - `type` 'readings', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `restingHr` integer, nullable, required
        - `hrv` integer, nullable, required: Overnight HRV (RMSSD), ms.
        - `at` string, date-time, nullable, required: An instant: ISO-8601 with offset, e.g. 2026-09-13T06:30:00Z.
      - object
        - `type` 'review', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `weekStart` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
        - `review` object, required: The engine's review of the week, as GET /training/weekly-review returns it. Only the latest complete week carries `ahead` and `event`.
          - `weekStart` string, date, required: The Monday the week starts on.
          - `weekEnd` string, date, required: The Sunday it ends on.
          - `latest` boolean, required: The most recent complete week. Only it carries `ahead` and `event`.
          - `previousWeek` string, date, nullable, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
          - `nextWeek` string, date, nullable, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
          - `units` 'metric' | 'imperial', required: How to display quantities; the API always speaks SI.
          - `hasData` boolean, required: Whether anything was recorded, planned or reported that week.
          - `headline` string, required: The week in one line.
          - `sessions` object, required
            - `committed` integer, required: Sessions on the week's plan: ones the athlete planned, exported or sent to a device, plus commitments they said were happening. The only ones there is anything to compare the week against. Equals `items.length`, and the five counts below partition it.
            - `asPrescribed` integer, required
            - `differently` integer, required
            - `skipped` integer, required: Planned sessions with nothing in their place, on days Body Lab could have seen.
            - `unmeasured` integer, required
            - `noData` integer, required: Planned sessions on days no data could have reached Body Lab. Not skips: nothing is known about them either way.
            - `notRecorded` integer, required: Commitments — sessions the athlete said were happening — that nothing was matched to. Not skips: Body Lab never prescribed them, and it holds nobody to an arrangement it had no part in.
            - `items` object[], required
              - …
            - `done` object, required
              - …
            - `summary` string, required: A sentence to show as written: it cites the number it rests on.
          - `load` object, required
            - `weekLoad` number, required
            - `conditionedWeekLoad` number, nullable, required: Chronic load × 7 the day before the week: what a loading week is judged against. Null without a base.
            - `acwrLow` number, required: The bottom of the acute:chronic band.
            - `acwrHigh` number, required: The top of the band.
            - `acwrEnd` number, nullable, required
            - `acwrMin` number, nullable, required
            - `acwrMax` number, nullable, required
            - `daysAboveBand` integer, required
            - `daysBelowBand` integer, required
            - `daysInBand` integer, required
            - `chronicStart` number, nullable, required: Chronic load (CTL) the day before the week.
            - `chronicEnd` number, required: Chronic load on the Sunday.
            - `rampRate` number, nullable, required: Chronic load's change over the week, as a fraction.
            - `rampCeiling` number, required: The weekly change the engine holds chronic load under, as a fraction.
            - `loadingWeeks` integer, required: Completed weeks in a row above chronic load; three earn a recovery week.
            - `summary` string[], required
          - `strength` object, required
            - `sessions` integer, required
            - `floor` integer, required: Strength sessions a week the engine defends.
            - `met` boolean, required
            - `last14` integer, required: Sessions in the 14 days to the Sunday, the count the engine's own rule reads.
            - `unloggedRecordings` integer, required: Strength workouts a device recorded that were never logged, which the floor can't count.
            - `liftsOnHardDays` integer: Logged lifts on a day that also held an interval session (a long steady session doesn't count). Counted at every focus; the summary mentions it only for the two strength options, which keep lifts off interval days.
            - `focus` string: The training focus the week was measured against, the profile's now. An unknown stored value is read as endurance. Known values: endurance, strength, strength_first. Treat unknown values as "other".
            - `summary` string, required: A sentence to show as written: it cites the number it rests on.
          - `reported` object, required
            - `items` object[], required
              - …
            - `shortOnTimeDays` integer, required
            - `shortestTimeMin` integer, nullable, required
            - `awayFromEquipmentDays` integer, required
            - `summary` string[], required
          - `ahead` object, nullable, required: The next seven days as projected today, for the latest week only. A projection: show its note with it.
            - `from` string, date, required: The day the projection was made: today.
            - `changes` object[], required: What changes in the next seven days and why, most significant first.
              - …
            - `projection` object, required: The sessions the engine expects for the coming week if every day goes as shown. A projection, not a plan: each day is decided that morning.
              - …
          - `event` object, nullable, required: The nearest A event in the next eight weeks, for the latest week only.
            - `id` string, required: Opaque identifier.
            - `name` string, required
            - `eventDate` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
            - `sport` string, required: Sport, from the engine's vocabulary (packages/engine/src/sports.ts), e.g. road_biking, running, hiking, strength_training. Known values: road_biking, running, hiking, strength_training, other. Treat unknown values as "other".
            - `daysUntil` integer, required
            - `phase` string, required: Where the athlete is relative to it. Known values: build, taper. Treat unknown values as "other".
            - `preparation` object, nullable, required: The emphasis of the current block of training before the athlete's nearest A event. Recomputed every morning from the event's date and expected duration; readiness still decides each day, and a phase never overrides a rest day, a taper or a recovery window.
              - …
            - `taperStartsOn` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
            - `status` string, required: on_track: no rule the engine applies counts against it. at_risk: one does (the goal-at-risk flag, or the return-to-impact gate). too_little_evidence: no training in its sport to judge from. Known values: on_track, at_risk, too_little_evidence. Treat unknown values as "other".
            - `headline` string, required: A sentence to show as written: it cites the number it rests on.
            - `supports` string[], required: What the training so far shows, as facts.
            - `notYet` string[], required: What it doesn't support yet, from rules the engine already applies.
            - `note` string, required: Said with the section, every time: it isn't a prediction.
        - `marks` object[], required: The week's seven days, Monday first, for the strip.
          - `date` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
          - `mark` string, required: One day's mark (lib/today/past-week.ts markFor). Known values: trained, rest, differently, skipped. Treat unknown values as "other".
      - object
        - `type` 'bloodPressure', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `at` string, date-time, required: When the sitting's first reading was taken; the entry is dated by it too.
        - `systolicMmHg` integer, required: The sitting's average systolic, rounded to a whole mmHg.
        - `diastolicMmHg` integer, required: The sitting's average diastolic, rounded to a whole mmHg.
        - `pulseBpm` integer, nullable, required: The average pulse of the readings that have one, rounded; null when none do.
        - `source` string, required: Where the readings came from: apple_health or manual. A sitting never mixes sources.
        - `readings` object[], required: Every reading in the sitting, earliest first. One reading is a sitting of one, and the numbers above are its own.
          - `at` string, date-time, required: When the cuff read.
          - `systolicMmHg` integer, required
          - `diastolicMmHg` integer, required
          - `pulseBpm` integer, nullable, required
      - object
        - `type` 'checkIn', required
        - `key` string, required: Stable key; see the module comment for the shapes.
        - `date` string, date, required: The local day the entry is drawn under.
        - `at` string, date-time, required: When the update was answered; the entry is dated by the morning it was for, `date`.
        - `feel` integer, nullable, required: 1–5 as the athlete rated the morning, or null: a day counts as answered once its yesterday step is, with or without a feel, and a connected app may answer without one.
        - `feelLabel` string, nullable, required: The feel in the Daily Update's own words (Wrecked, Flat, OK, Good, Ready to go); null with no feel.
        - `summary` string, required: The rest of what was said, in the Daily Update's own words joined with " · ", e.g. "legs heavy · 2 drinks · unwell, above the neck". Possibly empty.
  - `notes` object[], required: On the first page only; empty on later pages.
    - `key` string, required: The rule, e.g. `sleep.short_fortnight`, `progress.best:power_1200s`, `strength.floor`.
    - `subjectKey` string, required: The episode: usually the date the condition first held. A note is the same note for as long as its episode lasts.
    - `family` string, required: Which family it belongs to; "Not for me" mutes a family. Known values: sleep, heart, load, strength, progress, data, plan, event, polarization, monotony, power, anchors, age, strain, pattern. Treat unknown values as "other".
    - `kind` 'insight' | 'observation' | 'milestone' | 'gap', required
    - `attachTo` string, required: The entry it's drawn under. Always an entry on the first page; `today` when its own entry is further back.
    - `headline` string, required
    - `text` string, required
    - `detail` string, nullable, required: Shown on expand: the caveats and, for sleep, the clinical boundary sentence.
    - `collapsed` boolean, required: Past its first 7 days and not worse: drawn as one line under its entry.
    - `basis` 'guideline' | 'own_baseline' | 'convention' | 'engine', required
    - `source` object, nullable, required
      - `citation` string, required
      - `population` string, nullable, required
    - `actions` object[], required
      - `label` string, required
      - `href` string, required
    - `improvement` boolean, required: True only for a `best`. A client must not praise where this is false.
    - `tone` string, required: What the note means for the athlete, which is what a client colors it by (docs/feed-palette.md): positive (green: an improvement, an event on track), caution (amber: something to take care with), info (blue: news, neither good nor bad), neutral (grey: missing data). Independent of `kind`, which names it: most insights are cautions, and a milestone is positive only when it is an improvement. An unknown tone draws as info. Known values: positive, caution, info, neutral. Treat unknown values as "other".
  - `hidden` integer, required: Notes the athlete has hidden that would otherwise show.
  - `from` string, date, required: The earliest day this page covers.
  - `earlier` string, date, nullable, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.

## 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)
