Personal Athlete API (/v1/me/*)
Authenticated endpoints reading or updating the linked athlete's training log, race goals, and weekly 17-muscle volume ledger.
GET
/v1/me/profile
getAthleteProfile
Bearer · scope: read
Get the authenticated athlete's biometric profile and race goals
Returns athlete-facing physiological attributes (bodyweight, height, sex, primary modality, training phase, weekly time budget) and upcoming target events/races. Requires `read` scope.
200 OK Response Schema
| Field | Type | Status | Description |
|---|
profile | AthleteProfileFields | required | |
goals | AthleteGoalOut[] | required | |
active_pains | ActivePainOut[] | optional | Unresolved joint or tendon pain constraints that workout prescriptions must respect. |
Example Request
curl -s "https://struggl.singandclap.com/v1/me/profile" \
-H "Authorization: Bearer stg_ath_..."
200 OK Sample Payload
{
"profile": {
"name": "Taha",
"sex": "male",
"weight_kg": 65.0,
"height_cm": 175.0,
"primary_modality": "hyrox",
"current_phase": "specific_prep",
"weekly_time_budget": 7.5
},
"goals": [
{
"name": "HYROX Paris",
"event_date": "2027-04-25",
"discipline": "hyrox_men_open",
"target_time_s": 4320
}
]
}
GET
/v1/me/sessions
getAthleteSessions
Bearer · scope: read
List completed and planned training sessions
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.
Query Parameters
| Parameter | Type | Status | Description |
|---|
days | integer | optional | Lookback/lookahead window in days (ignored when `date` is set) |
date | string? | optional | Filter to a single calendar date (YYYY-MM-DD) |
200 OK Response Schema
| Field | Type | Status | Description |
|---|
sessions | SessionItemOut[] | required | |
Example Request
curl -s "https://struggl.singandclap.com/v1/me/sessions?days=7" \
-H "Authorization: Bearer stg_ath_..."
200 OK Sample Payload
{
"sessions": [
{
"date": "2026-11-11",
"exercise": "Back Squat",
"exercise_type": "strength",
"status": "completed",
"actual_sets": 4,
"actual_reps": 8,
"actual_weight_kg": 100.0,
"actual_rpe": 8.0
},
{
"date": "2026-11-12",
"exercise": "Threshold Run",
"exercise_type": "endurance",
"status": "planned",
"planned_duration_min": 40.0,
"planned_distance_km": 8.0,
"planned_rpe": 7.5
}
]
}
GET
/v1/me/muscle-volume
getWeeklyMuscleVolume
Bearer · scope: read
Get current week's hard sets per muscle group vs MEV/MAV/MRV landmarks
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.
200 OK Response Schema
| Field | Type | Status | Description |
|---|
summary | string | required | 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. |
Example Request
curl -s "https://struggl.singandclap.com/v1/me/muscle-volume" \
-H "Authorization: Bearer stg_ath_..."
200 OK Sample Payload
{
"summary": "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) · Chest: 8.0 sets (MEV 6–10)"
}
POST
/v1/me/workouts/log
logCompletedWorkout
Bearer · scope: write
Log a completed strength or endurance exercise
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.
JSON Request Body
| Field | Type | Status | Description |
|---|
exercise | string | required | Canonical or natural exercise name (e.g. 'Back Squat', 'Easy Zone 2 Run', 'SkiErg Intervals') |
date | string? | optional | Workout date (YYYY-MM-DD). Defaults to today in the athlete's timezone when logging. |
exercise_type | enum(strength | endurance | mobility | other) | optional | Training modality (`strength` for resistance sets, `endurance` for runs/ergs/rides) (default: strength) |
sets | integer? | optional | Number of working sets |
reps | integer? | optional | Reps per set |
weight_kg | number? | optional | External load in kg (added load for bodyweight movements such as pull-ups or dips) |
rpe | number? | optional | Borg CR10 / RIR-based Rate of Perceived Exertion (1–10) |
duration_min | number? | optional | Duration in minutes (primarily for endurance/mobility sessions) |
distance_km | number? | optional | Distance covered in kilometers (for running, rowing, SkiErg, cycling) |
set_details | SetIn[]? | optional | Optional per-set breakdown when load, reps, or RPE vary across sets |
comments | string? | optional | Optional athlete notes, splits, or subjective feel |
200 OK Response Schema
| Field | Type | Status | Description |
|---|
saved | boolean | required | |
result | string | required | |
trace_id | string? | optional | Trace correlation ID for AI evaluation & audit spans. |
advisories | WorkoutAdvisory[] | optional | 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. |
Example Request
curl -s -X POST "https://struggl.singandclap.com/v1/me/workouts/log" \
-H "Authorization: Bearer stg_ath_..." \
-H "Content-Type: application/json" \
-d '{"exercise":"Back Squat","exercise_type":"strength","sets":4,"reps":8,"weight_kg":100,"rpe":8}'
200 OK Sample Payload
{
"saved": true,
"result": "Saved Back Squat: added 1 completed row(s)."
}
POST
/v1/me/workouts/plan
planScheduledWorkout
Bearer · scope: write
Schedule a planned exercise on the athlete's calendar
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.
JSON Request Body
| Field | Type | Status | Description |
|---|
exercise | string | required | Canonical or natural exercise name (e.g. 'Back Squat', 'Easy Zone 2 Run', 'SkiErg Intervals') |
date | string? | optional | Workout date (YYYY-MM-DD). Defaults to today in the athlete's timezone when logging. |
exercise_type | enum(strength | endurance | mobility | other) | optional | Training modality (`strength` for resistance sets, `endurance` for runs/ergs/rides) (default: strength) |
sets | integer? | optional | Number of working sets |
reps | integer? | optional | Reps per set |
weight_kg | number? | optional | External load in kg (added load for bodyweight movements such as pull-ups or dips) |
rpe | number? | optional | Borg CR10 / RIR-based Rate of Perceived Exertion (1–10) |
duration_min | number? | optional | Duration in minutes (primarily for endurance/mobility sessions) |
distance_km | number? | optional | Distance covered in kilometers (for running, rowing, SkiErg, cycling) |
set_details | SetIn[]? | optional | Optional per-set breakdown when load, reps, or RPE vary across sets |
comments | string? | optional | Optional athlete notes, splits, or subjective feel |
200 OK Response Schema
| Field | Type | Status | Description |
|---|
saved | boolean | required | |
result | string | required | |
trace_id | string? | optional | Trace correlation ID for AI evaluation & audit spans. |
advisories | WorkoutAdvisory[] | optional | 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. |
Example Request
curl -s -X POST "https://struggl.singandclap.com/v1/me/workouts/plan" \
-H "Authorization: Bearer stg_ath_..." \
-H "Content-Type: application/json" \
-d '{"exercise":"Zone 2 Aerobic Run","date":"2026-11-14","exercise_type":"endurance","duration_min":45,"distance_km":8.5,"rpe":6}'
200 OK Sample Payload
{
"saved": true,
"result": "Planned Zone 2 Aerobic Run on 2026-11-14."
}
Deterministic Physiology Calculators (/v1/public/*)
Zero-authentication hybrid-athlete calculators backed by 200k Hyrox finisher splits, piecewise Wathan 1RM curves, and Karvonen heart-rate reserve zones.
POST
/v1/public/volume-audit
volumeAudit
Public · no auth
Audit weekly Direct (1.0x) + Secondary (0.5x) volume across 17 muscles
JSON Request Body
| Field | Type | Status | Description |
|---|
entries | VolumeAuditEntry[] | required | |
preset_id | string? | optional | Optional preset identifier for telemetry |
200 OK Response Schema
| Field | Type | Status | Description |
|---|
total_raw_sets | integer | required | |
total_hard_sets | number | required | |
total_junk_sets | number | required | |
junk_volume_pct | number | required | |
effective_stimulus_pct | number | required | |
overloaded_muscles | string[] | required | |
undertrained_muscles | string[] | required | |
optimal_muscles | string[] | required | |
primary_anomaly_muscle | string | required | |
primary_anomaly_summary | string | required | |
muscles | MuscleAuditRow[] | required | |
recommendations | string[] | required | |
app_url | string | required | |
Example Request
curl -s -X POST "https://struggl.singandclap.com/v1/public/volume-audit" \
-H "Content-Type: application/json" \
-d '{"entries":[{"archetype":"squat","sets":4,"rpe":8},{"archetype":"hinge","sets":3,"rpe":8.5},{"archetype":"vertical_pull","sets":4,"rpe":8}]}'
200 OK Sample Payload
{
"total_raw_sets": 11,
"total_hard_sets": 11.0,
"effective_stimulus_pct": 100.0,
"optimal_muscles": [
"quads",
"glutes",
"lats"
]
}
POST
/v1/public/hyrox-splits
hyroxSplits
Public · no auth
Compute 8 compromised Hyrox 1km run splits from standalone 5K time (200k finisher dataset)
JSON Request Body
| Field | Type | Status | Description |
|---|
standalone_5k_time | string | required | Standalone 5K time MM:SS (e.g. 21:30) |
goal_time | string? | optional | Optional target Hyrox finish time H:MM:SS |
cns_penalty_sec_per_km | integer | optional | Additional CNS/sled fatigue penalty in s/km (min 0.0, max 35.0, default: 0) |
division | enum(open_men | open_women | pro_men | pro_women | doubles) | optional | (default: open_men) |
200 OK Response Schema
| Field | Type | Status | Description |
|---|
standalone_5k_time | string | required | |
standalone_5k_pace | string | required | |
standalone_5k_pace_seconds | integer | required | |
decay_factor | number | required | |
decay_pct | number | required | |
compromised_target_pace | string | required | |
compromised_target_pace_seconds | integer | required | |
pace_band | string | required | |
total_running_time | string | required | |
est_total_race_time | string | required | |
lap1_trap_warning | string | required | |
lap1_blowup_cost_minutes | number | required | |
strategy | string | required | |
laps | HyroxLapSplitRow[] | required | |
race_predictions | RacePrediction[] | required | |
app_url | string | required | |
Example Request
curl -s -X POST "https://struggl.singandclap.com/v1/public/hyrox-splits" \
-H "Content-Type: application/json" \
-d '{"standalone_5k_time":"21:30","division":"open_men"}'
200 OK Sample Payload
{
"standalone_5k_time": "21:30",
"standalone_5k_pace": "4:18/km",
"compromised_target_pace": "4:41/km",
"pace_band": "4:35 - 4:48/km",
"total_running_time": "37:28",
"est_total_race_time": "1:13:10"
}
POST
/v1/public/plates-zone2
platesAndZone2
Public · no auth
Convert Reps x RPE to exact bar plates (core/prescribe.py) + Karvonen HR zones (core/endurance.py)
JSON Request Body
| Field | Type | Status | Description |
|---|
lift | string | optional | Lift key: bench_press, back_squat, deadlift, overhead_press, pull_up, dip (default: bench_press) |
bodyweight_kg | number | optional | (default: 78.0) |
sex | enum(male | female) | optional | (default: male) |
ref_weight_kg | number | optional | Reference set weight (added weight for pull_up/dip) (min 0.0, max 500.0, default: 100.0) |
ref_reps | integer | optional | Reference set reps (min 1.0, max 20.0, default: 5) |
ref_rpe | number | optional | Reference set RPE (min 5.0, max 10.0, default: 8.5) |
target_reps | integer | optional | Target set reps (min 1.0, max 20.0, default: 8) |
target_rpe | number | optional | Target set RPE (min 5.0, max 10.0, default: 8.0) |
bar_weight_kg | number | optional | Barbell weight in kg (20kg or 15kg) (min 10.0, max 25.0, default: 20.0) |
age | integer | optional | Athlete age in years (min 14.0, max 90.0, default: 30) |
rest_hr | integer | optional | Resting heart rate in bpm (min 32.0, max 110.0, default: 52) |
max_hr | integer? | optional | Optional measured Max HR (defaults to Tanaka 208 - 0.7*age) |
200 OK Response Schema
| Field | Type | Status | Description |
|---|
lift | string | required | |
is_bodyweight_lift | boolean | required | |
e1rm_total_kg | number | required | |
e1rm_added_kg | number | required | |
target_reps | integer | required | |
target_rpe | number | required | |
target_rir | number | required | |
prescribed_total_kg | number | required | |
prescribed_added_kg | number | required | |
pct_of_e1rm | number | required | |
max_reps_at_target_load | integer | required | |
plate_breakdown | object | required | |
rpe_matrix | RpeMatrixCell[] | required | |
measured_or_tanaka_max_hr | integer | required | |
rest_hr | integer | required | |
heart_rate_reserve | integer | required | |
karvonen_zones | object[] | required | |
karvonen_z2_min | integer | required | |
karvonen_z2_max | integer | required | |
naive_watch_z2_min | integer | required | |
naive_watch_z2_max | integer | required | |
z2_bpm_gained | integer | required | |
z2_comparison_summary | string | required | |
app_url | string | required | |
Example Request
curl -s -X POST "https://struggl.singandclap.com/v1/public/plates-zone2" \
-H "Content-Type: application/json" \
-d '{"lift":"back_squat","ref_weight_kg":110,"ref_reps":5,"ref_rpe":8.5,"target_reps":6,"target_rpe":8,"age":29,"resting_hr":50}'
200 OK Sample Payload
{
"lift": "back_squat",
"e1rm_kg": 131.5,
"prescribed_total_kg": 105.0,
"karvonen_z2_min": 135,
"karvonen_z2_max": 149
}