---
title: "How a finished week went, and what changes next"
method: GET
path: "/training/weekly-review"
tags: ["Training"]
---

# How a finished week went, and what changes next

`GET /training/weekly-review`

## Request

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

Omit `week` for the most recent complete week, which is the only one that also says what comes next and whether training supports an upcoming A event. Weeks run Monday to Sunday on the athlete's calendar.

## Query parameters

- `week` string, date: Any day in the week to review. Defaults to the most recent complete week.

## Headers

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

## Response `200`

OK

- object: A finished week against what was prescribed, and what comes next.
  - `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
      - `prescriptionId` string, required: Opaque identifier.
      - `date` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
      - `modality` 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".
      - `workoutName` string, nullable, required
      - `status` string, required: as_prescribed: matched, with the work there. differently: matched but short of the work, or done as another sport. skipped: nothing in its place that day, on a day Body Lab could have seen. unmeasured: done in the same sport but not matched to the plan (usually no heart-rate or power recording), so not measured. no_data: nothing was matched to it and no data for that day could have reached Body Lab — no connected service or device was delivering and nothing was entered by hand — so there is no evidence either way. not_recorded: a session the athlete told Body Lab was happening (a commitment) that nothing was matched to; Body Lab never prescribed it, so it is reported without a verdict. Never read no_data or not_recorded as a session missed. Known values: as_prescribed, differently, skipped, unmeasured, no_data, not_recorded. Treat unknown values as "other".
      - `reason` string, nullable, required: Why it was done differently. Known values: other_sport, fewer_intervals, less_work. Treat unknown values as "other".
      - `reported` string, nullable, required: What the athlete reported that day, where it explains a skipped or short session. Known values: illness, injury, short_on_time. Treat unknown values as "other".
      - `activityId` string, nullable, required: Opaque identifier.
      - `text` string, required: A sentence to show as written: it cites the number it rests on.
    - `done` object, required
      - `activities` integer, required: Recorded or typed-in activities.
      - `durationS` number, required
      - `load` number, required
      - `strengthSessions` integer, required: Strength sessions logged in Body Lab.
      - `restDays` integer, 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
      - `kind` string, required: What was reported. Known values: illness, injury. Treat unknown values as "other".
      - `label` string, required: How to name it mid-sentence: "a head cold", "your knee".
      - `startedOn` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
      - `clearedOn` string, date, nullable, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
      - `daysInWeek` integer, 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.
      - `headline` string, required: A sentence to show as written: it cites the number it rests on.
      - `detail` string, nullable, required
    - `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.
      - `from` string, date, required: The day this was computed on. It recalculates every day.
      - `days` object[], required: Seven days, today first.
        - `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".
      - `note` string, required: Why the week will change, to show with it wherever it's shown.
      - `assumptions` string[], required: What every projection takes as given, one sentence each.
      - `healthAssumption` string, nullable, required: The illness or injury the week assumes is still active, in a sentence to show with the week; null when there's none.
  - `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.
      - `eventId` string, required: Opaque identifier.
      - `eventName` string, required
      - `phase` string, 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".
      - `week` integer, required: Which week of this phase today is in, from 1.
      - `weeks` integer, required: How many weeks the phase runs for.
      - `startsOn` string, date, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
      - `endsOn` string, date, required: Inclusive: the last day of this phase.
      - `nextPhase` 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".
      - `nextStartsOn` string, date, nullable, required: A day on the athlete's own calendar: YYYY-MM-DD, no time zone.
    - `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.

## Other responses

- `401`: Error: UNAUTHORIZED.
- `409`: Error: WEEK_NOT_COMPLETE.
- `422`: Error: TOO_FAR_BACK.

---

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