{"openapi":"3.1.0","info":{"title":"ExerciseAPI","version":"1.0.0","summary":"Free, public, read-only REST API for a hand-curated, hypertrophy-focused exercise library.","description":"A catalog of 183 hand-curated exercises with training-quality metadata: stimulus-to-fatigue ratings, research-backed gold-standard flags, e1RM substitution groups, calisthenics progression chains, curated rep ranges, and coaching cues.\n\nNo authentication required. All endpoints are GET, JSON-only, CORS-enabled, and CDN-cached.\n\nThe `/v1` contract is additive-only: fields and enum values may be added, never removed or retyped. The catalog content is versioned independently via semver, exposed in `GET /v1/meta` and the `X-Dataset-Version` response header.\n\nData license: CC BY 4.0 (attribution required). Code: MIT.","contact":{"name":"ExerciseAPI"},"license":{"name":"CC BY 4.0 (data)","identifier":"CC-BY-4.0"}},"servers":[{"url":"https://www.exercise-api.com","description":"This deployment"}],"paths":{"/v1/exercises":{"get":{"operationId":"listExercises","summary":"List and filter exercises","description":"Returns exercises matching every provided filter (filters AND together; comma-separated values within one filter OR together). Use `available_equipment` to get only exercises doable with the gear you have — `none_bodyweight` (your own body) is always implied. Results are deterministic: stable sort with id tiebreak, so pagination is safe.","parameters":[{"name":"muscle","in":"query","required":false,"description":"Filter by primary muscle. Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["abs","biceps","calves","chest","forearms","front_delts","glutes","hamstrings","lats","lower_back","quads","rear_delts","side_delts","traps","triceps","upper_back"]},"style":"form"},{"name":"secondary_muscle","in":"query","required":false,"description":"Filter by secondary muscle involvement. Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["abs","biceps","calves","chest","forearms","front_delts","glutes","hamstrings","lats","lower_back","quads","rear_delts","side_delts","traps","triceps","upper_back"]},"style":"form"},{"name":"pattern","in":"query","required":false,"description":"Filter by movement pattern. Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["anti_extension","calf_raise","curl","fly","hip_hinge","hip_thrust","horizontal_press","horizontal_pull","incline_press","lateral_raise","leg_curl","leg_extension","lunge","rear_delt","shrug","squat","triceps_extension","trunk_flexion","vertical_press","vertical_pull"]},"style":"form"},{"name":"sfr_class","in":"query","required":false,"description":"Filter by stimulus-to-fatigue class. Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["high","moderate","low"]},"style":"form"},{"name":"tier","in":"query","required":false,"description":"Filter by catalog tier. Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["core","extended"]},"style":"form"},{"name":"modality","in":"query","required":false,"description":"Filter by training purpose (conditioning and mobility arrive in upcoming dataset releases). Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["hypertrophy","conditioning","calisthenics","mobility"]},"style":"form"},{"name":"substitution_group","in":"query","required":false,"description":"Filter by e1RM substitution group (see GET /v1/meta for values). Accepts a comma-separated list (matches any).","schema":{"type":"string"},"style":"form"},{"name":"progression_group","in":"query","required":false,"description":"Filter by calisthenics progression chain (see GET /v1/meta for values). Accepts a comma-separated list (matches any).","schema":{"type":"string"},"style":"form"},{"name":"equipment","in":"query","required":false,"description":"Exercises that require this equipment token. Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["ab_wheel","adjustable_bench","assisted_pullup_machine","barbell","bench_or_box","cable_stack","chest_press_machine","dip_belt","dip_station","dumbbells","ez_curl_bar","flat_bench","gymnastic_rings","hack_squat_machine","hip_thrust_machine","landmine","lat_pulldown","leg_curl_machine","leg_extension_machine","leg_press","none_bodyweight","parallettes","pec_deck","power_rack","preacher_bench","pullup_bar","resistance_bands","seated_calf_machine","seated_row_machine","shoulder_press_machine","smith_machine","standing_calf_machine","suspension_trainer","t_bar_row"]},"style":"form"},{"name":"available_equipment","in":"query","required":false,"description":"Subset match: only exercises whose ENTIRE equipment list is covered by the provided tokens. `none_bodyweight` is always implied. Accepts a comma-separated list (matches any).","schema":{"type":"string","enum":["ab_wheel","adjustable_bench","assisted_pullup_machine","barbell","bench_or_box","cable_stack","chest_press_machine","dip_belt","dip_station","dumbbells","ez_curl_bar","flat_bench","gymnastic_rings","hack_squat_machine","hip_thrust_machine","landmine","lat_pulldown","leg_curl_machine","leg_extension_machine","leg_press","none_bodyweight","parallettes","pec_deck","power_rack","preacher_bench","pullup_bar","resistance_bands","seated_calf_machine","seated_row_machine","shoulder_press_machine","smith_machine","standing_calf_machine","suspension_trainer","t_bar_row"]},"style":"form"},{"name":"gold_standard","in":"query","required":false,"description":"Only research-backed top picks (or explicitly exclude them with false).","schema":{"type":"boolean"}},{"name":"loadable","in":"query","required":false,"description":"Filter by external-load capability.","schema":{"type":"boolean"}},{"name":"unilateral","in":"query","required":false,"description":"Filter by unilateral execution.","schema":{"type":"boolean"}},{"name":"home_hotel_friendly","in":"query","required":false,"description":"Filter by minimal-equipment practicality.","schema":{"type":"boolean"}},{"name":"q","in":"query","required":false,"description":"Case-insensitive substring search over name and id.","schema":{"type":"string"}},{"name":"sort","in":"query","required":false,"description":"Sort key. Prefix with \"-\" for descending. Default: name.","schema":{"type":"string","enum":["name","-name","preferred_rank","-preferred_rank","id","-id"]}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–200. Default 20. The full catalog (183 records) fits in one page with limit=200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":20}},{"name":"offset","in":"query","required":false,"description":"Zero-based offset into the filtered result set.","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"A page of matching exercises.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExerciseList"}}}},"400":{"description":"A filter value was invalid. The error message lists the valid values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/exercises/{id}":{"get":{"operationId":"getExercise","summary":"Fetch one exercise by slug","parameters":[{"name":"id","in":"path","required":true,"description":"Stable snake_case slug, e.g. barbell_bench_press.","schema":{"type":"string"}}],"responses":{"200":{"description":"The exercise.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Exercise"},"examples":{"barbell_bench_press":{"value":{"id":"barbell_bench_press","name":"Barbell Bench Press","primary_muscle":"chest","secondary_muscles":["front_delts","triceps"],"pattern":"horizontal_press","equipment":["barbell","flat_bench","power_rack"],"sfr_class":"moderate","is_gold_standard":true,"preferred_rank":1,"e1rm_substitution_group":"chest_horizontal_press","default_rep_low":6,"default_rep_high":10,"loadable":true,"unilateral":false,"home_hotel_friendly":false,"tier":"core","modality":"hypertrophy","progression_group":null,"progression_level":null,"cues":"Tuck elbows ~45 degrees, touch lower chest, drive bar back over shoulders."}}}}}},"404":{"description":"No exercise with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/meta":{"get":{"operationId":"getMeta","summary":"Controlled vocabularies, counts, and dataset version","description":"Self-describing catalog metadata: every filterable vocabulary with occurrence counts (ideal for building filter UIs or validating agent tool calls) plus the current dataset_version.","responses":{"200":{"description":"Catalog metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meta"}}}}}}},"/health":{"get":{"operationId":"getHealth","summary":"Liveness + dataset size","responses":{"200":{"description":"Service is up.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"ok"},"dataset_version":{"type":"string"},"exercises":{"type":"integer"}}}}}}}}}},"components":{"schemas":{"Exercise":{"type":"object","description":"One exercise from the hand-curated, hypertrophy-focused catalog. All 19 fields are always present; nullable fields use null.","required":["id","name","primary_muscle","secondary_muscles","pattern","equipment","sfr_class","is_gold_standard","preferred_rank","e1rm_substitution_group","default_rep_low","default_rep_high","loadable","unilateral","home_hotel_friendly","tier","modality","progression_group","progression_level","cues"],"properties":{"id":{"type":"string","description":"Stable, URL-safe snake_case slug, unique across the catalog (e.g. `barbell_bench_press`). Never reused or renamed — safe to store as a foreign reference."},"name":{"type":"string","description":"Human-readable display name."},"primary_muscle":{"type":"string","enum":["abs","biceps","calves","chest","forearms","front_delts","glutes","hamstrings","lats","lower_back","quads","rear_delts","side_delts","traps","triceps","upper_back"],"description":"The muscle the exercise primarily targets."},"secondary_muscles":{"type":"array","items":{"type":"string","enum":["abs","biceps","calves","chest","forearms","front_delts","glutes","hamstrings","lats","lower_back","quads","rear_delts","side_delts","traps","triceps","upper_back"]},"description":"Muscles meaningfully worked besides the primary. Same vocabulary as `primary_muscle`. May be empty."},"pattern":{"type":"string","enum":["anti_extension","calf_raise","curl","fly","hip_hinge","hip_thrust","horizontal_press","horizontal_pull","incline_press","lateral_raise","leg_curl","leg_extension","lunge","rear_delt","shrug","squat","triceps_extension","trunk_flexion","vertical_press","vertical_pull"],"description":"Movement pattern classification."},"equipment":{"type":"array","items":{"type":"string","enum":["ab_wheel","adjustable_bench","assisted_pullup_machine","barbell","bench_or_box","cable_stack","chest_press_machine","dip_belt","dip_station","dumbbells","ez_curl_bar","flat_bench","gymnastic_rings","hack_squat_machine","hip_thrust_machine","landmine","lat_pulldown","leg_curl_machine","leg_extension_machine","leg_press","none_bodyweight","parallettes","pec_deck","power_rack","preacher_bench","pullup_bar","resistance_bands","seated_calf_machine","seated_row_machine","shoulder_press_machine","smith_machine","standing_calf_machine","suspension_trainer","t_bar_row"]},"description":"Every equipment token required to perform the exercise. `none_bodyweight` means no equipment is needed."},"sfr_class":{"type":["string","null"],"enum":["high","moderate","low"],"description":"Stimulus-to-fatigue ratio class: how much hypertrophy stimulus the exercise delivers per unit of fatigue. `high` is best. Null for non-hypertrophy modalities."},"is_gold_standard":{"type":"boolean","description":"True when the exercise is a research/EMG-backed top pick for its primary muscle (see data/SOURCE.md for citations)."},"preferred_rank":{"type":["integer","null"],"minimum":1,"description":"1-based preference order among exercises sharing a primary muscle — lower is more preferred by the curators. Null for non-hypertrophy modalities."},"e1rm_substitution_group":{"type":["string","null"],"description":"Named group of interchangeable exercises for estimated-1RM tracking: swapping within a group preserves comparable strength-progression data. Null when e1RM tracking doesn't apply."},"default_rep_low":{"type":["integer","null"],"minimum":1,"description":"Lower bound of the curated default hypertrophy rep range. Null for time- or hold-based work."},"default_rep_high":{"type":["integer","null"],"minimum":1,"description":"Upper bound of the curated default hypertrophy rep range. Null for time- or hold-based work."},"loadable":{"type":"boolean","description":"True when the exercise can be progressively loaded with external weight."},"unilateral":{"type":"boolean","description":"True when the exercise trains one side at a time."},"home_hotel_friendly":{"type":"boolean","description":"True when the exercise is practical with minimal/portable equipment (hotel room, home setup)."},"tier":{"type":"string","enum":["core","extended"],"description":"`core` = the curated default library; `extended` = additive variations and calisthenics progression rungs."},"modality":{"type":"string","enum":["hypertrophy","conditioning","calisthenics","mobility"],"description":"Primary training purpose. Current catalog: `hypertrophy` and `calisthenics` (skill-progression work); `conditioning` and `mobility` are reserved for upcoming dataset releases. Overlaps (e.g. weighted dips) are classified by primary purpose — use pattern/equipment/progression fields for finer slicing."},"progression_group":{"type":["string","null"],"description":"Named calisthenics progression chain this exercise belongs to (e.g. `planche_push_line`), or null for non-progression exercises."},"progression_level":{"type":["integer","null"],"minimum":1,"description":"1-based difficulty rung within `progression_group` (higher = harder), or null."},"cues":{"type":"string","description":"Short coaching cues for correct execution."}},"additionalProperties":false},"ExerciseList":{"type":"object","required":["object","data","count","total","limit","offset"],"properties":{"object":{"type":"string","const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Exercise"}},"count":{"type":"integer","description":"Records in this page."},"total":{"type":"integer","description":"Records matching the filters across all pages."},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"Meta":{"type":"object","description":"Vocabularies with counts, plus dataset_version (semver, also sent as the X-Dataset-Version header).","required":["object","dataset_version","api_version","counts","primary_muscles","patterns","equipment","sfr_classes","modalities","substitution_groups","progression_groups"],"properties":{"object":{"type":"string","const":"meta"},"dataset_version":{"type":"string","example":"1.1.0"},"api_version":{"type":"string","const":"v1"},"counts":{"type":"object","properties":{"total":{"type":"integer"},"by_tier":{"type":"object","additionalProperties":{"type":"integer"}}}},"primary_muscles":{"$ref":"#/components/schemas/VocabCounts"},"patterns":{"$ref":"#/components/schemas/VocabCounts"},"equipment":{"$ref":"#/components/schemas/VocabCounts"},"sfr_classes":{"$ref":"#/components/schemas/VocabCounts"},"modalities":{"$ref":"#/components/schemas/VocabCounts"},"substitution_groups":{"$ref":"#/components/schemas/VocabCounts"},"progression_groups":{"$ref":"#/components/schemas/VocabCounts"}}},"VocabCounts":{"type":"array","items":{"type":"object","required":["value","count"],"properties":{"value":{"type":"string"},"count":{"type":"integer"}}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","internal_error"],"description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}}}}}}}}