Business overview (owner-only)
const url = 'http://localhost:8000/api/dashboard/business/';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/business/ \ --header 'Authorization: Bearer <token>'Cross-coach productivity, daily client-growth chart, activity mix, plan + quota strip, payment health.
Gated by IsTeamOwner — OWNER membership on the active team, OR is_platform_admin == True. MEMBER requests land 403.
Range applies to coach productivity + activity mix; client-growth chart is fixed to a 90-day horizon (longer windows read better as a curve).
Source-of-truth doc: project_context/product/COACH_DASHBOARD_PLAN.md §7 / §9.1.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Custom-range start (ISO YYYY-MM-DD, inclusive). Takes precedence over range.
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/business/.
object
ISO date of the window’s first day (inclusive).
ISO date of the window’s last day (inclusive).
object
Sum of positive ledger entries (plan_grant:*, manual top-ups). Lifetime, not period-bound.
Absolute value of negative ledger entries — sessions consumed.
granted - debited. Same number Me.session_quota reports.
Active plan display name (e.g. Pro). Null when the team has no Subscription row yet (free tier).
Subscription.current_period_end — when the next quota grant is expected. Null on free tier.
Floor of (period_end - now) in days. Null on free tier; clamped to 0 if past_due.
True when the user clicked Cancel — quota stops refilling at period_end.
object
active / past_due / canceled / canceling (active + cancel_at_period_end) / trialing / incomplete / unpaid / free.
Tone the frontend renders the card with. Server-side mapping keeps presentation drift to one place.
recovery- recoveryform- formrecovery-low- recovery-lowsleep- sleep
object
owner or member. Sub-admin role is NEEDS-DECISION in ROADMAP §4.6 — when reintroduced, this widens.
Sessions the admin uploaded in the requested window.
Distinct clients the admin uploaded for in the window.
Cumulative count of completed sessions the admin uploaded that lack a coach_review row. Not range-bound.
Latest Session.created_at for any session the admin uploaded, all-time. Null when they’ve never uploaded.
object
ISO date YYYY-MM-DD.
Clients created on this calendar day (UTC).
Total team-client count as of end-of-day, including all pre-window clients.
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
0..1 share of total sessions in the window. Sums (with rounding) to 1 across the response.
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
{ "payment_health": { "tone": "recovery" }, "activity_mix": [ { "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).
Examples
403 — Owner-only (business overview)
{ "detail": "You do not have permission to perform this action."}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."}