{"openapi":"3.1.0","info":{"title":"Endure API","version":"1.0.0","description":"REST API for endurance athlete training data. Readiness scores, activities, performance metrics, training plans, and workouts.","license":{"name":"Proprietary"},"contact":{"name":"Endure Labs","url":"https://endurelabs.app"}},"servers":[{"url":"https://endurelabs.app/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Status","description":"Health check endpoints"},{"name":"Athlete","description":"Athlete profile and settings"},{"name":"Activities","description":"Training activities and streams"},{"name":"Readiness","description":"Daily readiness scores and recommendations"},{"name":"PMC","description":"Performance Management Chart (CTL/ATL/TSB)"},{"name":"Zones","description":"Training zone configuration"},{"name":"Plans","description":"Training plans"},{"name":"Workouts","description":"Workout library"},{"name":"Integrations","description":"Connected services"},{"name":"Export","description":"Data export"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication. Keys are prefixed with `endure_live_`. Pass via Authorization header: `Bearer endure_live_...`"}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed in the current window","schema":{"type":"integer","example":100}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window","schema":{"type":"integer","example":97}},"X-RateLimit-Reset":{"description":"Unix timestamp in milliseconds when the rate limit window resets","schema":{"type":"integer","format":"int64","example":1709251200000}},"Retry-After":{"description":"Seconds until the rate limit resets (only on 429 responses)","schema":{"type":"integer","example":30}}},"schemas":{"ApiMeta":{"type":"object","required":["request_id","timestamp"],"properties":{"request_id":{"type":"string","format":"uuid","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"timestamp":{"type":"string","format":"date-time","example":"2026-03-11T12:00:00.000Z"}}},"ApiPagination":{"type":"object","required":["has_more","cursor","limit"],"properties":{"has_more":{"type":"boolean","example":true},"cursor":{"type":["string","null"],"example":"eyJkYXRlIjoiMjAyNi0wMy0wMSIsImlkIjoiYWJjMTIzIn0="},"limit":{"type":"integer","example":50}}},"ApiErrorDetail":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string","example":"ftp"},"message":{"type":"string","example":"Must be between 50 and 600"}}},"ApiError":{"type":"object","required":["error","meta"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["UNAUTHORIZED","FORBIDDEN","NOT_FOUND","VALIDATION_ERROR","RATE_LIMITED","SCOPE_INSUFFICIENT","INTERNAL_ERROR"],"example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Invalid request body"},"details":{"type":"array","items":{"$ref":"#/components/schemas/ApiErrorDetail"}}}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}},"StatusResponse":{"type":"object","required":["status","version","database"],"properties":{"status":{"type":"string","enum":["operational","degraded"],"example":"operational"},"version":{"type":"string","example":"1.0.0"},"database":{"type":"string","enum":["healthy","unhealthy"],"example":"healthy"}}},"PublicAthlete":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid","example":"f47ac10b-58cc-4372-a567-0e02b2c3d479"},"name":{"type":["string","null"],"example":"Jane Doe"},"ftp":{"type":["integer","null"],"example":250},"lthr":{"type":["integer","null"],"example":165},"max_hr":{"type":["integer","null"],"example":190},"resting_hr":{"type":["integer","null"],"example":48},"weight_kg":{"type":["number","null"],"example":72.5},"height_cm":{"type":["number","null"],"example":178},"primary_sport":{"type":["string","null"],"example":"cycling"},"primary_goal":{"type":["string","null"],"example":"Build endurance for a century ride"},"zone_model":{"type":["string","null"],"example":"coggan"},"weekly_hours_available":{"type":["number","null"],"example":12},"timezone":{"type":["string","null"],"example":"America/New_York"},"created_at":{"type":["string","null"],"format":"date-time","example":"2025-06-01T10:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-03-10T15:30:00.000Z"}}},"UpdateAthleteRequest":{"type":"object","minProperties":1,"properties":{"ftp":{"type":"integer","minimum":50,"maximum":600,"example":260},"lthr":{"type":"integer","minimum":80,"maximum":220,"example":168},"max_hr":{"type":"integer","minimum":100,"maximum":250,"example":192},"resting_hr":{"type":"integer","minimum":25,"maximum":120,"example":46},"weight_kg":{"type":"number","minimum":30,"maximum":200,"example":71},"primary_goal":{"type":"string","maxLength":200,"example":"Complete an Ironman 70.3"},"zone_model":{"type":"string","maxLength":50,"example":"coggan"},"weekly_hours_available":{"type":"number","minimum":1,"maximum":40,"example":14}}},"PublicActivitySummary":{"type":"object","required":["id","date","source"],"properties":{"id":{"type":"string","format":"uuid","example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab"},"date":{"type":"string","format":"date","example":"2026-03-10"},"name":{"type":["string","null"],"example":"Morning Ride"},"type":{"type":["string","null"],"example":"ride"},"sport_type":{"type":["string","null"],"example":"cycling"},"source":{"type":"string","example":"strava"},"duration_seconds":{"type":["integer","null"],"example":5400},"distance_meters":{"type":["number","null"],"example":48200.5},"tss":{"type":["number","null"],"example":85.3},"avg_power":{"type":["number","null"],"example":195},"normalized_power":{"type":["number","null"],"example":210},"max_power":{"type":["number","null"],"example":620},"intensity_factor":{"type":["number","null"],"example":0.84},"avg_hr":{"type":["integer","null"],"example":145},"max_hr":{"type":["integer","null"],"example":172},"avg_cadence":{"type":["number","null"],"example":88},"total_elevation_gain_m":{"type":["number","null"],"example":850},"rpe":{"type":["number","null"],"example":6.5},"feeling":{"type":["string","null"],"example":"strong"},"was_planned":{"type":["boolean","null"],"example":true},"compliance_pct":{"type":["number","null"],"example":92},"compliance_grade":{"type":["string","null"],"example":"A"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-03-10T14:00:00.000Z"}}},"PublicActivityDetail":{"allOf":[{"$ref":"#/components/schemas/PublicActivitySummary"},{"type":"object","properties":{"start_time":{"type":["string","null"],"format":"date-time","example":"2026-03-10T07:30:00.000Z"},"start_lat":{"type":["number","null"],"example":39.9612},"start_lng":{"type":["number","null"],"example":-82.9988},"end_lat":{"type":["number","null"],"example":39.9701},"end_lng":{"type":["number","null"],"example":-82.9875},"polyline":{"type":["string","null"],"example":"a~l~Fjk~uOwHfE"},"planned_tss":{"type":["number","null"],"example":80},"planned_steps":{"type":["string","null"],"example":"Warm up 15 min, 3x10 at tempo, cool down"},"workout_intent":{"type":["string","null"],"example":"tempo"},"compliance_detail":{"type":["string","null"],"example":"Hit all intervals within target power"},"zone_snapshot":{"type":["string","null"],"example":"{\"z1\":120,\"z2\":155,\"z3\":175}"},"zone1_time":{"type":["number","null"],"example":1200},"zone2_time":{"type":["number","null"],"example":1800},"zone3_time":{"type":["number","null"],"example":900},"zone4_time":{"type":["number","null"],"example":600},"zone5_time":{"type":["number","null"],"example":300},"zone6_time":{"type":["number","null"],"example":60},"power_1s":{"type":["number","null"],"example":850},"power_5s":{"type":["number","null"],"example":720},"power_1m":{"type":["number","null"],"example":420},"power_5m":{"type":["number","null"],"example":310},"power_20m":{"type":["number","null"],"example":255},"power_60m":{"type":["number","null"],"example":230}}}]},"CreateActivityRequest":{"type":"object","required":["date","name","type"],"properties":{"date":{"type":"string","format":"date","example":"2026-03-11"},"name":{"type":"string","minLength":1,"maxLength":200,"example":"Lunch Run"},"type":{"type":"string","minLength":1,"maxLength":50,"example":"run"},"duration_seconds":{"type":"integer","minimum":0,"example":3600},"distance_meters":{"type":"number","minimum":0,"example":10000},"tss":{"type":"number","minimum":0,"example":65},"avg_power":{"type":"number","minimum":0,"example":180},"avg_hr":{"type":"integer","minimum":0,"example":148},"rpe":{"type":"number","minimum":1,"maximum":10,"example":7},"feeling":{"type":"string","maxLength":50,"example":"good"}}},"UpdateActivityRequest":{"type":"object","minProperties":1,"properties":{"rpe":{"type":"number","minimum":1,"maximum":10,"example":7.5},"feeling":{"type":"string","maxLength":50,"example":"tired"},"notes":{"type":"string","maxLength":2000,"example":"Legs felt heavy after yesterday's intervals"}}},"ActivityStreams":{"type":"object","required":["activity_id","channels"],"properties":{"activity_id":{"type":"string","format":"uuid","example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab"},"sample_rate_hz":{"type":["number","null"],"example":1},"total_samples":{"type":["integer","null"],"example":5400},"stream_duration_seconds":{"type":["number","null"],"example":5400},"channels":{"type":"object","properties":{"power":{"type":"array","items":{"type":"number"},"example":[180,195,210,205,198]},"hr":{"type":"array","items":{"type":"number"},"example":[130,135,142,148,145]},"cadence":{"type":"array","items":{"type":"number"},"example":[85,88,90,87,86]},"speed":{"type":"array","items":{"type":"number"},"example":[8.5,9,9.2,8.8,8.6]},"altitude":{"type":"array","items":{"type":"number"},"example":[250,252,255,258,260]},"pace":{"type":"array","items":{"type":"number"},"example":[300,295,290,298,302]}}}}},"PublicReadiness":{"type":"object","required":["date"],"properties":{"date":{"type":"string","format":"date","example":"2026-03-11"},"readiness_score":{"type":["number","null"],"example":78.5},"recommendation":{"type":["string","null"],"enum":["go","caution","rest",null],"example":"go"},"recovery_score":{"type":["number","null"],"example":82},"sleep_hours":{"type":["number","null"],"example":7.5},"sleep_quality":{"type":["number","null"],"example":85},"hrv":{"type":["number","null"],"example":55},"resting_hr":{"type":["number","null"],"example":48},"mood_score":{"type":["number","null"],"example":8},"motivation_level":{"type":["number","null"],"example":7},"gates":{"type":["object","null"],"properties":{"sleep":{"type":["boolean","null"],"example":true},"energy":{"type":["boolean","null"],"example":true},"stress":{"type":["boolean","null"],"example":false},"musculoskeletal":{"type":["boolean","null"],"example":true},"nutrition":{"type":["boolean","null"],"example":true},"autonomic":{"type":["boolean","null"],"example":true},"mental_health":{"type":["boolean","null"],"example":true}}},"ctl":{"type":["number","null"],"example":65},"atl":{"type":["number","null"],"example":72},"tsb":{"type":["number","null"],"example":-7},"is_yesterday_fallback":{"type":"boolean","example":false}}},"PublicPmcPoint":{"type":"object","required":["date"],"properties":{"date":{"type":"string","format":"date","example":"2026-03-10"},"ctl":{"type":["number","null"],"example":65},"atl":{"type":["number","null"],"example":72},"tsb":{"type":["number","null"],"example":-7}}},"PublicZone":{"type":"object","required":["zone","name","min","max"],"properties":{"zone":{"type":"integer","example":3},"name":{"type":"string","example":"Tempo"},"min":{"type":"number","example":210},"max":{"type":"number","example":250}}},"PublicZoneConfig":{"type":"object","required":["power_zones","hr_zones"],"properties":{"zone_model":{"type":["string","null"],"example":"coggan"},"ftp":{"type":["integer","null"],"example":250},"lthr":{"type":["integer","null"],"example":165},"max_hr":{"type":["integer","null"],"example":190},"power_zones":{"type":"array","items":{"$ref":"#/components/schemas/PublicZone"},"example":[{"zone":1,"name":"Active Recovery","min":0,"max":137},{"zone":2,"name":"Endurance","min":138,"max":187},{"zone":3,"name":"Tempo","min":188,"max":225},{"zone":4,"name":"Threshold","min":226,"max":262},{"zone":5,"name":"VO2max","min":263,"max":300},{"zone":6,"name":"Anaerobic","min":301,"max":9999}]},"hr_zones":{"type":"array","items":{"$ref":"#/components/schemas/PublicZone"},"example":[{"zone":1,"name":"Recovery","min":0,"max":120},{"zone":2,"name":"Aerobic","min":121,"max":145},{"zone":3,"name":"Tempo","min":146,"max":158},{"zone":4,"name":"Threshold","min":159,"max":170},{"zone":5,"name":"VO2max","min":171,"max":190}]}}},"PublicPlanSummary":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid","example":"d4e5f6a1-b2c3-7890-def0-1234567890cd"},"name":{"type":["string","null"],"example":"Spring Century Build"},"methodology":{"type":["string","null"],"example":"polarized"},"start_date":{"type":["string","null"],"format":"date","example":"2026-01-15"},"end_date":{"type":["string","null"],"format":"date","example":"2026-06-01"},"status":{"type":["string","null"],"example":"active"},"weekly_hours_target":{"type":["number","null"],"example":12},"experience_level":{"type":["string","null"],"example":"intermediate"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-01-10T08:00:00.000Z"}}},"PublicPlanDetail":{"allOf":[{"$ref":"#/components/schemas/PublicPlanSummary"},{"type":"object","properties":{"primary_limiter":{"type":["string","null"],"example":"endurance"},"adaptation_enabled":{"type":["boolean","null"],"example":true}}}]},"PublicWorkoutSummary":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid","example":"e5f6a1b2-c3d4-7890-ef01-234567890def"},"name":{"type":["string","null"],"example":"THR 2x20 Steady"},"sport_type":{"type":["string","null"],"example":"cycling"},"workout_type":{"type":["string","null"],"example":"threshold"},"description":{"type":["string","null"],"example":"Two 20-minute threshold intervals with 5 min recovery"},"estimated_duration_minutes":{"type":["number","null"],"example":60},"estimated_tss":{"type":["number","null"],"example":75},"tags":{"type":["array","null"],"items":{"type":"string"},"example":["threshold","indoor","structured"]},"is_favorite":{"type":["boolean","null"],"example":false},"usage_count":{"type":["integer","null"],"example":12},"created_at":{"type":["string","null"],"format":"date-time","example":"2025-08-15T10:00:00.000Z"}}},"PublicWorkoutDetail":{"allOf":[{"$ref":"#/components/schemas/PublicWorkoutSummary"},{"type":"object","properties":{"blocks":{"type":["array","null"],"items":{"type":"object"},"example":[{"type":"warmup","duration_seconds":600,"target_power_pct":55},{"type":"interval","duration_seconds":1200,"target_power_pct":95,"repeats":2,"rest_seconds":300},{"type":"cooldown","duration_seconds":600,"target_power_pct":50}]},"equipment_needed":{"type":["array","null"],"items":{"type":"string"},"example":["smart trainer","power meter"]},"estimated_if":{"type":["number","null"],"example":0.88},"target_muscles":{"type":["array","null"],"items":{"type":"string"},"example":["quadriceps","glutes"]}}}]},"PublicIntegration":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid","example":"f6a1b2c3-d4e5-7890-0123-456789abcdef"},"provider":{"type":["string","null"],"example":"strava"},"last_sync_at":{"type":["string","null"],"format":"date-time","example":"2026-03-11T06:00:00.000Z"},"needs_reauth":{"type":["boolean","null"],"example":false},"sync_error":{"type":["string","null"],"example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2025-05-20T12:00:00.000Z"}}},"PublicExportJob":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid","example":"a1b2c3d4-5678-90ab-cdef-1234567890ab"},"status":{"type":["string","null"],"enum":["pending","processing","completed","failed",null],"example":"pending"},"download_url":{"type":["string","null"],"format":"uri","example":null},"expires_at":{"type":["string","null"],"format":"date-time","example":null},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-03-11T12:00:00.000Z"},"error_message":{"type":["string","null"],"example":null}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"error":{"code":"UNAUTHORIZED","message":"Missing or invalid API key"},"meta":{"request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","timestamp":"2026-03-11T12:00:00.000Z"}}}}},"Forbidden":{"description":"Insufficient permissions or scope","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"error":{"code":"SCOPE_INSUFFICIENT","message":"API key does not have the required scope"},"meta":{"request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","timestamp":"2026-03-11T12:00:00.000Z"}}}}},"NotFound":{"description":"Resource not found","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"error":{"code":"NOT_FOUND","message":"Resource not found"},"meta":{"request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","timestamp":"2026-03-11T12:00:00.000Z"}}}}},"ValidationError":{"description":"Invalid request parameters or body","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Invalid request body","details":[{"field":"ftp","message":"Must be between 50 and 600"}]},"meta":{"request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","timestamp":"2026-03-11T12:00:00.000Z"}}}}},"RateLimited":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded. Retry after 30 seconds."},"meta":{"request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","timestamp":"2026-03-11T12:00:00.000Z"}}}}},"InternalError":{"description":"Internal server error","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred"},"meta":{"request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","timestamp":"2026-03-11T12:00:00.000Z"}}}}}},"parameters":{"ActivityId":{"name":"id","in":"path","required":true,"description":"Activity UUID","schema":{"type":"string","format":"uuid"}},"PlanId":{"name":"id","in":"path","required":true,"description":"Plan UUID","schema":{"type":"string","format":"uuid"}},"WorkoutId":{"name":"id","in":"path","required":true,"description":"Workout UUID","schema":{"type":"string","format":"uuid"}},"ExportId":{"name":"id","in":"path","required":true,"description":"Export job UUID","schema":{"type":"string","format":"uuid"}},"StartDate":{"name":"start","in":"query","required":true,"description":"Start date (inclusive, YYYY-MM-DD)","schema":{"type":"string","format":"date","example":"2026-01-01"}},"EndDate":{"name":"end","in":"query","required":true,"description":"End date (inclusive, YYYY-MM-DD)","schema":{"type":"string","format":"date","example":"2026-03-11"}}}},"paths":{"/status":{"get":{"operationId":"getStatus","summary":"Health check","description":"Returns API status, version, and database health. No authentication required.","tags":["Status"],"security":[],"responses":{"200":{"description":"API status","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/StatusResponse"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/athlete":{"get":{"operationId":"getAthlete","summary":"Get athlete profile","description":"Returns the authenticated athlete's profile. Requires `athlete:read` scope.","tags":["Athlete"],"responses":{"200":{"description":"Athlete profile","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicAthlete"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"updateAthlete","summary":"Update athlete profile","description":"Updates the authenticated athlete's profile fields. Requires `athlete:write` scope. At least one field must be provided.","tags":["Athlete"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAthleteRequest"}}}},"responses":{"200":{"description":"Updated athlete profile","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicAthlete"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/activities":{"get":{"operationId":"listActivities","summary":"List activities","description":"Returns a paginated list of activities within a date range. Maximum range is 90 days. Requires `activities:read` scope.","tags":["Activities"],"parameters":[{"$ref":"#/components/parameters/StartDate"},{"$ref":"#/components/parameters/EndDate"},{"name":"type","in":"query","required":false,"description":"Filter by activity type","schema":{"type":"string","example":"ride"}},{"name":"limit","in":"query","required":false,"description":"Number of results per page (1-200, default 50)","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Pagination cursor from a previous response","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of activities","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicActivitySummary"}},"meta":{"$ref":"#/components/schemas/ApiMeta"},"pagination":{"$ref":"#/components/schemas/ApiPagination"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createActivity","summary":"Create an activity","description":"Creates a new activity record. Requires `activities:write` scope.","tags":["Activities"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateActivityRequest"}}}},"responses":{"201":{"description":"Created activity","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicActivitySummary"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/activities/{id}":{"get":{"operationId":"getActivity","summary":"Get activity detail","description":"Returns full detail for a single activity including power peaks and zone times. Requires `activities:read` scope.","tags":["Activities"],"parameters":[{"$ref":"#/components/parameters/ActivityId"}],"responses":{"200":{"description":"Activity detail","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicActivityDetail"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"updateActivity","summary":"Update activity metadata","description":"Updates RPE, feeling, or notes on an activity. Requires `activities:write` scope. At least one field must be provided.","tags":["Activities"],"parameters":[{"$ref":"#/components/parameters/ActivityId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateActivityRequest"}}}},"responses":{"200":{"description":"Updated activity detail","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicActivityDetail"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/activities/{id}/streams":{"get":{"operationId":"getActivityStreams","summary":"Get activity data streams","description":"Returns time-series data streams (power, heart rate, cadence, etc.) for an activity. Requires `activities:read` scope.","tags":["Activities"],"parameters":[{"$ref":"#/components/parameters/ActivityId"},{"name":"channels","in":"query","required":false,"description":"Comma-separated list of channels to return. If omitted, all available channels are returned.","schema":{"type":"string","example":"power,hr,cadence"},"explode":false}],"responses":{"200":{"description":"Activity data streams","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/ActivityStreams"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/readiness/current":{"get":{"operationId":"getCurrentReadiness","summary":"Get current readiness","description":"Returns today's readiness score and recommendation. Falls back to yesterday if today's data is not yet available. Requires `readiness:read` scope.","tags":["Readiness"],"responses":{"200":{"description":"Current readiness data","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicReadiness"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/readiness/history":{"get":{"operationId":"getReadinessHistory","summary":"Get readiness history","description":"Returns daily readiness scores for a date range. Maximum range is 90 days. Requires `readiness:read` scope.","tags":["Readiness"],"parameters":[{"$ref":"#/components/parameters/StartDate"},{"$ref":"#/components/parameters/EndDate"}],"responses":{"200":{"description":"Readiness history","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicReadiness"}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/pmc":{"get":{"operationId":"getPmc","summary":"Get PMC data","description":"Returns Performance Management Chart data (CTL, ATL, TSB) for a date range. Maximum range is 365 days. Requires `pmc:read` scope.","tags":["PMC"],"parameters":[{"$ref":"#/components/parameters/StartDate"},{"$ref":"#/components/parameters/EndDate"}],"responses":{"200":{"description":"PMC data points","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicPmcPoint"}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/zones":{"get":{"operationId":"getZones","summary":"Get training zones","description":"Returns the athlete's current training zone configuration for power and heart rate. Requires `zones:read` scope.","tags":["Zones"],"responses":{"200":{"description":"Zone configuration","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicZoneConfig"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/plans":{"get":{"operationId":"listPlans","summary":"List training plans","description":"Returns all training plans for the authenticated athlete. Requires `plans:read` scope.","tags":["Plans"],"responses":{"200":{"description":"List of training plans","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicPlanSummary"}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/plans/{id}":{"get":{"operationId":"getPlan","summary":"Get plan detail","description":"Returns full detail for a single training plan. Requires `plans:read` scope.","tags":["Plans"],"parameters":[{"$ref":"#/components/parameters/PlanId"}],"responses":{"200":{"description":"Plan detail","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicPlanDetail"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/workouts":{"get":{"operationId":"listWorkouts","summary":"List workouts","description":"Returns all workouts in the athlete's library. Requires `workouts:read` scope.","tags":["Workouts"],"responses":{"200":{"description":"List of workouts","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicWorkoutSummary"}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/workouts/{id}":{"get":{"operationId":"getWorkout","summary":"Get workout detail","description":"Returns full detail for a single workout including structured blocks. Requires `workouts:read` scope.","tags":["Workouts"],"parameters":[{"$ref":"#/components/parameters/WorkoutId"}],"responses":{"200":{"description":"Workout detail","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicWorkoutDetail"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations":{"get":{"operationId":"listIntegrations","summary":"List integrations","description":"Returns all connected integrations for the authenticated athlete. Requires `integrations:read` scope.","tags":["Integrations"],"responses":{"200":{"description":"List of integrations","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicIntegration"}},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/export":{"post":{"operationId":"createExport","summary":"Request data export","description":"Initiates an export of the athlete's data. Returns a job that can be polled for completion. Requires `export:write` scope.","tags":["Export"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Empty object. No parameters required."},"example":{}}}},"responses":{"201":{"description":"Export job created","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicExportJob"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/export/{id}":{"get":{"operationId":"getExport","summary":"Get export job status","description":"Returns the current status of an export job. Poll until status is `completed` or `failed`. Requires `export:write` scope.","tags":["Export"],"parameters":[{"$ref":"#/components/parameters/ExportId"}],"responses":{"200":{"description":"Export job status","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/PublicExportJob"},"meta":{"$ref":"#/components/schemas/ApiMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}