Per-client metric trend
const url = 'http://localhost:8000/api/dashboard/client/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/trend/?activity=example';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/dashboard/client/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/trend/?activity=example' \ --header 'Authorization: Bearer <token>'Per-session timeline of one metric for one client over an (activity, range) window. Each point in series carries the metric value at that session, the composite score, and the spec target band (min_good/max_good). activity_breakdown lets the frontend render the activity-tabs strip without a second round-trip.
Unknown activity → 404; unknown metric → 400; client not on the active team → 404.
Source-of-truth doc: project_context/product/COACH_DASHBOARD_PLAN.md §6 / §9.1.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Client UUID. Must belong to the active team — otherwise 404.
Query Parameters
Section titled “Query Parameters”One of the closed Activity enum values.
Custom-range start (ISO YYYY-MM-DD, inclusive). Takes precedence over range.
MetricSpec key. Defaults to the first headline metric for the activity.
Preset look-back — 7d / 14d / 30d / 90d / 365d. Mutually exclusive with from/to.
Custom-range end (ISO YYYY-MM-DD, inclusive). Defaults to today.
Viewer’s IANA timezone (e.g. America/Chicago). The look-back window AND the daily/weekly buckets are computed in it, so a session lands on the coach’s local day, not the server’s UTC day. Omit to fall back to UTC (legacy / partner-key callers).
Responses
Section titled “Responses”Shape of GET /api/dashboard/client/{id}/trend/.
object
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
ISO date of the window’s first day (inclusive).
ISO date of the window’s last day (inclusive).
object
One of the canonical Unit literal strings (see domain/metrics/base.py).
Metric has not cleared clinical / force-plate validation; the UI shows a ‘beta’ precision caveat.
object
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
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.
First recorded value in the window — the progress reference. Null when no session has a value. #609 Phase 3.
Best value in the window, by the metric’s higher_is_better. Null when no value, or the metric has no good/bad direction. #609 Phase 3.
One AI-coach insight attached to a dashboard response.
Server returns the i18n keys + interpolation vars; the frontend renders the localised copy. This keeps server-side from owning user-facing English/Russian strings.
object
Semantic category — drives icon + i18n key on the client.
Drives the tone-bar colour: info → sleep, warning → form, critical → recovery-low.
info- infowarning- warningcritical- critical
I18n key for the headline. Frontend interpolates with title_vars.
Vars for title_key interpolation.
object
object
Example
{ "activity": "running", "activity_breakdown": [ { "activity": "running" } ], "recommendations": [ { "severity": "info" } ]}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
404 — No active team
{ "detail": "No active team — finish onboarding first."}