Re coaching availability metadata and roster API request; all three asks answered by v2.1.0 contract, roster endpoint live
All three questions answered below. The answers are encoded in contracts/coach-availability/README.v2.md v2.1.0 (published 2026-05-19); if Sales has not read that version yet, the answers here and the contract are aligned.
Display metadata shape
Coaching will not enrich the availability response with coach labels, market display names, or timezone. This is the deliberate boundary in §5 of the contract: "Coaching SHALL NOT expose canonical Person labels or market display labels on the roster or availability response." The reasons are the same as why the roster returns person_id rather than a name: Coaching does not own Person identity and should not be duplicating Platform-owned facts on every availability payload.
The correct consumer path is: call GET /coaching/v2/roster to get person_id and geography IDs for each coach, then hydrate display labels from Platform's Person facts API (for coach name) and Platform canonical geography (for market display name and timezone). This is a one-time hydration call per roster, not a per-availability-request lookup, so the cost is low.
A companion endpoint that duplicates Platform's Person labels is not the right shape: it would create a second source of truth for identity data Coaching does not own, and any drift between Coaching's copy and Platform's becomes Coaching's incident to debug. Sales should source those labels from Platform directly.
Roster read endpoint
GET /coaching/v2/roster is live and matches §4.4 of the v2.1.0 contract. Query parameters:
organization_id(required)coach_id(optional, scope to one coach)service_area_id(optional, scope to coaches whose home service area or coverage list includes this area)include_archived(optional boolean, default false)
Response per coach: coach_id, person_id, status, home_service_area_id, service_area_ids, market_id (nullable today), can_cross_service_areas, max_drive_minutes_from_home, max_inter_lesson_travel_minutes.
For the coach selector dropdown, the expected call is GET /coaching/v2/roster?organization_id=...&service_area_id=... without include_archived, which returns active and onboarding/hiring coaches but not archived ones. person_id is the key Sales passes to Platform for the display label. status is available if Sales wants to filter or visually distinguish inactive coaches in the dropdown.
market_id in the roster response is nullable in v2.1.0 for the same reason as on the availability response: Coaching has not yet hydrated the service-area-to-market mapping into the read model. Sales should use Platform canonical geography to map service areas to markets for any market-level grouping in the selector UI.
market_id filter status
market_id is reserved on both the availability and roster routes. Passing it currently returns HTTP 400 with error: market_filter_not_supported. service_area_id is the canonical live geography filter. Market-level filtering is a planned minor-version addition once Coaching hydrates the mapping; Coaching will announce on the coach-availability contract thread when it ships. Until then, Sales can filter by service area and derive market grouping from Platform canonical geography on the consumer side.
References
contracts/coach-availability/README.v2.md§4.1 (availability route, market_id reserved), §4.4 (roster endpoint shape and filtering), §5 (Coaching SHALL NOT expose canonical labels), §6 (consumer responsibility to read Platform for labels)coaching/app/api/v2/coaching/roster/route.ts(live implementation)