{"openapi":"3.1.0","info":{"title":"STRUGGL — Hybrid Athlete Training & Physiology API","description":"Production REST API powering STRUGGL's hybrid-athlete coaching platform (Hyrox, running, strength) across conversational AI assistants, wearable/AI-glasses voice workflows, and Model Context Protocol (MCP) clients.\n\n### Two Capability Tiers\n1. **Personal Athlete API (`/v1/me/*`)** — Authenticated read/write access to an athlete's biometric profile, race goals, completed & scheduled training sessions, weekly 17-muscle MEV/MAV/MRV volume ledger, and voice/conversational workout logging & planning.\n2. **Deterministic Physiology Calculators (`/v1/public/*`)** — Stateless, zero-LLM-latency sports-science engines for Hyrox 8×1 km compromised run pacing (calibrated on 200k finisher splits), piecewise Wathan 1RM & SymmetricStrength benchmarking, barbell RPE plate loading, and Karvonen Zone 2 heart-rate zones.","termsOfService":"https://struggl.singandclap.com/terms","contact":{"name":"STRUGGL Engineering (Sing And Clap)","url":"https://struggl.singandclap.com/docs"},"version":"1.0.0"},"servers":[{"url":"https://struggl.singandclap.com","description":"STRUGGL Production API"}],"paths":{"/v1/me/profile":{"get":{"tags":["athlete"],"summary":"Get the authenticated athlete's biometric profile and race goals","description":"Returns athlete-facing physiological attributes (bodyweight, height, sex, primary modality, training phase, weekly time budget) and upcoming target events/races. Requires `read` scope.","operationId":"getAthleteProfile","responses":{"200":{"description":"Athlete profile and goals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileResponse","additionalProperties":true,"type":"object","title":"Response Getathleteprofile"}}}},"401":{"description":"Missing, invalid, or revoked Bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"402":{"description":"Active Coach plan or free 30-day Coach trial required for personal API/MCP sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Per-athlete fair-use rate limit exceeded (Coach: 60 reads/hr, 200/day; 30 writes/hr, 80/day)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"OAuth2AuthorizationCode":["read"]},{"AthleteBearer":[]}],"x-required-scope":"read"}},"/v1/me/sessions":{"get":{"tags":["athlete"],"summary":"List completed and planned training sessions","description":"Retrieves the athlete's completed and scheduled workouts over a rolling window (`days`, 1–90) or on a single calendar date (`date`, YYYY-MM-DD). Call this before prescribing or adjusting today's workout. Requires `read` scope.","operationId":"getAthleteSessions","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"description":"Lookback/lookahead window in days (ignored when `date` is set)","default":14,"title":"Days"},"description":"Lookback/lookahead window in days (ignored when `date` is set)"},{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"Filter to a single calendar date (YYYY-MM-DD)","examples":["2026-11-12"],"title":"Date"},"description":"Filter to a single calendar date (YYYY-MM-DD)"}],"responses":{"200":{"description":"Completed and planned sessions","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Getathletesessions","$ref":"#/components/schemas/SessionsResponse"}}}},"401":{"description":"Missing, invalid, or revoked Bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"402":{"description":"Active Coach plan or free 30-day Coach trial required for personal API/MCP sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Per-athlete fair-use rate limit exceeded (Coach: 60 reads/hr, 200/day; 30 writes/hr, 80/day)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2AuthorizationCode":["read"]},{"AthleteBearer":[]}],"x-required-scope":"read"}},"/v1/me/muscle-volume":{"get":{"tags":["athlete"],"summary":"Get current week's hard sets per muscle group vs MEV/MAV/MRV landmarks","description":"Computes the athlete's current ISO-week effective training volume across 17 muscle groups using fractional set accounting (1.0x prime mover, 0.5x synergist, RPE >= 6 gating) compared against evidence-based Minimum Effective, Maximum Adaptive, and Maximum Recoverable Volume landmarks. Requires `read` scope.","operationId":"getWeeklyMuscleVolume","responses":{"200":{"description":"Weekly muscle volume summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MuscleVolumeResponse","additionalProperties":true,"type":"object","title":"Response Getweeklymusclevolume"}}}},"401":{"description":"Missing, invalid, or revoked Bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"402":{"description":"Active Coach plan or free 30-day Coach trial required for personal API/MCP sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Per-athlete fair-use rate limit exceeded (Coach: 60 reads/hr, 200/day; 30 writes/hr, 80/day)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"OAuth2AuthorizationCode":["read"]},{"AthleteBearer":[]}],"x-required-scope":"read"}},"/v1/me/workouts/log":{"post":{"tags":["athlete"],"summary":"Log a completed strength or endurance exercise","description":"Records one completed exercise into the athlete's training ledger with duplicate-write protection and automatic weekly streak & muscle-volume accounting. Call once per exercise completed. Requires `write` scope.","operationId":"logCompletedWorkout","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutIn"}}},"required":true},"responses":{"200":{"description":"Workout logged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutSavedResponse","additionalProperties":true,"type":"object","title":"Response Logcompletedworkout"}}}},"401":{"description":"Missing, invalid, or revoked Bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"402":{"description":"Active Coach plan or free 30-day Coach trial required for personal API/MCP sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Per-athlete fair-use rate limit exceeded (Coach: 60 reads/hr, 200/day; 30 writes/hr, 80/day)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"Token lacks required `write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2AuthorizationCode":["read","write"]},{"AthleteBearer":[]}],"x-required-scope":"write"}},"/v1/me/workouts/plan":{"post":{"tags":["athlete"],"summary":"Schedule a planned exercise on the athlete's calendar","description":"Adds a planned strength or endurance exercise to the athlete's training calendar on `date` (YYYY-MM-DD) and audits it deterministically against the athlete's 30-day e1RM envelope, 48–72h axial recovery spacing, intra-day exercise hierarchy, and active pain constraints. Call once per exercise when scheduling upcoming work. Requires `write` scope.","operationId":"planScheduledWorkout","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutIn"}}},"required":true},"responses":{"200":{"description":"Planned workout saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutSavedResponse","additionalProperties":true,"type":"object","title":"Response Planscheduledworkout"}}}},"401":{"description":"Missing, invalid, or revoked Bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"402":{"description":"Active Coach plan or free 30-day Coach trial required for personal API/MCP sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Per-athlete fair-use rate limit exceeded (Coach: 60 reads/hr, 200/day; 30 writes/hr, 80/day)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"Token lacks required `write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2AuthorizationCode":["read","write"]},{"AthleteBearer":[]}],"x-required-scope":"write"}},"/v1/public/hyrox-pace":{"get":{"tags":["public"],"summary":"Hyrox run splits and race predictions from a 5 km time","operationId":"hyroxPace","parameters":[{"name":"five_k","in":"query","required":true,"schema":{"type":"string","description":"Recent 5 km time, MM:SS (e.g. 22:30)","examples":["22:30"],"title":"Five K"},"description":"Recent 5 km time, MM:SS (e.g. 22:30)"},{"name":"goal","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Target Hyrox finish time, H:MM:SS (optional)","examples":["1:15:00"],"title":"Goal"},"description":"Target Hyrox finish time, H:MM:SS (optional)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HyroxPaceResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[]}},"/v1/public/strength-benchmark":{"get":{"tags":["public"],"summary":"Estimated 1RM, strength score and tier from one set","operationId":"strengthBenchmark","parameters":[{"name":"lift","in":"query","required":true,"schema":{"enum":["back_squat","front_squat","deadlift","sumo_deadlift","bench_press","incline_bench_press","dip","overhead_press","pull_up","chin_up","barbell_row"],"type":"string","description":"Benchmark lift","title":"Lift"},"description":"Benchmark lift"},{"name":"weight_kg","in":"query","required":true,"schema":{"type":"number","maximum":500,"minimum":0,"description":"Load lifted (ADDED load for dips / pull-ups / chin-ups)","title":"Weight Kg"},"description":"Load lifted (ADDED load for dips / pull-ups / chin-ups)"},{"name":"reps","in":"query","required":true,"schema":{"type":"integer","maximum":20,"minimum":1,"description":"Reps completed (estimates beyond 10 are capped)","title":"Reps"},"description":"Reps completed (estimates beyond 10 are capped)"},{"name":"bodyweight_kg","in":"query","required":true,"schema":{"type":"number","maximum":200,"minimum":35,"title":"Bodyweight Kg"}},{"name":"sex","in":"query","required":true,"schema":{"enum":["male","female"],"type":"string","title":"Sex"}},{"name":"age","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":90,"minimum":13},{"type":"null"}],"title":"Age"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrengthBenchmarkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[]}},"/v1/public/volume-audit":{"post":{"tags":["public"],"summary":"Audit weekly Direct (1.0x) + Secondary (0.5x) volume across 17 muscles","operationId":"volumeAudit","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeAuditRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeAuditResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[]}},"/v1/public/hyrox-splits":{"post":{"tags":["public"],"summary":"Compute 8 compromised Hyrox 1km run splits from standalone 5K time (200k finisher dataset)","operationId":"hyroxSplits","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HyroxSplitsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HyroxSplitsResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[]}},"/v1/public/plates-zone2":{"post":{"tags":["public"],"summary":"Convert Reps x RPE to exact bar plates (core/prescribe.py) + Karvonen HR zones (core/endurance.py)","operationId":"platesAndZone2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatesZone2Request"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatesZone2Result"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[]}}},"components":{"schemas":{"ActivePainOut":{"properties":{"region":{"type":"string","title":"Region","examples":["elbow"]},"side":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Side","examples":["right"]},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind","examples":["tendinitis"]},"severity":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":0.0},{"type":"null"}],"title":"Severity","examples":[6]},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","examples":["active"]}},"type":"object","required":["region"],"title":"ActivePainOut"},"ApiErrorDetail":{"properties":{"error":{"type":"string","title":"Error","examples":["invalid_token"]},"needed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Needed","examples":["write"]},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["error"],"title":"ApiErrorDetail"},"ApiErrorResponse":{"properties":{"detail":{"$ref":"#/components/schemas/ApiErrorDetail"}},"type":"object","required":["detail"],"title":"ApiErrorResponse"},"AthleteGoalOut":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","examples":["HYROX Paris"]},"event_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Date","description":"ISO date YYYY-MM-DD","examples":["2027-04-25"]},"discipline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Discipline","examples":["hyrox_men_open"]},"target_time_s":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target Time S","description":"Target finish time in seconds","examples":[4320]}},"type":"object","title":"AthleteGoalOut"},"AthleteProfileFields":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","examples":["Taha"]},"sex":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sex","examples":["male"]},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gender"},"weight_kg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weight Kg","description":"Bodyweight in kilograms","examples":[65.0]},"height_cm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Height Cm","description":"Height in centimeters","examples":[175.0]},"date_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Birth","description":"ISO date YYYY-MM-DD","examples":["1996-05-14"]},"primary_modality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Modality","examples":["hyrox"]},"current_phase":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Phase","examples":["specific_prep"]},"weekly_time_budget":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weekly Time Budget","description":"Weekly training budget in hours","examples":[7.5]},"training_age_years":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Training Age Years","examples":[4.0]},"coaching_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coaching Tier","examples":["pro"]},"knows_rpe":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Knows Rpe"},"knows_zones":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Knows Zones"}},"type":"object","title":"AthleteProfileFields"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HyroxLapSplitRow":{"properties":{"lap":{"type":"integer","title":"Lap"},"preceding_station":{"type":"string","title":"Preceding Station"},"station_key":{"type":"string","title":"Station Key"},"fatigue_multiplier":{"type":"number","title":"Fatigue Multiplier"},"target_pace":{"type":"string","title":"Target Pace"},"target_pace_seconds":{"type":"integer","title":"Target Pace Seconds"},"delta_vs_5k_sec":{"type":"integer","title":"Delta Vs 5K Sec"},"delta_vs_5k_label":{"type":"string","title":"Delta Vs 5K Label"},"cumulative_run_time":{"type":"string","title":"Cumulative Run Time"},"station_variance_gap_min":{"type":"number","title":"Station Variance Gap Min"},"coaching_cue":{"type":"string","title":"Coaching Cue"}},"type":"object","required":["lap","preceding_station","station_key","fatigue_multiplier","target_pace","target_pace_seconds","delta_vs_5k_sec","delta_vs_5k_label","cumulative_run_time","station_variance_gap_min","coaching_cue"],"title":"HyroxLapSplitRow"},"HyroxPaceResult":{"properties":{"five_k_time":{"type":"string","title":"Five K Time"},"five_k_pace":{"type":"string","title":"Five K Pace"},"hyrox_runs":{"$ref":"#/components/schemas/RunTarget"},"race_predictions":{"items":{"$ref":"#/components/schemas/RacePrediction"},"type":"array","title":"Race Predictions"},"app_url":{"type":"string","title":"App Url","description":"Where the athlete can get a full plan"}},"type":"object","required":["five_k_time","five_k_pace","hyrox_runs","race_predictions","app_url"],"title":"HyroxPaceResult"},"HyroxSplitsRequest":{"properties":{"standalone_5k_time":{"type":"string","title":"Standalone 5K Time","description":"Standalone 5K time MM:SS (e.g. 21:30)","examples":["21:30"]},"goal_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Goal Time","description":"Optional target Hyrox finish time H:MM:SS","examples":["1:18:00"]},"cns_penalty_sec_per_km":{"type":"integer","maximum":35.0,"minimum":0.0,"title":"Cns Penalty Sec Per Km","description":"Additional CNS/sled fatigue penalty in s/km","default":0},"division":{"type":"string","enum":["open_men","open_women","pro_men","pro_women","doubles"],"title":"Division","default":"open_men"}},"type":"object","required":["standalone_5k_time"],"title":"HyroxSplitsRequest"},"HyroxSplitsResult":{"properties":{"standalone_5k_time":{"type":"string","title":"Standalone 5K Time"},"standalone_5k_pace":{"type":"string","title":"Standalone 5K Pace"},"standalone_5k_pace_seconds":{"type":"integer","title":"Standalone 5K Pace Seconds"},"decay_factor":{"type":"number","title":"Decay Factor"},"decay_pct":{"type":"number","title":"Decay Pct"},"compromised_target_pace":{"type":"string","title":"Compromised Target Pace"},"compromised_target_pace_seconds":{"type":"integer","title":"Compromised Target Pace Seconds"},"pace_band":{"type":"string","title":"Pace Band"},"total_running_time":{"type":"string","title":"Total Running Time"},"est_total_race_time":{"type":"string","title":"Est Total Race Time"},"lap1_trap_warning":{"type":"string","title":"Lap1 Trap Warning"},"lap1_blowup_cost_minutes":{"type":"number","title":"Lap1 Blowup Cost Minutes"},"strategy":{"type":"string","title":"Strategy"},"laps":{"items":{"$ref":"#/components/schemas/HyroxLapSplitRow"},"type":"array","title":"Laps"},"race_predictions":{"items":{"$ref":"#/components/schemas/RacePrediction"},"type":"array","title":"Race Predictions"},"app_url":{"type":"string","title":"App Url"}},"type":"object","required":["standalone_5k_time","standalone_5k_pace","standalone_5k_pace_seconds","decay_factor","decay_pct","compromised_target_pace","compromised_target_pace_seconds","pace_band","total_running_time","est_total_race_time","lap1_trap_warning","lap1_blowup_cost_minutes","strategy","laps","race_predictions","app_url"],"title":"HyroxSplitsResult"},"MuscleAuditRow":{"properties":{"muscle":{"type":"string","title":"Muscle"},"direct_sets":{"type":"integer","title":"Direct Sets"},"secondary_sets":{"type":"number","title":"Secondary Sets"},"hard_sets":{"type":"number","title":"Hard Sets"},"effective_sets":{"type":"number","title":"Effective Sets"},"frequency":{"type":"integer","title":"Frequency"},"mev":{"type":"integer","title":"Mev"},"opt_low":{"type":"integer","title":"Opt Low"},"opt_high":{"type":"integer","title":"Opt High"},"mrv":{"type":"integer","title":"Mrv"},"status":{"type":"string","title":"Status"},"junk_sets":{"type":"number","title":"Junk Sets"},"deficit_to_mev":{"type":"number","title":"Deficit To Mev"},"contributors":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Contributors"}},"type":"object","required":["muscle","direct_sets","secondary_sets","hard_sets","effective_sets","frequency","mev","opt_low","opt_high","mrv","status","junk_sets","deficit_to_mev","contributors"],"title":"MuscleAuditRow"},"MuscleVolumeResponse":{"properties":{"summary":{"type":"string","title":"Summary","description":"Formatted weekly tension audit across 17 muscle groups with fractional direct (1.0x) and synergist (0.5x) hard-set totals mapped against MEV/MAV/MRV landmarks.","examples":["Week 2026-11-09 — Quads: 10.0 sets (MAV 10–16) · Hamstrings: 6.5 sets (MEV 6–10) · Back: 12.0 sets (MAV 10–18)"]}},"type":"object","required":["summary"],"title":"MuscleVolumeResponse"},"NextTier":{"properties":{"tier":{"type":"string","title":"Tier"},"e1rm_needed_kg":{"type":"number","title":"E1Rm Needed Kg","description":"e1RM that reaches it (added load for dips / pull-ups / chin-ups)"},"kg_to_go":{"type":"number","title":"Kg To Go"}},"type":"object","required":["tier","e1rm_needed_kg","kg_to_go"],"title":"NextTier"},"PlatesZone2Request":{"properties":{"lift":{"type":"string","title":"Lift","description":"Lift key: bench_press, back_squat, deadlift, overhead_press, pull_up, dip","default":"bench_press"},"bodyweight_kg":{"type":"number","exclusiveMaximum":220.0,"exclusiveMinimum":35.0,"title":"Bodyweight Kg","default":78.0},"sex":{"type":"string","enum":["male","female"],"title":"Sex","default":"male"},"ref_weight_kg":{"type":"number","maximum":500.0,"minimum":0.0,"title":"Ref Weight Kg","description":"Reference set weight (added weight for pull_up/dip)","default":100.0},"ref_reps":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Ref Reps","description":"Reference set reps","default":5},"ref_rpe":{"type":"number","maximum":10.0,"minimum":5.0,"title":"Ref Rpe","description":"Reference set RPE","default":8.5},"target_reps":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Target Reps","description":"Target set reps","default":8},"target_rpe":{"type":"number","maximum":10.0,"minimum":5.0,"title":"Target Rpe","description":"Target set RPE","default":8.0},"bar_weight_kg":{"type":"number","maximum":25.0,"minimum":10.0,"title":"Bar Weight Kg","description":"Barbell weight in kg (20kg or 15kg)","default":20.0},"age":{"type":"integer","maximum":90.0,"minimum":14.0,"title":"Age","description":"Athlete age in years","default":30},"rest_hr":{"type":"integer","maximum":110.0,"minimum":32.0,"title":"Rest Hr","description":"Resting heart rate in bpm","default":52},"max_hr":{"anyOf":[{"type":"integer","maximum":230.0,"minimum":130.0},{"type":"null"}],"title":"Max Hr","description":"Optional measured Max HR (defaults to Tanaka 208 - 0.7*age)"}},"type":"object","title":"PlatesZone2Request"},"PlatesZone2Result":{"properties":{"lift":{"type":"string","title":"Lift"},"is_bodyweight_lift":{"type":"boolean","title":"Is Bodyweight Lift"},"e1rm_total_kg":{"type":"number","title":"E1Rm Total Kg"},"e1rm_added_kg":{"type":"number","title":"E1Rm Added Kg"},"target_reps":{"type":"integer","title":"Target Reps"},"target_rpe":{"type":"number","title":"Target Rpe"},"target_rir":{"type":"number","title":"Target Rir"},"prescribed_total_kg":{"type":"number","title":"Prescribed Total Kg"},"prescribed_added_kg":{"type":"number","title":"Prescribed Added Kg"},"pct_of_e1rm":{"type":"number","title":"Pct Of E1Rm"},"max_reps_at_target_load":{"type":"integer","title":"Max Reps At Target Load"},"plate_breakdown":{"additionalProperties":true,"type":"object","title":"Plate Breakdown"},"rpe_matrix":{"items":{"$ref":"#/components/schemas/RpeMatrixCell"},"type":"array","title":"Rpe Matrix"},"measured_or_tanaka_max_hr":{"type":"integer","title":"Measured Or Tanaka Max Hr"},"rest_hr":{"type":"integer","title":"Rest Hr"},"heart_rate_reserve":{"type":"integer","title":"Heart Rate Reserve"},"karvonen_zones":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Karvonen Zones"},"karvonen_z2_min":{"type":"integer","title":"Karvonen Z2 Min"},"karvonen_z2_max":{"type":"integer","title":"Karvonen Z2 Max"},"naive_watch_z2_min":{"type":"integer","title":"Naive Watch Z2 Min"},"naive_watch_z2_max":{"type":"integer","title":"Naive Watch Z2 Max"},"z2_bpm_gained":{"type":"integer","title":"Z2 Bpm Gained"},"z2_comparison_summary":{"type":"string","title":"Z2 Comparison Summary"},"app_url":{"type":"string","title":"App Url"}},"type":"object","required":["lift","is_bodyweight_lift","e1rm_total_kg","e1rm_added_kg","target_reps","target_rpe","target_rir","prescribed_total_kg","prescribed_added_kg","pct_of_e1rm","max_reps_at_target_load","plate_breakdown","rpe_matrix","measured_or_tanaka_max_hr","rest_hr","heart_rate_reserve","karvonen_zones","karvonen_z2_min","karvonen_z2_max","naive_watch_z2_min","naive_watch_z2_max","z2_bpm_gained","z2_comparison_summary","app_url"],"title":"PlatesZone2Result"},"ProfileResponse":{"properties":{"profile":{"$ref":"#/components/schemas/AthleteProfileFields"},"goals":{"items":{"$ref":"#/components/schemas/AthleteGoalOut"},"type":"array","title":"Goals"},"active_pains":{"items":{"$ref":"#/components/schemas/ActivePainOut"},"type":"array","title":"Active Pains","description":"Unresolved joint or tendon pain constraints that workout prescriptions must respect."}},"type":"object","required":["profile","goals"],"title":"ProfileResponse"},"RacePrediction":{"properties":{"distance":{"type":"string","title":"Distance"},"time":{"type":"string","title":"Time"},"pace":{"type":"string","title":"Pace"}},"type":"object","required":["distance","time","pace"],"title":"RacePrediction"},"RpeMatrixCell":{"properties":{"rpe":{"type":"number","title":"Rpe"},"rir":{"type":"number","title":"Rir"},"reps_loads":{"additionalProperties":{"type":"number"},"type":"object","title":"Reps Loads"}},"type":"object","required":["rpe","rir","reps_loads"],"title":"RpeMatrixCell"},"RunTarget":{"properties":{"target_pace":{"type":"string","title":"Target Pace","description":"Target pace per km for each of the 8 x 1 km runs"},"pace_band":{"type":"string","title":"Pace Band","description":"Aggressive to conservative pace band"},"total_running_time":{"type":"string","title":"Total Running Time"},"estimated_race_time":{"type":"string","title":"Estimated Race Time","description":"Whole race, stations included (estimate)"},"strategy":{"type":"string","title":"Strategy"}},"type":"object","required":["target_pace","pace_band","total_running_time","estimated_race_time","strategy"],"title":"RunTarget"},"SessionItemOut":{"properties":{"date":{"type":"string","title":"Date","description":"Session date (YYYY-MM-DD)","examples":["2026-11-11"]},"exercise":{"type":"string","title":"Exercise","examples":["Back Squat"]},"exercise_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exercise Type","examples":["strength"]},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"completed or planned","examples":["completed"]},"planned_sets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Planned Sets"},"planned_reps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Planned Reps"},"planned_weight_kg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Planned Weight Kg"},"planned_rpe":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Planned Rpe"},"planned_duration_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Planned Duration Min"},"planned_distance_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Planned Distance Km"},"actual_sets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Actual Sets","examples":[4]},"actual_reps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Actual Reps","examples":[8]},"actual_weight_kg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Weight Kg","examples":[100.0]},"actual_rpe":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Rpe","examples":[8.0]},"actual_duration_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Duration Min"},"actual_distance_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Distance Km"},"actual_pace":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actual Pace"},"comments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comments"}},"type":"object","required":["date","exercise"],"title":"SessionItemOut"},"SessionsResponse":{"properties":{"sessions":{"items":{"$ref":"#/components/schemas/SessionItemOut"},"type":"array","title":"Sessions"}},"type":"object","required":["sessions"],"title":"SessionsResponse"},"SetIn":{"properties":{"reps":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":1.0},{"type":"null"}],"title":"Reps","examples":[8]},"weight_kg":{"anyOf":[{"type":"number","maximum":500.0,"minimum":0.0},{"type":"null"}],"title":"Weight Kg","examples":[100.0]},"rpe":{"anyOf":[{"type":"number","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Rpe","examples":[8.0]}},"type":"object","title":"SetIn"},"StrengthBenchmarkResult":{"properties":{"lift":{"type":"string","title":"Lift"},"e1rm_kg":{"type":"number","title":"E1Rm Kg","description":"Estimated 1RM (added load for dips / pull-ups / chin-ups)"},"score":{"type":"integer","title":"Score","description":"Bodyweight-, sex- and age-adjusted strength score"},"tier":{"type":"string","title":"Tier"},"next_tier":{"anyOf":[{"$ref":"#/components/schemas/NextTier"},{"type":"null"}]},"app_url":{"type":"string","title":"App Url"}},"type":"object","required":["lift","e1rm_kg","score","tier","next_tier","app_url"],"title":"StrengthBenchmarkResult"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VolumeAuditEntry":{"properties":{"archetype":{"type":"string","title":"Archetype","description":"Movement archetype key (e.g. horizontal_press, vertical_pull)"},"sets":{"type":"integer","maximum":60.0,"minimum":0.0,"title":"Sets","description":"Weekly sets for this movement"},"rpe":{"type":"number","maximum":10.0,"minimum":5.0,"title":"Rpe","description":"Average RPE (sets < RPE 6 are warm-ups)","default":8.0},"frequency_days":{"type":"integer","maximum":7.0,"minimum":1.0,"title":"Frequency Days","description":"Days per week this movement is performed","default":2}},"type":"object","required":["archetype","sets"],"title":"VolumeAuditEntry"},"VolumeAuditRequest":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/VolumeAuditEntry"},"type":"array","maxItems":25,"minItems":1,"title":"Entries"},"preset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preset Id","description":"Optional preset identifier for telemetry"}},"type":"object","required":["entries"],"title":"VolumeAuditRequest"},"VolumeAuditResult":{"properties":{"total_raw_sets":{"type":"integer","title":"Total Raw Sets"},"total_hard_sets":{"type":"number","title":"Total Hard Sets"},"total_junk_sets":{"type":"number","title":"Total Junk Sets"},"junk_volume_pct":{"type":"number","title":"Junk Volume Pct"},"effective_stimulus_pct":{"type":"number","title":"Effective Stimulus Pct"},"overloaded_muscles":{"items":{"type":"string"},"type":"array","title":"Overloaded Muscles"},"undertrained_muscles":{"items":{"type":"string"},"type":"array","title":"Undertrained Muscles"},"optimal_muscles":{"items":{"type":"string"},"type":"array","title":"Optimal Muscles"},"primary_anomaly_muscle":{"type":"string","title":"Primary Anomaly Muscle"},"primary_anomaly_summary":{"type":"string","title":"Primary Anomaly Summary"},"muscles":{"items":{"$ref":"#/components/schemas/MuscleAuditRow"},"type":"array","title":"Muscles"},"recommendations":{"items":{"type":"string"},"type":"array","title":"Recommendations"},"app_url":{"type":"string","title":"App Url"}},"type":"object","required":["total_raw_sets","total_hard_sets","total_junk_sets","junk_volume_pct","effective_stimulus_pct","overloaded_muscles","undertrained_muscles","optimal_muscles","primary_anomaly_muscle","primary_anomaly_summary","muscles","recommendations","app_url"],"title":"VolumeAuditResult"},"WorkoutAdvisory":{"properties":{"code":{"type":"string","title":"Code","examples":["axial_fatigue_clash"]},"severity":{"type":"string","enum":["warn","critical"],"title":"Severity","examples":["warn"]},"message":{"type":"string","title":"Message","examples":["Heavy squat and heavy hinge (RPE >= 8) are scheduled on consecutive calendar days, violating the 48–72h central and spinal recovery window."]},"agent_action":{"type":"string","title":"Agent Action","examples":["Separate heavy squat and heavy deadlift/hinge days by >= 48h, or lower the second session's intensity to a technical variant at RPE 6–7."]}},"type":"object","required":["code","severity","message","agent_action"],"title":"WorkoutAdvisory"},"WorkoutIn":{"properties":{"exercise":{"type":"string","maxLength":80,"minLength":1,"title":"Exercise","description":"Canonical or natural exercise name (e.g. 'Back Squat', 'Easy Zone 2 Run', 'SkiErg Intervals')","examples":["Back Squat"]},"date":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"title":"Date","description":"Workout date (YYYY-MM-DD). Defaults to today in the athlete's timezone when logging.","examples":["2026-11-12"]},"exercise_type":{"type":"string","enum":["strength","endurance","mobility","other"],"title":"Exercise Type","description":"Training modality (`strength` for resistance sets, `endurance` for runs/ergs/rides)","default":"strength"},"sets":{"anyOf":[{"type":"integer","maximum":50.0,"minimum":1.0},{"type":"null"}],"title":"Sets","description":"Number of working sets","examples":[4]},"reps":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":1.0},{"type":"null"}],"title":"Reps","description":"Reps per set","examples":[8]},"weight_kg":{"anyOf":[{"type":"number","maximum":500.0,"minimum":0.0},{"type":"null"}],"title":"Weight Kg","description":"External load in kg (added load for bodyweight movements such as pull-ups or dips)","examples":[100.0]},"rpe":{"anyOf":[{"type":"number","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Rpe","description":"Borg CR10 / RIR-based Rate of Perceived Exertion (1–10)","examples":[8.0]},"duration_min":{"anyOf":[{"type":"number","maximum":1440.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Duration Min","description":"Duration in minutes (primarily for endurance/mobility sessions)"},"distance_km":{"anyOf":[{"type":"number","maximum":500.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Distance Km","description":"Distance covered in kilometers (for running, rowing, SkiErg, cycling)"},"set_details":{"anyOf":[{"items":{"$ref":"#/components/schemas/SetIn"},"type":"array","maxItems":50},{"type":"null"}],"title":"Set Details","description":"Optional per-set breakdown when load, reps, or RPE vary across sets"},"comments":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Comments","description":"Optional athlete notes, splits, or subjective feel","examples":["Felt crisp, beltless"]}},"type":"object","required":["exercise"],"title":"WorkoutIn"},"WorkoutSavedResponse":{"properties":{"saved":{"type":"boolean","title":"Saved","examples":[true]},"result":{"type":"string","title":"Result","examples":["Saved Back Squat: added 1 completed row(s)."]},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trace Id","description":"Trace correlation ID for AI evaluation & audit spans."},"advisories":{"items":{"$ref":"#/components/schemas/WorkoutAdvisory"},"type":"array","title":"Advisories","description":"Deterministic physiology and clinical pain advisories audited against the athlete's measured e1RM envelope, 48–72h axial recovery window, intra-day lift hierarchy, and active pain states."}},"type":"object","required":["saved","result"],"title":"WorkoutSavedResponse"}},"securitySchemes":{"OAuth2AuthorizationCode":{"type":"oauth2","description":"OAuth 2.1 Authorization Code flow with PKCE (S256) for consumer AI assistants (Meta AI Connectors across AI glasses/mobile/web, Claude.ai Connectors, ChatGPT Actions). Supports RFC 8414 metadata (`/.well-known/oauth-authorization-server`), RFC 9728 protected resource metadata (`/.well-known/oauth-protected-resource`), RFC 7591 dynamic client registration (`/oauth/register`), refresh token rotation, and RFC 7009 revocation (`/oauth/revoke`).","flows":{"authorizationCode":{"authorizationUrl":"https://struggl.singandclap.com/oauth/authorize","tokenUrl":"https://struggl.singandclap.com/oauth/token","refreshUrl":"https://struggl.singandclap.com/oauth/token","scopes":{"read":"Read athletic profile, race goals, training sessions, and weekly 17-muscle volume.","write":"Log completed sets/runs and schedule planned workouts on the athlete's calendar."}}}},"AthleteBearer":{"type":"http","scheme":"bearer","bearerFormat":"stg_ath_<token>","description":"Scoped athlete Bearer token (`Authorization: Bearer stg_ath_...`) issued via OAuth 2.1 or self-serve at https://struggl.singandclap.com/connect (included during the free 1st month of Coach, then €9.99/mo or €109.89/yr). Tokens carry `read` scope (profile, sessions, weekly muscle volume) and optional `write` scope (log completed workouts, schedule planned sessions). Fair-use caps per athlete: Coach 60 reads/hr (200/day) & 30 writes/hr (80/day)."}}},"tags":[{"name":"athlete","description":"Authenticated athlete endpoints (`/v1/me/*`). Require a scoped Bearer token (`read` for profile, sessions, and weekly muscle volume; `write` for logging completed sets or scheduling planned workouts)."},{"name":"public","description":"Stateless, deterministic hybrid-athlete calculators (`/v1/public/*`). Require no authentication and store no personal data."}]}