RTSport API โ v0.3
Frontend-driven contract from the AT dashboard mock.
These are the endpoints the frontend currently fetches or POSTs to.
Socrates: wire these. Auth, roles, and FERPA matrix in contract.md.
openapi: "3.0.3"
info:
title: RTSport API
version: "0.3"
description: |
Athletic training case management for high school sports.
Current frontend targets: AT dashboard, sideline entry, athlete detail overlay.
servers:
- url: https://api.hoffdesk.com/rtsport/v1
description: Production
- url: https://hoffdesk.com/api/v1
description: Current mock server path
paths:
# โโ Dashboard โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
/events/sideline-entry:
post:
summary: Submit a sideline injury/incident entry
description: Called by the 3-tap sideline entry flow after all 3 selections
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- school_id
- athlete_id
- body_part
- severity
properties:
school_id:
type: string
example: "schl_001"
athlete_id:
type: string
example: "ath_001"
body_part:
type: string
example: "Ankle"
severity:
type: string
enum: [mild, moderate, severe]
example: "moderate"
removed_from_play:
type: boolean
default: false
timestamp:
type: string
format: date-time
description: ISO-8601 timestamp of when the injury occurred
responses:
"200":
description: Entry created
content:
application/json:
schema:
type: object
properties:
case_id:
type: string
example: "cas_abc123"
athlete:
type: string
example: "Jake Larson"
body_part:
type: string
example: "Ankle"
severity:
type: string
example: "moderate"
athlete_status:
type: string
enum: [removed, evaluated]
"400":
description: Validation error โ missing required fields
# โโ Athlete Detail โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
/athletes/{athlete_id}:
get:
summary: Get athlete profile
parameters:
- name: athlete_id
in: path
required: true
schema:
type: string
responses:
"200":
description: Athlete profile
content:
application/json:
schema:
$ref: "#/components/schemas/Athlete"
/cases/{athlete_id}:
get:
summary: Get active case for an athlete (latest if multiple)
parameters:
- name: athlete_id
in: path
required: true
schema:
type: string
responses:
"200":
description: Full case data including milestones and timeline
content:
application/json:
schema:
$ref: "#/components/schemas/Case"
"404":
description: No active case found for this athlete
/athletes/{athlete_id}/case:
get:
summary: Combined endpoint โ returns athlete + active case in one call
description: |
Frontend currently makes TWO separate fetches (athletes.json + cases.json)
and joins on athlete_id. This endpoint wraps both into one response
for the athlete detail overlay.
parameters:
- name: athlete_id
in: path
required: true
schema:
type: string
responses:
"200":
description: Athlete and case data merged
content:
application/json:
schema:
type: object
properties:
athlete:
$ref: "#/components/schemas/Athlete"
case:
$ref: "#/components/schemas/Case"
# โโ Dashboard Data โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
/dashboard/at:
get:
summary: AT dashboard โ quick stats and active cases
responses:
"200":
content:
application/json:
schema:
type: object
properties:
stats:
type: object
properties:
full_count:
type: integer
example: 72
modified_count:
type: integer
example: 8
out_count:
type: integer
example: 3
active_cases:
type: array
items:
$ref: "#/components/schemas/CaseSummary"
recent_activity:
type: array
items:
$ref: "#/components/schemas/ActivityItem"
# โโ Sideline โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
/body-parts:
get:
summary: Body part categories and parts for the sideline entry picker
responses:
"200":
description: Body part hierarchy (categories โ parts)
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/BodyPartCategory"
components:
schemas:
Athlete:
type: object
required:
- id
- first_name
- last_name
- sport
- team
- grade
properties:
id:
type: string
example: "ath_001"
first_name:
type: string
example: "Jake"
last_name:
type: string
example: "Larson"
sport:
type: string
example: "Football"
team:
type: string
example: "Varsity"
grade:
type: integer
example: 11
initials:
type: string
example: "JL"
description: Computed from first/last name, could also be server-generated
active:
type: boolean
default: true
Case:
type: object
required:
- case_id
- athlete_id
- injury
- status
properties:
case_id:
type: string
example: "cas_001"
athlete_id:
type: string
example: "ath_001"
injury:
type: string
example: "Ankle Sprain (Grade 2)"
injury_date:
type: string
format: date
example: "2026-04-28"
body_part:
type: string
example: "Ankle"
side:
type: string
enum: [Left, Right, null]
nullable: true
example: "Right"
severity:
type: string
enum: [mild, moderate, severe]
attention:
type: string
enum: [stable, urgent, warning]
description: >-
stable = on track. warning = behind schedule, need check-in.
urgent = medical concern, review today.
status:
type: string
enum: [active, cleared, referred]
phase:
type: integer
example: 2
total_phases:
type: integer
example: 4
phase_label:
type: string
description: Human-readable current phase name
example: "Active Rehab"
projected_return:
type: string
format: date
nullable: true
example: "2026-05-12"
last_updated:
type: string
example: "2026-05-01 14:00"
last_updated_by:
type: string
example: "You"
notified:
type: array
items:
type: string
example: ["Coach Andrews", "Parent"]
milestones:
type: array
items:
$ref: "#/components/schemas/Milestone"
timeline:
type: array
items:
$ref: "#/components/schemas/TimelineEvent"
Milestone:
type: object
properties:
num:
type: integer
description: Phase number (1-based)
example: 2
label:
type: string
description: Phase name
example: "Active Rehab"
status:
type: string
enum: [done, current, pending]
completed:
type: string
format: date
nullable: true
note:
type: string
example: "Walking without limp. ROM 75%. Strength work initiated."
TimelineEvent:
type: object
properties:
date:
type: string
example: "Apr 28 ยท 3:15 PM"
description: Display-ready date string or ISO-8601 timestamp
title:
type: string
example: "Initial Assessment"
note:
type: string
example: "Grade 2 lateral ankle sprain. Swelling +2, unable to bear weight."
by:
type: string
example: "You"
type:
type: string
enum: [assessment, restriction, milestone, clearance, note]
description: Drives the colored dot in the timeline UI
CaseSummary:
type: object
properties:
athlete_id:
type: string
athlete_name:
type: string
initials:
type: string
sport:
type: string
injury:
type: string
injury_short:
type: string
example: "Ankle sprain (Grade 2)"
status:
type: string
enum: [active, cleared, referred]
status_label:
type: string
example: "Phase 2/4"
avatar_color:
type: string
description: CSS-compatible color string for avatar background
example: "teal"
ActivityItem:
type: object
properties:
type:
type: string
enum: [cleared, out, modified]
text:
type: string
example: "Marcus Johnson cleared for full practice"
time_ago:
type: string
example: "2h ago"
BodyPartCategory:
type: object
properties:
name:
type: string
example: "Lower Body"
parts:
type: array
items:
type: object
properties:
id:
type: string
example: "ankle"
label:
type: string
example: "Ankle"
icon:
type: string
example: "๐ฆถ"