STRUGGL / REST API & Connector Reference OpenAPI 3.1.0
MCP & Architecture Docs Raw openapi.json

STRUGGL Hybrid-Athlete API

Production REST interface for AI assistants, hands-free wearable/AI-glasses coaching, and Model Context Protocol (MCP) clients. Exposes authenticated athlete training state (/v1/me/*) alongside stateless, peer-reviewed hybrid sports-science calculators (/v1/public/*).

Production Base URL
https://struggl.singandclap.com
OpenAPI 3.1 Specification
Authentication & OAuth 2.1
OAuth 2.1 PKCE (/oauth/authorize) & Bearer stg_ath_…
Remote MCP Endpoints
/v1/connector/mcp (OAuth) · /mcp (CLI)

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
FieldTypeStatusDescription
profileAthleteProfileFieldsrequired
goalsAthleteGoalOut[]required
active_painsActivePainOut[]optionalUnresolved 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
ParameterTypeStatusDescription
daysintegeroptionalLookback/lookahead window in days (ignored when `date` is set)
datestring?optionalFilter to a single calendar date (YYYY-MM-DD)
200 OK Response Schema
FieldTypeStatusDescription
sessionsSessionItemOut[]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
FieldTypeStatusDescription
summarystringrequiredFormatted 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
FieldTypeStatusDescription
exercisestringrequiredCanonical or natural exercise name (e.g. 'Back Squat', 'Easy Zone 2 Run', 'SkiErg Intervals')
datestring?optionalWorkout date (YYYY-MM-DD). Defaults to today in the athlete's timezone when logging.
exercise_typeenum(strength | endurance | mobility | other)optionalTraining modality (`strength` for resistance sets, `endurance` for runs/ergs/rides) (default: strength)
setsinteger?optionalNumber of working sets
repsinteger?optionalReps per set
weight_kgnumber?optionalExternal load in kg (added load for bodyweight movements such as pull-ups or dips)
rpenumber?optionalBorg CR10 / RIR-based Rate of Perceived Exertion (1–10)
duration_minnumber?optionalDuration in minutes (primarily for endurance/mobility sessions)
distance_kmnumber?optionalDistance covered in kilometers (for running, rowing, SkiErg, cycling)
set_detailsSetIn[]?optionalOptional per-set breakdown when load, reps, or RPE vary across sets
commentsstring?optionalOptional athlete notes, splits, or subjective feel
200 OK Response Schema
FieldTypeStatusDescription
savedbooleanrequired
resultstringrequired
trace_idstring?optionalTrace correlation ID for AI evaluation & audit spans.
advisoriesWorkoutAdvisory[]optionalDeterministic 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
FieldTypeStatusDescription
exercisestringrequiredCanonical or natural exercise name (e.g. 'Back Squat', 'Easy Zone 2 Run', 'SkiErg Intervals')
datestring?optionalWorkout date (YYYY-MM-DD). Defaults to today in the athlete's timezone when logging.
exercise_typeenum(strength | endurance | mobility | other)optionalTraining modality (`strength` for resistance sets, `endurance` for runs/ergs/rides) (default: strength)
setsinteger?optionalNumber of working sets
repsinteger?optionalReps per set
weight_kgnumber?optionalExternal load in kg (added load for bodyweight movements such as pull-ups or dips)
rpenumber?optionalBorg CR10 / RIR-based Rate of Perceived Exertion (1–10)
duration_minnumber?optionalDuration in minutes (primarily for endurance/mobility sessions)
distance_kmnumber?optionalDistance covered in kilometers (for running, rowing, SkiErg, cycling)
set_detailsSetIn[]?optionalOptional per-set breakdown when load, reps, or RPE vary across sets
commentsstring?optionalOptional athlete notes, splits, or subjective feel
200 OK Response Schema
FieldTypeStatusDescription
savedbooleanrequired
resultstringrequired
trace_idstring?optionalTrace correlation ID for AI evaluation & audit spans.
advisoriesWorkoutAdvisory[]optionalDeterministic 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.

GET /v1/public/hyrox-pace
hyroxPace Public · no auth

Hyrox run splits and race predictions from a 5 km time

Query Parameters
ParameterTypeStatusDescription
five_kstringrequiredRecent 5 km time, MM:SS (e.g. 22:30)
goalstring?optionalTarget Hyrox finish time, H:MM:SS (optional)
200 OK Response Schema
FieldTypeStatusDescription
five_k_timestringrequired
five_k_pacestringrequired
hyrox_runsRunTargetrequired
race_predictionsRacePrediction[]required
app_urlstringrequiredWhere the athlete can get a full plan
Example Request
curl -s "https://struggl.singandclap.com/v1/public/hyrox-pace?five_k=21:30&goal=1:12:00"
200 OK Sample Payload
{
  "five_k_time": "21:30",
  "five_k_pace": "4:18/km",
  "hyrox_runs": {
    "target_pace": "4:38/km",
    "pace_band": "4:33 - 4:45/km",
    "total_running_time": "37:04",
    "estimated_race_time": "1:12:15",
    "strategy": "Hold conservative rhythm through Run 4; protect Roxzone transitions."
  },
  "race_predictions": [
    {
      "distance": "10 km",
      "time": "44:42",
      "pace": "4:28/km"
    },
    {
      "distance": "Half marathon",
      "time": "1:38:50",
      "pace": "4:41/km"
    }
  ],
  "app_url": "https://struggl.singandclap.com/?ref=hyrox-pace&utm_source=public_api&utm_medium=api&utm_campaign=hyrox-pace"
}
GET /v1/public/strength-benchmark
strengthBenchmark Public · no auth

Estimated 1RM, strength score and tier from one set

Query Parameters
ParameterTypeStatusDescription
liftenum(back_squat | front_squat | deadlift | sumo_deadlift | bench_press…)requiredBenchmark lift
weight_kgnumberrequiredLoad lifted (ADDED load for dips / pull-ups / chin-ups)
repsintegerrequiredReps completed (estimates beyond 10 are capped)
bodyweight_kgnumberrequired
sexenum(male | female)required
ageinteger?optional
200 OK Response Schema
FieldTypeStatusDescription
liftstringrequired
e1rm_kgnumberrequiredEstimated 1RM (added load for dips / pull-ups / chin-ups)
scoreintegerrequiredBodyweight-, sex- and age-adjusted strength score
tierstringrequired
next_tierNextTier?required
app_urlstringrequired
Example Request
curl -s "https://struggl.singandclap.com/v1/public/strength-benchmark?lift=back_squat&weight_kg=120&reps=5&bodyweight_kg=65&sex=male"
200 OK Sample Payload
{
  "lift": "back_squat",
  "e1rm_kg": 140.0,
  "score": 81,
  "tier": "advanced",
  "next_tier": {
    "tier": "elite",
    "e1rm_needed_kg": 162.5,
    "kg_to_go": 22.5
  },
  "app_url": "https://struggl.singandclap.com/?ref=strength-benchmark&utm_source=public_api&utm_medium=api&utm_campaign=strength-benchmark"
}
POST /v1/public/volume-audit
volumeAudit Public · no auth

Audit weekly Direct (1.0x) + Secondary (0.5x) volume across 17 muscles

JSON Request Body
FieldTypeStatusDescription
entriesVolumeAuditEntry[]required
preset_idstring?optionalOptional preset identifier for telemetry
200 OK Response Schema
FieldTypeStatusDescription
total_raw_setsintegerrequired
total_hard_setsnumberrequired
total_junk_setsnumberrequired
junk_volume_pctnumberrequired
effective_stimulus_pctnumberrequired
overloaded_musclesstring[]required
undertrained_musclesstring[]required
optimal_musclesstring[]required
primary_anomaly_musclestringrequired
primary_anomaly_summarystringrequired
musclesMuscleAuditRow[]required
recommendationsstring[]required
app_urlstringrequired
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
FieldTypeStatusDescription
standalone_5k_timestringrequiredStandalone 5K time MM:SS (e.g. 21:30)
goal_timestring?optionalOptional target Hyrox finish time H:MM:SS
cns_penalty_sec_per_kmintegeroptionalAdditional CNS/sled fatigue penalty in s/km (min 0.0, max 35.0, default: 0)
divisionenum(open_men | open_women | pro_men | pro_women | doubles)optional (default: open_men)
200 OK Response Schema
FieldTypeStatusDescription
standalone_5k_timestringrequired
standalone_5k_pacestringrequired
standalone_5k_pace_secondsintegerrequired
decay_factornumberrequired
decay_pctnumberrequired
compromised_target_pacestringrequired
compromised_target_pace_secondsintegerrequired
pace_bandstringrequired
total_running_timestringrequired
est_total_race_timestringrequired
lap1_trap_warningstringrequired
lap1_blowup_cost_minutesnumberrequired
strategystringrequired
lapsHyroxLapSplitRow[]required
race_predictionsRacePrediction[]required
app_urlstringrequired
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
FieldTypeStatusDescription
liftstringoptionalLift key: bench_press, back_squat, deadlift, overhead_press, pull_up, dip (default: bench_press)
bodyweight_kgnumberoptional (default: 78.0)
sexenum(male | female)optional (default: male)
ref_weight_kgnumberoptionalReference set weight (added weight for pull_up/dip) (min 0.0, max 500.0, default: 100.0)
ref_repsintegeroptionalReference set reps (min 1.0, max 20.0, default: 5)
ref_rpenumberoptionalReference set RPE (min 5.0, max 10.0, default: 8.5)
target_repsintegeroptionalTarget set reps (min 1.0, max 20.0, default: 8)
target_rpenumberoptionalTarget set RPE (min 5.0, max 10.0, default: 8.0)
bar_weight_kgnumberoptionalBarbell weight in kg (20kg or 15kg) (min 10.0, max 25.0, default: 20.0)
ageintegeroptionalAthlete age in years (min 14.0, max 90.0, default: 30)
rest_hrintegeroptionalResting heart rate in bpm (min 32.0, max 110.0, default: 52)
max_hrinteger?optionalOptional measured Max HR (defaults to Tanaka 208 - 0.7*age)
200 OK Response Schema
FieldTypeStatusDescription
liftstringrequired
is_bodyweight_liftbooleanrequired
e1rm_total_kgnumberrequired
e1rm_added_kgnumberrequired
target_repsintegerrequired
target_rpenumberrequired
target_rirnumberrequired
prescribed_total_kgnumberrequired
prescribed_added_kgnumberrequired
pct_of_e1rmnumberrequired
max_reps_at_target_loadintegerrequired
plate_breakdownobjectrequired
rpe_matrixRpeMatrixCell[]required
measured_or_tanaka_max_hrintegerrequired
rest_hrintegerrequired
heart_rate_reserveintegerrequired
karvonen_zonesobject[]required
karvonen_z2_minintegerrequired
karvonen_z2_maxintegerrequired
naive_watch_z2_minintegerrequired
naive_watch_z2_maxintegerrequired
z2_bpm_gainedintegerrequired
z2_comparison_summarystringrequired
app_urlstringrequired
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
}