Skip to content

Cross-roster view of one activity

GET
/api/dashboard/activity/{activity}/
curl --request GET \
--url http://localhost:8000/api/dashboard/activity/example/ \
--header 'Authorization: Bearer <token>'

Returns the cohort timeseries (median + IQR), per-client leaderboard with headline metric values, and an outlier strip of clients whose latest readings fall outside the MetricSpec target zone.

Range must be one of 7, 14, 30, 90. Bucketing switches from daily to weekly above 30 days. The metric must be one of the activity’s available_metrics; missing → 400 with the valid set listed. Unknown activity404.

Source-of-truth doc: project_context/product/COACH_DASHBOARD_PLAN.md §5 / §9.1.

activity
required
string

One of the closed Activity enum values: running, walking, jump, weightlifting, mobility, agility, fencing, workspace_wellness. Unknown → 404.

athlete
string format: uuid

Optional Client id — overlays that athlete’s per-bucket series for metric on the cohort distribution chart (athlete_series, aligned 1:1 with cohort). Omit for no overlay. A malformed id, or a client that isn’t the caller’s team, returns 404.

exercise
string

Exercise preset to narrow the cohort to — one of the activity’s available_exercises. Scopes the cohort, athlete overlay, leaderboard, and outliers to that exercise and narrows available_metrics + headline_metrics to the metrics it emits; when the current metric isn’t emitted by the exercise it falls back to the exercise’s first metric. Unknown exercise → 400. Omit for the all-exercises view. #795.

from
string format: date

Custom-range start (ISO YYYY-MM-DD, inclusive). Takes precedence over range.

group
string format: uuid

Optional ClientGroup id — narrows every roster / cohort / leaderboard / outlier figure to that group’s members. Omit for the whole-team view. A malformed id, or a group that isn’t the caller’s team, returns 404.

metric
string

MetricSpec key driving the cohort timeseries. Defaults to the first entry of the activity’s HEADLINE_METRICS list. Must be a member of available_metrics.

range
string

Preset look-back — 7d / 14d / 30d / 90d / 365d. Mutually exclusive with from/to.

to
string format: date

Custom-range end (ISO YYYY-MM-DD, inclusive). Defaults to today.

tz
string

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

Media typeapplication/json

Shape of GET /api/dashboard/activity/{activity}/.

object
activity
required
  • running - Running
  • walking - Walking
  • jump - Vertical Jump
  • weightlifting - Weightlifting
  • mobility - Mobility Assessment
  • workspace_wellness - Workspace Wellness
  • agility - Agility
  • fencing - Fencing
  • cycling - Cycling
  • tennis - Tennis
  • padel - Padel Tennis
  • bowling - Bowling
  • baseball - Baseball
  • football - Football
  • badminton - Badminton
  • cricket - Cricket
  • basketball - Basketball
  • scuba_diving - Scuba Diving
  • ice_hockey - Ice Hockey
  • american_football - American Football
  • fri - Falls Risk Indicator
string
Allowed values: running walking jump weightlifting mobility workspace_wellness agility fencing cycling tennis padel bowling baseball football badminton cricket basketball scuba_diving ice_hockey american_football fri
range_days
required
integer
range_start
required

ISO date of the window’s first day (inclusive).

string format: date
range_end
required

ISO date of the window’s last day (inclusive).

string format: date
granularity
required

Bucket granularity the cohort series is binned to. Picked from window length: ≤30d → day, ≤120d → week, otherwise month.

  • day - day
  • week - week
  • month - month
string
Allowed values: day week month
metric
required

MetricSpec key the cohort timeseries was computed against.

string
cohort_size
required

Clients with a latest score in scope — the denominator behind each leaderboard row’s standing rank (#3 of {cohort_size}). #609 Phase 2.

integer
cohort_median
required

Median latest score across the standing cohort. Null when no client has a scored session. #609 Phase 2.

number format: double
nullable
available_metrics
required

Closed list of cohort-switchable metrics. Narrowed to the chosen ?exercise=’s specs when it is set (#795); otherwise the activity-wide union, deduped by key across exercises.

Array<object>
object
key
required
string
label
required
string
unit
required

One of the canonical Unit literal strings (see domain/metrics/base.py).

string
higher_is_better
required
boolean
nullable
min_good
required
number format: double
nullable
max_good
required
number format: double
nullable
beta
required

Metric has not cleared clinical / force-plate validation; the UI shows a ‘beta’ precision caveat.

boolean
available_exercises
required

Exercise presets of the activity (preset_exercises) for the cohort exercise sub-filter (#795). One entry for single-exercise activities; the frontend hides the control below 2. Filter via ?exercise=<name>.

Array<string>
headline_metrics
required

Up to 4 keys the leaderboard surfaces as named columns. Driven by HEADLINE_METRICS in the dashboard service.

Array<string>
cohort
required
Array<object>
object
bucket
required

Bucket label. ISO date for range_days ≤ 30 (daily); ISO Monday-of-the-week for larger ranges (weekly).

string
median
required

Median value of the chosen metric across the cohort in the bucket. Null when the bucket is empty.

number format: double
nullable
p25
required

25th percentile (inclusive). Renders as the lower edge of the IQR band on the timeline chart.

number format: double
nullable
p75
required

75th percentile (inclusive). Upper edge of the IQR band.

number format: double
nullable
count
required

Number of athletes contributing to this bucket — each athlete counts once regardless of how many sessions they posted. Zero for empty buckets.

integer
athlete_series
required

The overlay athlete’s per-bucket values for metric, aligned 1:1 with cohort (one entry per bucket, null where that athlete has no session that bucket). Present only when ?athlete=<client_id> is supplied; null otherwise. #609.

Array<number>
nullable
leaderboard
required
Array<object>
object
client_id
required

Client UUID.

string format: uuid
client_name
required

display_nameemail → empty.

string
last_session_id
required

UUID of the most-recent completed session in the range.

string format: uuid
nullable
last_session_at
required

created_at of that session.

string format: date-time
nullable
score
required

score SessionMetric value (0..100) when present.

number format: double
nullable
metrics
required

Headline metric values keyed by MetricSpec.key. Missing keys → null.

object
key
additional properties
number format: double
nullable
rank
required

1-based overall standing within the in-scope cohort, by composite score (1 = best; ties share a rank). NOT the selected cohort metric — a per-metric rank misleads for band-optimal metrics + contradicts score. Null when the client has no scored session. #609 Phase 2.

integer
nullable
percentile
required

0-100 — the share of other in-scope clients this client beats on composite score (best → 100). Null for a single-client cohort or a client with no scored session. #609 Phase 2.

number format: double
nullable
score_delta
required

Composite-score progress vs the client’s personal baseline (latest − the score at their earliest in-range session). The small per-row ‘vs baseline’ delta. Null when the client has a single in-range session or that earliest session carries no score. #609 Phase 2.

number format: double
nullable
outliers
required
Array<object>
object
client_id
required
string format: uuid
client_name
required
string
metric
required

MetricSpec.key whose latest reading breaches the spec band.

string
value
required

The actual value that breached.

number format: double
direction
required

above = value > max_good; below = value < min_good.

  • above - above
  • below - below
string
Allowed values: above below
target_min
required

MetricSpec.min_good for context — the POPULATION default, not this athlete’s resolved band, so the roster ranks every client against one yardstick. Deliberate and unchanged by #1317; note it can therefore flag an athlete whose own card reads in-zone.

number format: double
nullable
target_max
required

MetricSpec.max_good — population, see target_min.

number format: double
nullable
generated_at
required
string format: date-time
recommendations
required
Array<object>

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
kind
required

Semantic category — drives icon + i18n key on the client.

string
severity
required

Drives the tone-bar colour: info → sleep, warning → form, critical → recovery-low.

  • info - info
  • warning - warning
  • critical - critical
string
Allowed values: info warning critical
title_key
required

I18n key for the headline. Frontend interpolates with title_vars.

string
title_vars
required

Vars for title_key interpolation.

object
key
additional properties
body_key
required
string
nullable
body_vars
required
object
key
additional properties
cta_label_key
required
string
nullable
cta_href
required
string
nullable
Example
{
"activity": "running",
"granularity": "day",
"outliers": [
{
"direction": "above"
}
],
"recommendations": [
{
"severity": "info"
}
]
}
Media typeapplication/json
object
detail
required

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

string
Examplegenerated
{
"detail": "example"
}
Media typeapplication/json
object
detail
required

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

string
Examplegenerated
{
"detail": "example"
}
Media typeapplication/json
object
detail
required

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

string
Examples

404 — Unknown activity

{
"detail": "Unknown activity: 'curling'"
}