Skip to content

Business overview (owner-only)

GET
/api/dashboard/business/
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 IsTeamOwnerOWNER 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.

from
string format: date

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

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/business/.

object
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
generated_at
required
string format: date-time
quota
required
object
granted
required

Sum of positive ledger entries (plan_grant:*, manual top-ups). Lifetime, not period-bound.

integer
debited
required

Absolute value of negative ledger entries — sessions consumed.

integer
remaining
required

granted - debited. Same number Me.session_quota reports.

integer
plan_name
required

Active plan display name (e.g. Pro). Null when the team has no Subscription row yet (free tier).

string
nullable
period_end
required

Subscription.current_period_end — when the next quota grant is expected. Null on free tier.

string format: date-time
nullable
days_to_renew
required

Floor of (period_end - now) in days. Null on free tier; clamped to 0 if past_due.

integer
nullable
cancel_at_period_end
required

True when the user clicked Cancel — quota stops refilling at period_end.

boolean
payment_health
required
object
status
required

active / past_due / canceled / canceling (active + cancel_at_period_end) / trialing / incomplete / unpaid / free.

string
plan_name
required
string
nullable
period_end
required
string format: date-time
nullable
cancel_at_period_end
required
boolean
tone
required

Tone the frontend renders the card with. Server-side mapping keeps presentation drift to one place.

  • recovery - recovery
  • form - form
  • recovery-low - recovery-low
  • sleep - sleep
string
Allowed values: recovery form recovery-low sleep
coach_productivity
required
Array<object>
object
admin_id
required
string format: uuid
email
required
string
display_name
required
string
role
required

owner or member. Sub-admin role is NEEDS-DECISION in ROADMAP §4.6 — when reintroduced, this widens.

string
sessions_in_range
required

Sessions the admin uploaded in the requested window.

integer
unique_clients
required

Distinct clients the admin uploaded for in the window.

integer
pending_reviews
required

Cumulative count of completed sessions the admin uploaded that lack a coach_review row. Not range-bound.

integer
last_active
required

Latest Session.created_at for any session the admin uploaded, all-time. Null when they’ve never uploaded.

string format: date-time
nullable
client_growth
required
Array<object>
object
bucket
required

ISO date YYYY-MM-DD.

string format: date
new_clients
required

Clients created on this calendar day (UTC).

integer
cumulative
required

Total team-client count as of end-of-day, including all pre-window clients.

integer
activity_mix
required
Array<object>
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
count
required
integer
fraction
required

0..1 share of total sessions in the window. Sums (with rounding) to 1 across the response.

number format: double
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
{
"payment_health": {
"tone": "recovery"
},
"activity_mix": [
{
"activity": "running"
}
],
"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
Examples
Example403—Owner-only(businessOverview)

403 — Owner-only (business overview)

{
"detail": "You do not have permission to perform this action."
}
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
Example404—NoActiveTeam

404 — No active team

{
"detail": "No active team — finish onboarding first."
}