Across-session trends for the session's visible metrics
const url = 'http://localhost:8000/api/sessions/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/trends/';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url http://localhost:8000/api/sessions/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/trends/ \ --header 'Authorization: Bearer <token>'Returns the across-session trajectory for every single-scalar metric the coach hasn’t hidden, in one call — keyed off the session’s OWN client + activity, filtered by the coach’s server-side curation (/api/me/hidden-metrics/). Powers the player Summary’s Current (delta vs prior + compact sparkline) and Dynamics (across-session chart) views and the PDF trend section, so all three read the same data.
Each metric carries THIS athlete’s resolved target band (the same one her session card, PDF and Solutions report show — domain.target_bands, #1317, not the MetricSpec population default) + higher_is_better (improvement tone, not raw direction) and a series of one point per completed session in the window — with delta_vs_prev, baseline and is_personal_best. Bilateral L/R pairs and the composite score are excluded (the player shows the pair card without a sparkline). metrics is empty when the session has no client, no in-window history, or every trendable metric is hidden. Window defaults to a year; narrow with ?range=30d or ?from=&to=.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Query Parameters
Section titled “Query Parameters”Custom window start (YYYY-MM-DD); wins over range.
Preset window: one of 7d/14d/30d/90d/365d (default 365d). Mutually exclusive with from/to.
Custom window end (YYYY-MM-DD); defaults to today.
IANA timezone for day boundaries (UTC fallback).
Responses
Section titled “Responses”Shape of GET /api/sessions/{id}/trends/ — across-session
trajectories for the session’s visible metrics, in one call (#424).
object
Null when the session has no client — metrics is then empty (no across-session history without a client).
running- Runningwalking- Walkingjump- Vertical Jumpweightlifting- Weightliftingmobility- Mobility Assessmentworkspace_wellness- Workspace Wellnessagility- Agilityfencing- Fencingcycling- Cyclingtennis- Tennispadel- Padel Tennisbowling- Bowlingbaseball- Baseballfootball- Footballbadminton- Badmintoncricket- Cricketbasketball- Basketballscuba_diving- Scuba Divingice_hockey- Ice Hockeyamerican_football- American Footballfri- Falls Risk Indicator
One visible metric’s across-session trajectory.
object
Canonical Unit literal (see domain/metrics/base.py).
Drives the delta tone — improvement, not raw direction. Null for a directionless metric.
Lower green bound, resolved for THIS athlete (domain.target_bands, #1317), mirroring the per-client trend. Null when no curated zone applies.
First recorded value in the window — the progress reference the compact sparkline + Dynamics chart both draw.
object
Metric value at this session. Null when the analyzer didn’t emit it (e.g. front-only metric on a side-view session).
Composite score for the session, when present.
Lower green bound, resolved for THIS athlete (domain.target_bands, #1317) — the same band the session card, the PDF and the Solutions report show, not the MetricSpec population default. Null when no curated zone applies.
True / false / null. Null when value or zone is missing.
This value minus the previous recorded (non-null) value in the window — null for the first reading or a null value. The per-session Δ. #609 Phase 3 (shared with #424).
True when this value equals the window’s best (by higher_is_better) — drives the personal-best marker. #609 Phase 3.
Examples
One running session's curated metrics, each with its across-session trajectory
{ "session_id": "3f9a…", "client_id": "c1a2…", "activity": "running", "exercise": "Treadmill Run", "range_days": 365, "range_start": "2025-06-24", "range_end": "2026-06-24", "generated_at": "2026-06-24T12:00:00Z", "metrics": [ { "key": "cadence", "label": "Cadence", "unit": "spm", "higher_is_better": true, "target_min": 165, "target_max": 180, "baseline": 151, "personal_best": 168, "series": [ { "session_id": "a1…", "created_at": "2026-03-04T09:00:00Z", "value": 151, "score": 72, "target_min": 165, "target_max": 180, "in_zone": false, "delta_vs_prev": null, "is_personal_best": false }, { "session_id": "3f9a…", "created_at": "2026-06-24T09:00:00Z", "value": 168, "score": 88, "target_min": 165, "target_max": 180, "in_zone": true, "delta_vs_prev": 4, "is_personal_best": true } ] } ]}object
Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).
Examplegenerated
{ "detail": "example"}object
Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).
Examplegenerated
{ "detail": "example"}object
Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).
Examples
Absent, or owned by another team (collapsed to 404)
{ "detail": "session_not_found"}