GymFit API
Exercises with the muscles they target, muscles, and fitness calculators (BMR, TDEE, BMI, IBW).
For agents and code generators: the OpenAPI specification is at /openapi.json, and this reference as Markdown at /docs.md. AI assistants can call the API as an MCP server: see *AI assistants (MCP)* below.
Quickstart
- Create a free account and create a key in your dashboard: 1,000 requests a month, no credit card.
- Send the key in the
X-API-Keyheader:
curl "https://api.gymfit-api.com/v2/exercises/search?query=bench%20press&limit=3" \
-H "X-API-Key: YOUR_API_KEY"
- Each result has an
idand aslug. Read the whole exercise (muscles, steps, tips, variants, alternatives) withGET /v2/exercises/{id}, and draw its muscles withGET /v2/exercises/{id}/heatmap.
Keep the key on your server in production: a key shipped in a mobile app or a web page can be read by anyone who opens it. The code samples of the routes call the API directly, as for a prototype.
Authentication
Send your API key in the X-API-Key header. No key yet? Sign up for the free plan: 1,000 requests a month, no credit card. Create and manage your keys from your dashboard: a key is only shown once, when it is created.
Subscribed through RapidAPI? Keep calling the API through RapidAPI, with your RapidAPI key.
Search and filters
GET /v2/exercises/search reads what people type: typos (bech press), abbreviations (rdl, ohp) and muscles (quads, lower back).
- Filters combine:
?muscle=Pecs&equipment=Dumbbell,Cable&difficulty=Beginner. The values come fromGET /v2/equipment,/v2/categories,/v2/familiesand/v2/muscle-groups, each with how many exercises have it. - Autocomplete:
GET /v2/exercises/suggest?q=benchwhile the person types. It is free and does not count in the quota. - Filters with counts:
facets=trueadds how many matches fall under each category, difficulty, tier, equipment and muscle group. - Did you mean:
suggest=trueaddssuggestionwhen a word of the query looks misspelled. - Pages:
limit(up to 100) andoffset;totalis the number of matches. - One line per movement:
group=trueshows each movement once, with its variants counted under it.
Muscle heatmap
GET /v2/exercises/{id}/heatmap answers an SVG of the body, with the target muscles of the exercise and its secondary ones in color.
view:front,backorboth(default).- Colors in hex, the
#optional:target,secondary,base(the muscles the exercise does not work),bodyandoutline. For example?target=D4F53C&secondary=7A8C2E. - The heatmap of an exercise does not change: it comes with
Cache-Control: private, max-age=86400, keep it on your side instead of asking for it at each display. - It needs the key like every route: load it from your server, or fetch it with the key and show it (see the code samples of the route).
AI assistants (MCP)
GymFit is also an MCP server: Claude, ChatGPT, Claude Code, Cursor, VS Code or any MCP client searches the exercises, reads them and runs the calculators for you, on your plan.
Claude, ChatGPT and the apps that sign in with OAuth: add a custom connector with the URL https://mcp.gymfit-api.com/mcp, then sign in to GymFit and allow it. No key: the assistant uses your account, and you disconnect it from your dashboard.
Claude Code, Cursor and the clients that take a key:
- URL:
https://api.gymfit-api.com/mcp(Streamable HTTP) - Key: in the
X-API-Keyheader, or asAuthorization: Bearer YOUR_API_KEYfor clients that only take a token. A RapidAPI key does not work here: the MCP server takes a GymFit key.
Claude Code:
claude mcp add --transport http gymfit https://api.gymfit-api.com/mcp --header "X-API-Key: YOUR_API_KEY"
Cursor (.cursor/mcp.json), and the same entry in most clients (VS Code names the list servers and adds "type": "http"):
{
"mcpServers": {
"gymfit": {
"url": "https://api.gymfit-api.com/mcp",
"headers": { "X-API-Key": "YOUR_API_KEY" }
}
}
}
Keep the key out of shared files: Cursor reads ${env:GYMFIT_API_KEY} and Claude Code ${GYMFIT_API_KEY} in a .mcp.json.
The tools are read-only: search_exercises, get_exercise, find_alternatives, get_exercise_heatmap, search_muscles, get_muscle, list_filter_values, calculate_bmr, calculate_tdee, calculate_bmi, calculate_ideal_weight and get_usage. Each tool call counts as one request of your quota, like a call to the API; get_usage is free. A limit reached is answered to the assistant as an error it can read, with the time to wait or the way to upgrade.
Plans, quotas and rate limits
| Plan | Price / month | Requests / month | Beyond the quota | Requests / minute |
|---|---|---|---|---|
| Free | $0 | 1,000 | Refused | 30 |
| Starter | $9 | 20,000 | $0.002 per request | 60 |
| Pro | $29 | 100,000 | $0.001 per request | 300 |
Only successful (2xx) responses count in the quota. Every response carries:
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset(seconds until the minute window resets)X-Quota-Limit,X-Quota-UsedandX-Quota-Remainingfor the current billing periodX-Request-Id: mention it when you contact the support
When a limit is reached, the API answers 429 with a Retry-After header: wait that many seconds before sending again, and space out the retries rather than sending them at once. Your consumption is also available from GET /v2/usage, which is free and does not count in your quota.
Errors
Errors follow RFC 9457 (application/problem+json):
{
"type": "https://api.gymfit-api.com/docs#error-invalid_api_key",
"title": "Unauthorized",
"status": 401,
"code": "invalid_api_key",
"detail": "Missing or invalid API key. Get a free key at https://www.gymfit-api.com/signup",
"instance": "/v2/exercises/search",
"requestId": "9f3c2d1e-5b7a-4c8e-9d6f-1a2b3c4d5e6f"
}
Branch on code, which is stable: invalid_api_key, validation_failed (with an errors list), not_found, rate_limited, quota_exceeded, internal_error...
Versions
This reference documents v2, under /v2. v1 stays available under /v1 for existing integrations: the same routes, with the legacy image and images fields, and without the muscle heatmap.
Base URL: https://api.gymfit-api.com. OpenAPI specification: https://api.gymfit-api.com/openapi.json
Exercises
Search the 5,800 exercises, read one with its muscles, steps and variants, find its alternatives and draw its muscle heatmap.
Search exercises
GET /v2/exercises/search
Search the exercise catalog by what the user types, with filters and pagination.
What it understands:
- Words in any order, plural forms and spellings (
pushup,push-ups,curl biceps) - Typos (
bech press) - Abbreviations (
rdl,db curl,ohp) - Muscles (
quads,lower back,abs no equipment)
Ranking: exact name first, then the words in the name, then in the rest of the exercise, weighed by how often the exercise is done and its level.
Default results: the exercises people do. include=all adds the rare ones and the exercises of rehab, plyometrics, aerobics and warm-up; typing the name of a rare exercise finds it anyway.
Filters: body part, equipment (several values, comma separated), muscle (by id, name or common name, with muscleRole), muscle group, family, tier, type, category, difficulty, purpose, force, tracking type, laterality. ids fetches up to 50 exercises by id or slug. group=true shows each movement once, with its variants counted under it.
Sort: by relevance (default), popularity, name or difficulty.
Options: suggest=true adds suggestion, the query put right when a word looks misspelled. facets=true adds facets, the count of the matches per category, difficulty, tier, equipment and muscle group. Both are off by default.
Without a query, the most popular exercises come first.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
query | query | string | Search query to filter exercises by name (case-insensitive). |
bodyPart | query | string | Filter by target body part. Values: Legs, Back, Chest, Shoulders, Arms, Core, Neck. |
type | query | string | Filter by exercise type (compound or isolation). Values: Compound, Isolation. |
limit | query | number | Number of results to return. Default 20. |
offset | query | number | Number of results to skip for pagination. Default 0. |
equipment | query | array of string | Equipment the exercise uses. Several values, separated by commas, give the exercises that use any of them. Values: Barbell, Dumbbell, Machine, Bodyweight, Kettlebell, ResistanceBand, BattleRope, MedicineBall, BosuBall, PowerSled, SmithMachine, StabilityBall, TrapBar, Stepper, WheelRoller, Towel, Landmine, Cable, Bench, Box, EzBar, ParallelBars, PullUpBar, Rings, Rope, Sledgehammer, Stick, SuspensionTrainer, Weighted, Chair, FoamRoller, PreacherBench, Hurdle, Block. |
muscle | query | string | A muscle: its id, its name (Pectoralis major) or its common name (Pecs). |
muscleRole | query | string | With muscle: target for the exercises it is the main mover of (default), synergist for those it helps, any for both. Default target. Values: target, synergist, any. |
family | query | string | Family of movements (GET /v2/families): squat, bench-press... |
tier | query | string | How common the exercise is. Values: Standard, Variant, Niche. |
trackingType | query | string | How a set is logged: weight and reps, time, distance... Values: WeightReps, Reps, WeightedBodyweightReps, AssistedReps, Duration, WeightDuration, DistanceDuration, WeightDistance. |
laterality | query | string | How the sides work: both, one at a time, or taking turns. Values: Bilateral, Unilateral, Alternating. |
ids | query | string | Exercises to fetch at once: up to 50 ids or slugs, separated by commas (bench-press-barbell,squat-barbell). The rare exercises are included. |
sort | query | string | Order of the results. relevance is for a text search, the others sort the matches. Default relevance. Values: relevance, popularity, name, difficulty. |
category | query | string | Kind of exercise. Values: Strength, Weightlifting, Plyometrics, Cardio, Stretching, Mobility, Yoga. |
difficulty | query | string | How hard the exercise is. Values: Beginner, Intermediate, Advanced. |
muscleGroup | query | string | Muscle group the exercise works the most (GET /v2/muscle-groups), e.g. Quadriceps. |
purpose | query | string | Purpose of the exercise: rehab, yoga, plyometrics... Values: Strength, Calisthenics, Weightlifting, Strongman, Plyometrics, Cardio, Aerobics, Stretching, Mobility, Yoga, Pilates, Rehab, WarmUp. |
force | query | string | Push, pull or static. Values: Push, Pull, Static. |
include | query | string | default shows the exercises people do; all adds the rare ones and the exercises of rehab, plyometrics, aerobics and warm-up. Default default. Values: default, all. |
group | query | boolean | Shows each movement once, with its variants counted under it. Default false. |
suggest | query | boolean | Adds suggestion to the answer when a word of the query looks misspelled: the query put right, for a "Did you mean" line. Default false. |
facets | query | boolean | Adds facets to the answer: how many of the matches fall under each category, difficulty, tier, equipment and muscle group, to build filters. Default false. |
Example request
curl "https://api.gymfit-api.com/v2/exercises/search?query=bench%20press&limit=20&offset=0" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Exercises matching the search criteria400: Invalid search parameters
Example response
{
"results": [
{
"id": "c2b6fccf-2c2c-43e1-aca3-a3cb73caa78b",
"name": "Bench Press (Barbell)",
"bodyPart": "Chest",
"slug": "bench-press-barbell",
"equipment": "Barbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 100,
"variantCount": 26
},
{
"id": "3f05cb6b-dfe4-4aaa-9e45-2cbb79ffbf20",
"name": "Bench Press (Dumbbell)",
"bodyPart": "Chest",
"slug": "bench-press-dumbbell",
"equipment": "Dumbbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 90,
"variantCount": 22
},
{
"id": "9f14802d-441a-42b4-bd23-79b1e2c89d0e",
"name": "Bench Press (Smith Machine)",
"bodyPart": "Chest",
"slug": "bench-press-smith-machine",
"equipment": "SmithMachine",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 62,
"variantCount": 7
},
{
"id": "d2204c30-e837-4fe8-88ed-843d424fb036",
"name": "Bench Press (Band)",
"bodyPart": "Chest",
"slug": "bench-press-band",
"equipment": "ResistanceBand",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Variant",
"popularity": 30,
"variantCount": 2
},
{
"id": "b0884130-ccad-466f-b591-8ab041e07098",
"name": "Seated Shoulder Press (Dumbbell)",
"bodyPart": "Shoulders",
"slug": "seated-shoulder-press-dumbbell",
"equipment": "Dumbbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Shoulders"
],
"tier": "Standard",
"popularity": 88,
"variantCount": 7
}
],
"total": 20,
"count": 20,
"facets": {
"category": [
{
"value": "Strength",
"count": 102
}
],
"difficulty": [
{
"value": "Intermediate",
"count": 72
},
{
"value": "Beginner",
"count": 27
},
{
"value": "Advanced",
"count": 3
}
],
"tier": [
{
"value": "Niche",
"count": 52
},
{
"value": "Variant",
"count": 35
},
{
"value": "Standard",
"count": 15
}
],
"equipment": [
{
"value": "Bench",
"count": 88
},
{
"value": "Barbell",
"count": 32
},
{
"value": "Dumbbell",
"count": 32
},
{
"value": "Kettlebell",
"count": 9
},
{
"value": "SmithMachine",
"count": 9
}
],
"muscleGroup": [
{
"value": "Chest",
"count": 84
},
{
"value": "Shoulders",
"count": 28
},
{
"value": "Triceps",
"count": 27
},
{
"value": "Calves",
"count": 1
},
{
"value": "Trapezius",
"count": 1
}
]
}
}
A real answer, its lists cut to 5 items.
TypeScript
type ExerciseSummary = {
id: string
slug: string | null
name: string
equipment?: string
difficulty?: string | null
primaryGroups?: string[]
}
type SearchResponse = {
total: number
count: number
results: ExerciseSummary[]
}
export async function searchExercises(query: string, limit = 20): Promise<SearchResponse> {
const url = new URL('https://api.gymfit-api.com/v2/exercises/search')
url.search = new URLSearchParams({ query, limit: String(limit) }).toString()
const response = await fetch(url, {
headers: { 'X-API-Key': process.env.GYMFIT_API_KEY ?? '' }
})
if (!response.ok) {
const problem = await response.json()
throw new Error(`${problem.code}: ${problem.detail}`)
}
return response.json()
}
Swift
import Foundation
struct ExerciseSummary: Decodable {
let id: String
let slug: String?
let name: String
let equipment: String?
let difficulty: String?
let primaryGroups: [String]?
}
struct SearchResponse: Decodable {
let total: Int
let count: Int
let results: [ExerciseSummary]
}
let apiKey = "YOUR_API_KEY"
func searchExercises(_ query: String, limit: Int = 20) async throws -> SearchResponse {
var components = URLComponents(string: "https://api.gymfit-api.com/v2/exercises/search")!
components.queryItems = [
URLQueryItem(name: "query", value: query),
URLQueryItem(name: "limit", value: String(limit))
]
var request = URLRequest(url: components.url!)
request.setValue(apiKey, forHTTPHeaderField: "X-API-Key")
let (data, response) = try await URLSession.shared.data(for: request)
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(SearchResponse.self, from: data)
}
Kotlin
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
@Serializable
data class ExerciseSummary(
val id: String,
val slug: String? = null,
val name: String,
val equipment: String? = null,
val difficulty: String? = null,
val primaryGroups: List<String> = emptyList()
)
@Serializable
data class SearchResponse(val total: Int, val count: Int, val results: List<ExerciseSummary>)
private val client = OkHttpClient()
private val json = Json { ignoreUnknownKeys = true }
// Blocking: call it from a coroutine on Dispatchers.IO
fun searchExercises(query: String, limit: Int = 20): SearchResponse {
val url = "https://api.gymfit-api.com/v2/exercises/search".toHttpUrl().newBuilder()
.addQueryParameter("query", query)
.addQueryParameter("limit", limit.toString())
.build()
val request = Request.Builder()
.url(url)
.header("X-API-Key", BuildConfig.GYMFIT_API_KEY)
.build()
client.newCall(request).execute().use { response ->
check(response.isSuccessful) { "GymFit API: ${response.code}" }
return json.decodeFromString(response.body!!.string())
}
}
Dart (Flutter)
import 'dart:convert';
import 'package:http/http.dart' as http;
const apiKey = String.fromEnvironment('GYMFIT_API_KEY');
class ExerciseSummary {
ExerciseSummary({
required this.id,
required this.name,
this.slug,
this.equipment,
this.primaryGroups = const [],
});
factory ExerciseSummary.fromJson(Map<String, dynamic> json) => ExerciseSummary(
id: json['id'] as String,
name: json['name'] as String,
slug: json['slug'] as String?,
equipment: json['equipment'] as String?,
primaryGroups: (json['primaryGroups'] as List<dynamic>? ?? []).cast<String>(),
);
final String id;
final String name;
final String? slug;
final String? equipment;
final List<String> primaryGroups;
}
Future<List<ExerciseSummary>> searchExercises(String query, {int limit = 20}) async {
final uri = Uri.https('api.gymfit-api.com', '/v2/exercises/search', {
'query': query,
'limit': '$limit',
});
final response = await http.get(uri, headers: {'X-API-Key': apiKey});
if (response.statusCode != 200) {
throw Exception('GymFit API: ${response.statusCode} ${response.body}');
}
final body = jsonDecode(response.body) as Map<String, dynamic>;
return (body['results'] as List<dynamic>)
.map((item) => ExerciseSummary.fromJson(item as Map<String, dynamic>))
.toList();
}
Suggest exercises while typing
GET /v2/exercises/suggest
Exercises to offer under a search box while a person types: what is typed so far (two characters at least) gives the most popular exercises whose name or text starts or holds it.
Not billable: a search box calls this on every key. It counts in the rate limit but never in the monthly quota; a click on a suggestion is a billable GET /v2/exercises/{id}.
For the full result page, use GET /v2/exercises/search.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
q | query | string | The beginning of what is typed, two characters at least. Required. |
limit | query | number | Number of suggestions. Default 8. |
Example request
curl "https://api.gymfit-api.com/v2/exercises/suggest?q=bench%20pr" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Suggestions, the most popular first400: Less than two characters, or invalid parameters
Example response
{
"results": [
{
"id": "c2b6fccf-2c2c-43e1-aca3-a3cb73caa78b",
"slug": "bench-press-barbell",
"name": "Bench Press (Barbell)",
"equipment": "Barbell",
"category": "Strength"
},
{
"id": "3f05cb6b-dfe4-4aaa-9e45-2cbb79ffbf20",
"slug": "bench-press-dumbbell",
"name": "Bench Press (Dumbbell)",
"equipment": "Dumbbell",
"category": "Strength"
},
{
"id": "a1281637-139d-4864-903b-67d62037c16e",
"slug": "incline-bench-press-barbell",
"name": "Incline Bench Press (Barbell)",
"equipment": "Barbell",
"category": "Strength"
},
{
"id": "e48f6911-2a0d-45b5-b854-61aca0570173",
"slug": "incline-bench-press-dumbbell",
"name": "Incline Bench Press (Dumbbell)",
"equipment": "Dumbbell",
"category": "Strength"
},
{
"id": "8a764a28-b2d8-496e-9d08-fa352280b178",
"slug": "close-grip-bench-press-barbell",
"name": "Close Grip Bench Press (Barbell)",
"equipment": "Barbell",
"category": "Strength"
}
],
"count": 8
}
A real answer, its lists cut to 5 items.
Get exercise details
GET /v2/exercises/{id}
Retrieve comprehensive information about a specific exercise.
Includes:
- Complete exercise metadata (name, equipment, target body part)
- Muscle engagement details (target and synergist muscles)
- Step-by-step instructions
- Exercise variations
The exercise is found by its id or its slug (bench-press-barbell). The muscles it works can be drawn with GET /v2/exercises/{id}/heatmap.
Use cases:
- Display exercise details in workout builder
- Show proper form and technique
- Suggest exercise variations
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | Id (UUID) or slug of the exercise. Required. |
Example request
curl "https://api.gymfit-api.com/v2/exercises/bench-press-barbell" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Detailed exercise information400: Invalid id or slug404: Exercise not found
Example response
{
"id": "c2b6fccf-2c2c-43e1-aca3-a3cb73caa78b",
"name": "Bench Press (Barbell)",
"slug": "bench-press-barbell",
"bodyPart": "Chest",
"equipment": "Barbell",
"type": "Compound",
"description": "The classic flat-bench press with a barbell, a staple for pressing strength. It works the chest, the front delts and the triceps.",
"difficulty": "Intermediate",
"category": "Strength",
"force": "Push",
"trackingType": "WeightReps",
"laterality": "Bilateral",
"tier": "Standard",
"popularity": 100,
"purposes": [
"Strength"
],
"tips": [
"Keep your shoulder blades pulled together and your feet planted throughout.",
"Press the bar back in a slight arc so it finishes over your shoulders."
],
"mistakes": [
"Bouncing the bar off the chest.",
"Lifting the hips off the bench to push the bar up.",
"Flaring the elbows straight out to the sides."
],
"aliases": [
"Weighted Bench Press (Barbell)"
],
"primaryGroups": [
"Chest"
],
"secondaryGroups": [
"Shoulders",
"Triceps"
],
"family": {
"id": "bench-press",
"label": "Bench press"
},
"equipments": [
{
"equipment": "Barbell",
"main": true
},
{
"equipment": "Bench",
"main": false
}
],
"targetMuscles": [
{
"id": "ffd76ee8-7633-4062-9c91-9092d637567a",
"name": "Pectoralis major",
"commonName": "Pecs",
"bodyPart": "Chest",
"group": "Chest"
}
],
"secondaryMuscles": [
{
"id": "d0f075f6-831c-43b9-9749-15e1b74987be",
"name": "Deltoid",
"commonName": "Delts",
"bodyPart": "Shoulders",
"group": "Shoulders"
},
{
"id": "dec5954e-80b5-493b-8911-a73ef54d96ee",
"name": "Triceps brachii",
"commonName": "Triceps",
"bodyPart": "Arms",
"group": "Triceps"
}
],
"instructions": [
{
"order": 1,
"description": "Lie on a flat bench with your eyes under the bar, feet flat on the floor and shoulder blades pulled together."
},
{
"order": 2,
"description": "Grip the bar a little wider than shoulder width, palms facing away, and unrack it over your chest with straight arms."
},
{
"order": 3,
"description": "Inhale and lower the bar under control to your mid-chest, elbows at about 45 degrees from your body."
},
{
"order": 4,
"description": "Pause briefly with the bar just touching your chest."
},
{
"order": 5,
"description": "Exhale and press the bar back up until your arms are straight."
}
],
"base": null,
"variations": [
{
"id": "a1281637-139d-4864-903b-67d62037c16e",
"name": "Incline Bench Press (Barbell)",
"bodyPart": "Chest",
"slug": "incline-bench-press-barbell",
"equipment": "Barbell",
"difficulty": "Intermediate",
"tier": "Standard",
"popularity": 88
},
{
"id": "8a764a28-b2d8-496e-9d08-fa352280b178",
"name": "Close Grip Bench Press (Barbell)",
"bodyPart": "Arms",
"slug": "close-grip-bench-press-barbell",
"equipment": "Barbell",
"difficulty": "Intermediate",
"tier": "Standard",
"popularity": 72
},
{
"id": "c3eece11-94f5-49fc-9789-a03eb217e34b",
"name": "Decline Bench Press (Barbell)",
"bodyPart": "Chest",
"slug": "decline-bench-press-barbell",
"equipment": "Barbell",
"difficulty": "Intermediate",
"tier": "Standard",
"popularity": 65
},
{
"id": "864c3482-fe80-4740-85c7-1c3fdfeba898",
"name": "Pause Bench Press (Barbell)",
"bodyPart": "Chest",
"slug": "pause-bench-press-barbell",
"equipment": "Barbell",
"difficulty": "Intermediate",
"tier": "Variant",
"popularity": 45
},
{
"id": "859bb806-b4d8-4200-aea1-f9758e412ed1",
"name": "Floor Chest Press (Barbell)",
"bodyPart": "Chest",
"slug": "floor-chest-press-barbell",
"equipment": "Barbell",
"difficulty": "Intermediate",
"tier": "Variant",
"popularity": 40
}
],
"alternatives": [
{
"id": "3f05cb6b-dfe4-4aaa-9e45-2cbb79ffbf20",
"name": "Bench Press (Dumbbell)",
"bodyPart": "Chest",
"slug": "bench-press-dumbbell",
"equipment": "Dumbbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 90,
"score": 0.96,
"reasons": [
"same-target-muscles",
"same-movement",
"other-equipment"
]
},
{
"id": "af3d6a16-23a2-42be-a486-fc2c00e66098",
"name": "Chest Press (Machine)",
"bodyPart": "Chest",
"slug": "chest-press-machine",
"equipment": "Machine",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 85,
"score": 0.93,
"reasons": [
"same-target-muscles",
"same-movement",
"other-equipment",
"easier"
]
},
{
"id": "dda1be2c-e910-4115-a864-0864b119c179",
"name": "Push-up",
"bodyPart": "Chest",
"slug": "push-up",
"equipment": "Bodyweight",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 97,
"score": 0.93,
"reasons": [
"same-target-muscles",
"no-equipment",
"easier"
]
},
{
"id": "84177edb-a08d-4756-8be7-2bf6515c91e4",
"name": "Chest Dip",
"bodyPart": "Chest",
"slug": "chest-dip",
"equipment": "Bodyweight",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest",
"Triceps"
],
"tier": "Standard",
"popularity": 85,
"score": 0.86,
"reasons": [
"similar-muscles",
"no-equipment"
]
},
{
"id": "918ceabc-3449-4184-b4f9-c5bcf85e0a14",
"name": "Chest Press (Suspension)",
"bodyPart": "Chest",
"slug": "chest-press-suspension",
"equipment": "SuspensionTrainer",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 55,
"score": 0.75,
"reasons": [
"same-target-muscles",
"other-equipment"
]
}
],
"easier": [
{
"id": "af3d6a16-23a2-42be-a486-fc2c00e66098",
"name": "Chest Press (Machine)",
"bodyPart": "Chest",
"slug": "chest-press-machine",
"equipment": "Machine",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 85,
"step": 10
},
{
"id": "77714948-0022-410c-a18a-53cd85224fa7",
"name": "Incline Chest Press (Machine)",
"bodyPart": "Chest",
"slug": "incline-chest-press-machine",
"equipment": "Machine",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest",
"Shoulders"
],
"tier": "Standard",
"popularity": 65,
"step": 10
},
{
"id": "ca6c6d78-58ec-4984-b02d-68d784acc8a5",
"name": "Incline Bench Press (Smith Machine)",
"bodyPart": "Chest",
"slug": "incline-bench-press-smith-machine",
"equipment": "SmithMachine",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest",
"Shoulders"
],
"tier": "Standard",
"popularity": 65,
"step": 10
}
],
"harder": []
}
A real answer, its lists cut to 5 items.
TypeScript
type Muscle = {
id: string
name: string
commonName: string | null
group: string | null
}
type Exercise = {
id: string
slug: string | null
name: string
difficulty?: string | null
instructions: { order: number; description: string }[]
targetMuscles: Muscle[]
secondaryMuscles: Muscle[]
tips?: string[]
}
/** null when the exercise does not exist */
export async function getExercise(idOrSlug: string): Promise<Exercise | null> {
const response = await fetch(
`https://api.gymfit-api.com/v2/exercises/${encodeURIComponent(idOrSlug)}`,
{ headers: { 'X-API-Key': process.env.GYMFIT_API_KEY ?? '' } }
)
if (response.status === 404) {
return null
}
if (!response.ok) {
throw new Error(`GymFit API: ${response.status}`)
}
return response.json()
}
Swift
import Foundation
struct Muscle: Decodable {
let id: String
let name: String
let commonName: String?
let group: String?
}
struct Step: Decodable {
let order: Int
let description: String
}
struct Exercise: Decodable {
let id: String
let slug: String?
let name: String
let difficulty: String?
let instructions: [Step]
let targetMuscles: [Muscle]
let secondaryMuscles: [Muscle]
let tips: [String]?
}
/// nil when the exercise does not exist (apiKey: see the search)
func getExercise(_ idOrSlug: String) async throws -> Exercise? {
let url = URL(string: "https://api.gymfit-api.com/v2/exercises/\(idOrSlug)")!
var request = URLRequest(url: url)
request.setValue(apiKey, forHTTPHeaderField: "X-API-Key")
let (data, response) = try await URLSession.shared.data(for: request)
switch (response as? HTTPURLResponse)?.statusCode {
case 200: return try JSONDecoder().decode(Exercise.self, from: data)
case 404: return nil
default: throw URLError(.badServerResponse)
}
}
Kotlin
import kotlinx.serialization.Serializable
@Serializable
data class Muscle(
val id: String,
val name: String,
val commonName: String? = null,
val group: String? = null
)
@Serializable
data class Step(val order: Int, val description: String)
@Serializable
data class Exercise(
val id: String,
val slug: String? = null,
val name: String,
val difficulty: String? = null,
val instructions: List<Step>,
val targetMuscles: List<Muscle>,
val secondaryMuscles: List<Muscle>,
val tips: List<String> = emptyList()
)
// null when the exercise does not exist. client and json: see the search.
// Blocking: call it from a coroutine on Dispatchers.IO
fun getExercise(idOrSlug: String): Exercise? {
val request = Request.Builder()
.url("https://api.gymfit-api.com/v2/exercises/$idOrSlug")
.header("X-API-Key", BuildConfig.GYMFIT_API_KEY)
.build()
client.newCall(request).execute().use { response ->
if (response.code == 404) return null
check(response.isSuccessful) { "GymFit API: ${response.code}" }
return json.decodeFromString(response.body!!.string())
}
}
Dart (Flutter)
import 'dart:convert';
import 'package:http/http.dart' as http;
class Muscle {
Muscle({required this.name, this.commonName});
factory Muscle.fromJson(Map<String, dynamic> json) =>
Muscle(name: json['name'] as String, commonName: json['commonName'] as String?);
final String name;
final String? commonName;
}
class Exercise {
Exercise({required this.name, required this.steps, required this.targetMuscles});
factory Exercise.fromJson(Map<String, dynamic> json) => Exercise(
name: json['name'] as String,
steps: [
for (final step in json['instructions'] as List<dynamic>)
(step as Map<String, dynamic>)['description'] as String,
],
targetMuscles: [
for (final muscle in json['targetMuscles'] as List<dynamic>)
Muscle.fromJson(muscle as Map<String, dynamic>),
],
);
final String name;
final List<String> steps;
final List<Muscle> targetMuscles;
}
/// null when the exercise does not exist (apiKey: see the search)
Future<Exercise?> getExercise(String idOrSlug) async {
final uri = Uri.https('api.gymfit-api.com', '/v2/exercises/$idOrSlug');
final response = await http.get(uri, headers: {'X-API-Key': apiKey});
if (response.statusCode == 404) return null;
if (response.statusCode != 200) {
throw Exception('GymFit API: ${response.statusCode}');
}
return Exercise.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
}
Get alternative exercises
GET /v2/exercises/{id}/alternatives
Find alternative exercises based on similarity scoring.
Similarity Algorithm:
- Muscle engagement similarity (70% weight): Uses Jaccard index to compare target and synergist muscles
- Name similarity (30% weight): Fuzzy string matching
- Minimum similarity threshold: 0.7 (70%)
Results are sorted by similarity score (highest first)
Use cases:
- Suggest alternatives when equipment is unavailable
- Provide exercise variety for progressive overload
- Help with injury adaptations
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | Id (UUID) or slug of the source exercise. Required. |
limit | query | number | Maximum number of alternatives to return. |
Example request
curl "https://api.gymfit-api.com/v2/exercises/bench-press-barbell/alternatives?limit=10" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: List of alternative exercises404: Source exercise not found
Example response
[
{
"id": "3f05cb6b-dfe4-4aaa-9e45-2cbb79ffbf20",
"name": "Bench Press (Dumbbell)",
"bodyPart": "Chest",
"slug": "bench-press-dumbbell",
"equipment": "Dumbbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 90,
"score": 0.96,
"reasons": [
"same-target-muscles",
"same-movement",
"other-equipment"
]
},
{
"id": "af3d6a16-23a2-42be-a486-fc2c00e66098",
"name": "Chest Press (Machine)",
"bodyPart": "Chest",
"slug": "chest-press-machine",
"equipment": "Machine",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 85,
"score": 0.93,
"reasons": [
"same-target-muscles",
"same-movement",
"other-equipment",
"easier"
]
},
{
"id": "dda1be2c-e910-4115-a864-0864b119c179",
"name": "Push-up",
"bodyPart": "Chest",
"slug": "push-up",
"equipment": "Bodyweight",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 97,
"score": 0.93,
"reasons": [
"same-target-muscles",
"no-equipment",
"easier"
]
},
{
"id": "84177edb-a08d-4756-8be7-2bf6515c91e4",
"name": "Chest Dip",
"bodyPart": "Chest",
"slug": "chest-dip",
"equipment": "Bodyweight",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest",
"Triceps"
],
"tier": "Standard",
"popularity": 85,
"score": 0.86,
"reasons": [
"similar-muscles",
"no-equipment"
]
},
{
"id": "918ceabc-3449-4184-b4f9-c5bcf85e0a14",
"name": "Chest Press (Suspension)",
"bodyPart": "Chest",
"slug": "chest-press-suspension",
"equipment": "SuspensionTrainer",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 55,
"score": 0.75,
"reasons": [
"same-target-muscles",
"other-equipment"
]
}
]
A real answer, its lists cut to 5 items.
Get the muscle heatmap of an exercise
GET /v2/exercises/{id}/heatmap
SVG image of the body, front and back, with the target and secondary muscles of the exercise highlighted. Colors can be set to match your app.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | Id (UUID) or slug of the exercise. Required. |
view | query | string | Side of the body to draw. Default both. Values: front, back, both. |
target | query | string | Color of the target muscles (hex, the # is optional). |
secondary | query | string | Color of the secondary muscles (hex, the # is optional). |
base | query | string | Color of the muscles the exercise does not work (hex, the # is optional). Defaults to the colors of the drawing. |
body | query | string | Color of the body and of the lines between the muscles (hex, the # is optional). Defaults to the colors of the drawing. |
outline | query | string | Color of the contour of the body (hex, the # is optional). Defaults to the colors of the drawing. |
Example request
curl "https://api.gymfit-api.com/v2/exercises/bench-press-barbell/heatmap?target=E53935&secondary=F6A26B&base=D9D9D9&body=2B2B30&outline=45454D" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: The heatmap, as an SVG image400: Invalid id, slug, view or color404: Exercise not found
The response is an SVG image (image/svg+xml).
TypeScript
// The heatmap is an SVG that needs the key: fetch it, then show it as an image
export async function heatmapUrl(idOrSlug: string, view = 'both'): Promise<string> {
const response = await fetch(
`https://api.gymfit-api.com/v2/exercises/${encodeURIComponent(idOrSlug)}/heatmap?view=${view}`,
{ headers: { 'X-API-Key': process.env.GYMFIT_API_KEY ?? '' } }
)
if (!response.ok) {
throw new Error(`GymFit API: ${response.status}`)
}
return URL.createObjectURL(await response.blob())
}
// <img src={await heatmapUrl('bench-press-barbell')} alt="Muscles worked by the bench press" />
Swift
import WebKit
// UIImage does not read SVG: a WKWebView draws it (apiKey: see the search)
@MainActor
func showHeatmap(of idOrSlug: String, in webView: WKWebView) async throws {
let url = URL(string: "https://api.gymfit-api.com/v2/exercises/\(idOrSlug)/heatmap")!
var request = URLRequest(url: url)
request.setValue(apiKey, forHTTPHeaderField: "X-API-Key")
let (data, _) = try await URLSession.shared.data(for: request)
let svg = String(decoding: data, as: UTF8.self)
webView.isOpaque = false
webView.loadHTMLString(
"<style>body{margin:0}svg{width:100%;height:auto}</style>\(svg)",
baseURL: nil
)
}
Kotlin (Compose)
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import coil.compose.AsyncImage
import coil.decode.SvgDecoder
import coil.request.ImageRequest
// Coil 2 with its SVG decoder: io.coil-kt:coil-compose and io.coil-kt:coil-svg
@Composable
fun Heatmap(idOrSlug: String) {
val request = ImageRequest.Builder(LocalContext.current)
.data("https://api.gymfit-api.com/v2/exercises/$idOrSlug/heatmap")
.addHeader("X-API-Key", BuildConfig.GYMFIT_API_KEY)
.decoderFactory(SvgDecoder.Factory())
.build()
AsyncImage(model = request, contentDescription = "Muscles worked")
}
Dart (Flutter)
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart';
// flutter_svg draws the SVG and sends the key (apiKey: see the search)
Widget heatmap(String idOrSlug) => SvgPicture.network(
'https://api.gymfit-api.com/v2/exercises/$idOrSlug/heatmap',
headers: const {'X-API-Key': apiKey},
semanticsLabel: 'Muscles worked',
);
Muscles
The muscles with their common names and groups, and the exercises that work them.
Search muscles
GET /v2/muscles/search
Search the muscles of the catalog.
Features:
- Text search on the anatomical name, the common name (
Pecs,Quads) and the aliases (six pack,lower back) - Filter by body part and by group (
GET /v2/muscle-groups) - Paginated results, ordered by name
Use cases:
- Find a muscle by what people call it
- List the muscles of a group
- Fill a muscle picker
Parameters
| Name | In | Type | Description |
|---|---|---|---|
query | query | string | Search query to filter muscles by name (case-insensitive). |
bodyPart | query | string | Filter by body part. Values: Legs, Back, Chest, Shoulders, Arms, Core, Neck. |
limit | query | number | Number of results to return. Default 50. |
offset | query | number | Number of results to skip. Default 0. |
group | query | string | Group of muscles (GET /v2/muscle-groups), e.g. Hamstrings. |
Example request
curl "https://api.gymfit-api.com/v2/muscles/search?query=pectoralis" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Muscles matching criteria
Example response
{
"results": [
{
"id": "ffd76ee8-7633-4062-9c91-9092d637567a",
"name": "Pectoralis major",
"commonName": "Pecs",
"bodyPart": "Chest",
"group": "Chest"
},
{
"id": "6be0d058-5813-49b8-aa58-634171adbee0",
"name": "Pectoralis minor",
"commonName": "Pectoralis minor",
"bodyPart": "Chest",
"group": "Chest"
}
],
"total": 2,
"count": 2
}
Get muscle details
GET /v2/muscles/{id}
Retrieve a muscle with everything the catalog knows of it.
Includes:
- Anatomical name, common name and aliases
- Body part and group
- Heads of the muscle
The exercises that work it are listed by GET /v2/muscles/{id}/exercises.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | Muscle UUID. Required. |
Example request
curl "https://api.gymfit-api.com/v2/muscles/ffd76ee8-7633-4062-9c91-9092d637567a" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Detailed muscle information404: Muscle not found
Example response
{
"id": "ffd76ee8-7633-4062-9c91-9092d637567a",
"name": "Pectoralis major",
"commonName": "Pecs",
"bodyPart": "Chest",
"group": "Chest",
"aliases": [
"chest",
"pectorals"
],
"heads": [
"Clavicular (Upper)",
"Sternal (Lower)"
]
}
List the muscle groups
GET /v2/muscle-groups
The muscle groups (Chest, Lats, Hamstrings...), each with its muscles and their heads, in one call.
A group name is what muscleGroup takes on GET /v2/exercises/search. The result is the same for every request: keep it.
Example request
curl "https://api.gymfit-api.com/v2/muscle-groups" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: The groups with their muscles
Example response
[
{
"id": "56cd4301-0124-4c75-bbe9-6a04ccd338e3",
"name": "Abs",
"aliases": [
"abdominals",
"six pack",
"core"
],
"muscles": [
{
"id": "7d561eae-b72d-48e8-9e5d-a8c82c1fc753",
"name": "Diaphragm",
"commonName": "Diaphragm",
"heads": []
},
{
"id": "b11a737a-d371-4f43-97b3-c3c4bd47cd09",
"name": "Rectus abdominis",
"commonName": "Abs",
"heads": [
"Lower",
"Middle",
"Superior"
]
},
{
"id": "45b8f8b5-cff3-4cec-8d1f-52f19ff9af14",
"name": "Transverse abdominis",
"commonName": "Deep abs",
"heads": []
}
]
},
{
"id": "b4798677-fd22-48d4-9662-94daf36cd7f3",
"name": "Adductors",
"aliases": [
"inner thigh",
"groin"
],
"muscles": [
{
"id": "22456832-adb8-4eef-bdf6-03c03ede89fa",
"name": "Adductor brevis",
"commonName": "Adductor brevis",
"heads": []
},
{
"id": "df03e634-d5d7-4d61-bc23-15b5e2f708bb",
"name": "Adductor longus",
"commonName": "Adductor longus",
"heads": []
},
{
"id": "af4088f9-a989-4f23-9cd9-49558602c761",
"name": "Adductor magnus",
"commonName": "Adductor magnus",
"heads": [
"Adductor (Anterior)",
"Hamstring (Posterior)"
]
},
{
"id": "771f5070-1d6a-435d-8cff-e8bb562d4441",
"name": "Gracilis",
"commonName": "Gracilis",
"heads": []
},
{
"id": "7d2cf221-96bb-4c38-9471-71f6401df991",
"name": "Pectineus",
"commonName": "Pectineus",
"heads": []
}
]
},
{
"id": "fe03d381-5c6a-4229-8faa-f79bb3e0e1b7",
"name": "Biceps",
"aliases": [
"bis",
"guns"
],
"muscles": [
{
"id": "6ad37840-db50-431c-80df-171a031fbdec",
"name": "Biceps brachii",
"commonName": "Biceps",
"heads": [
"Long",
"Short"
]
},
{
"id": "98b3cd59-8b5c-4fcf-9724-b9874e4b93c1",
"name": "Brachialis",
"commonName": "Brachialis",
"heads": []
}
]
},
{
"id": "62ccea28-6d01-42ea-a66f-04fa153119ef",
"name": "Calves",
"aliases": [
"calf"
],
"muscles": [
{
"id": "ac2bb610-6d0e-47eb-bb46-0f767196de7e",
"name": "Fibularis",
"commonName": "Peroneals",
"heads": []
},
{
"id": "5c8b7816-388c-4ccf-8251-b283fa7dbe77",
"name": "Gastrocnemius",
"commonName": "Calf",
"heads": [
"Lateral (Outer)",
"Medial (Inner)"
]
},
{
"id": "98180f1c-d623-4982-8955-8c93cff2c7f1",
"name": "Soleus",
"commonName": "Soleus",
"heads": []
}
]
},
{
"id": "7a45a47c-f008-42e3-977b-9529dcdcf6b9",
"name": "Chest",
"aliases": [
"pecs",
"pectorals"
],
"muscles": [
{
"id": "ffd76ee8-7633-4062-9c91-9092d637567a",
"name": "Pectoralis major",
"commonName": "Pecs",
"heads": [
"Clavicular (Upper)",
"Sternal (Lower)"
]
},
{
"id": "6be0d058-5813-49b8-aa58-634171adbee0",
"name": "Pectoralis minor",
"commonName": "Pectoralis minor",
"heads": []
}
]
}
]
A real answer, its lists cut to 5 items.
List the exercises of a muscle
GET /v2/muscles/{id}/exercises
The exercises that work a muscle, the most popular first.
By default the muscle is the main mover (muscleRole=target); synergist gives the exercises it only helps, any both.
The filters and the sort are those of GET /v2/exercises/search.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | Muscle UUID. Required. |
query | query | string | Search query to filter exercises by name (case-insensitive). |
type | query | string | Filter by exercise type (compound or isolation). Values: Compound, Isolation. |
limit | query | number | Number of results to return. Default 20. |
offset | query | number | Number of results to skip for pagination. Default 0. |
equipment | query | array of string | Equipment the exercise uses. Several values, separated by commas, give the exercises that use any of them. Values: Barbell, Dumbbell, Machine, Bodyweight, Kettlebell, ResistanceBand, BattleRope, MedicineBall, BosuBall, PowerSled, SmithMachine, StabilityBall, TrapBar, Stepper, WheelRoller, Towel, Landmine, Cable, Bench, Box, EzBar, ParallelBars, PullUpBar, Rings, Rope, Sledgehammer, Stick, SuspensionTrainer, Weighted, Chair, FoamRoller, PreacherBench, Hurdle, Block. |
muscleRole | query | string | With muscle: target for the exercises it is the main mover of (default), synergist for those it helps, any for both. Default target. Values: target, synergist, any. |
tier | query | string | How common the exercise is. Values: Standard, Variant, Niche. |
sort | query | string | Order of the results. relevance is for a text search, the others sort the matches. Default relevance. Values: relevance, popularity, name, difficulty. |
category | query | string | Kind of exercise. Values: Strength, Weightlifting, Plyometrics, Cardio, Stretching, Mobility, Yoga. |
difficulty | query | string | How hard the exercise is. Values: Beginner, Intermediate, Advanced. |
include | query | string | default shows the exercises people do; all adds the rare ones and the exercises of rehab, plyometrics, aerobics and warm-up. Default default. Values: default, all. |
Example request
curl "https://api.gymfit-api.com/v2/muscles/ffd76ee8-7633-4062-9c91-9092d637567a/exercises?query=bench%20press&limit=20&offset=0" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Exercises of the muscle404: Muscle not found
Example response
{
"results": [
{
"id": "c2b6fccf-2c2c-43e1-aca3-a3cb73caa78b",
"name": "Bench Press (Barbell)",
"bodyPart": "Chest",
"slug": "bench-press-barbell",
"equipment": "Barbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 100
},
{
"id": "3f05cb6b-dfe4-4aaa-9e45-2cbb79ffbf20",
"name": "Bench Press (Dumbbell)",
"bodyPart": "Chest",
"slug": "bench-press-dumbbell",
"equipment": "Dumbbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 90
},
{
"id": "9f14802d-441a-42b4-bd23-79b1e2c89d0e",
"name": "Bench Press (Smith Machine)",
"bodyPart": "Chest",
"slug": "bench-press-smith-machine",
"equipment": "SmithMachine",
"category": "Strength",
"difficulty": "Beginner",
"primaryGroups": [
"Chest"
],
"tier": "Standard",
"popularity": 62
},
{
"id": "a1281637-139d-4864-903b-67d62037c16e",
"name": "Incline Bench Press (Barbell)",
"bodyPart": "Chest",
"slug": "incline-bench-press-barbell",
"equipment": "Barbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest",
"Shoulders"
],
"tier": "Standard",
"popularity": 88
},
{
"id": "e48f6911-2a0d-45b5-b854-61aca0570173",
"name": "Incline Bench Press (Dumbbell)",
"bodyPart": "Chest",
"slug": "incline-bench-press-dumbbell",
"equipment": "Dumbbell",
"category": "Strength",
"difficulty": "Intermediate",
"primaryGroups": [
"Chest",
"Shoulders"
],
"tier": "Standard",
"popularity": 88
}
],
"total": 84,
"count": 20
}
A real answer, its lists cut to 5 items.
Reference
The values the search filters take, with how many exercises have each.
List the equipment
GET /v2/equipment
Every value of equipment, with the number of exercises that use it. Lists change only when the catalog does: keep them.
Example request
curl "https://api.gymfit-api.com/v2/equipment" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200:
Example response
[
{
"value": "Barbell",
"exercises": 171,
"total": 367
},
{
"value": "Dumbbell",
"exercises": 239,
"total": 644
},
{
"value": "Machine",
"exercises": 130,
"total": 261
},
{
"value": "Bodyweight",
"exercises": 861,
"total": 2988
},
{
"value": "Kettlebell",
"exercises": 81,
"total": 213
}
]
A real answer, its lists cut to 5 items.
List the categories
GET /v2/categories
Every value of category (strength, cardio, stretching, mobility, yoga...), with the number of exercises.
Example request
curl "https://api.gymfit-api.com/v2/categories" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200:
Example response
[
{
"value": "Strength",
"exercises": 1356,
"total": 3972
},
{
"value": "Weightlifting",
"exercises": 27,
"total": 43
},
{
"value": "Plyometrics",
"exercises": 22,
"total": 190
},
{
"value": "Cardio",
"exercises": 85,
"total": 607
},
{
"value": "Stretching",
"exercises": 251,
"total": 581
}
]
A real answer, its lists cut to 5 items.
List the families of movements
GET /v2/families
The families (squat, bench-press, row...) an exercise belongs to, with the number of exercises. id is what family takes on the search.
Example request
curl "https://api.gymfit-api.com/v2/families" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200:
Example response
[
{
"id": "stretch-trunk",
"label": "Abdominal and side stretch",
"pattern": "stretch",
"exercises": 9,
"total": 44
},
{
"id": "core-activation",
"label": "Abdominal vacuum and draw-in",
"pattern": "core activation",
"exercises": 1,
"total": 2
},
{
"id": "stretch-adductors",
"label": "Adductor stretch",
"pattern": "stretch",
"exercises": 14,
"total": 33
},
{
"id": "agility-drill",
"label": "Agility drill",
"pattern": "agility",
"exercises": 11,
"total": 26
},
{
"id": "ankle-mobility",
"label": "Ankle and foot mobility",
"pattern": "ankle mobility",
"exercises": 7,
"total": 11
}
]
A real answer, its lists cut to 5 items.
What the catalog holds
GET /v2/meta
The size of the catalog and every value its enumerations take (difficulties, forces, tracking types, laterality, purposes, tiers, body parts, equipment, categories).
Example request
curl "https://api.gymfit-api.com/v2/meta" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200:
Example response
{
"exercises": {
"default": 1900,
"total": 5796
},
"muscles": 49,
"muscleGroups": 21,
"families": 136,
"values": {
"equipment": [
"Barbell",
"Dumbbell",
"Machine",
"Bodyweight",
"Kettlebell"
],
"categories": [
"Strength",
"Weightlifting",
"Plyometrics",
"Cardio",
"Stretching"
],
"difficulties": [
"Beginner",
"Intermediate",
"Advanced"
],
"forces": [
"Push",
"Pull",
"Static"
],
"types": [
"Compound",
"Isolation"
],
"trackingTypes": [
"WeightReps",
"Reps",
"WeightedBodyweightReps",
"AssistedReps",
"Duration"
],
"lateralities": [
"Bilateral",
"Unilateral",
"Alternating"
],
"purposes": [
"Strength",
"Calisthenics",
"Weightlifting",
"Strongman",
"Plyometrics"
],
"tiers": [
"Standard",
"Variant",
"Niche"
],
"bodyParts": [
"Legs",
"Back",
"Chest",
"Shoulders",
"Arms"
]
}
}
A real answer, its lists cut to 5 items.
Calculator
BMR, TDEE, BMI and ideal body weight.
Basal metabolic rate (BMR)
GET /v2/calculator/bmr
Calories burned at rest in a day, with the Mifflin-St Jeor equation. Rounded to the unit.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
height | query | number | Height in centimeters. Required. |
age | query | number | Age. Required. |
weight | query | number | Body weight in kilograms. Required. |
gender | query | string | Gender, which changes the constant of the equation. Required. Values: male, female. |
Example request
curl "https://api.gymfit-api.com/v2/calculator/bmr?height=180&age=25&weight=78&gender=male" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Successful BMR calculation
Example response
{
"result": 1785
}
Total daily energy expenditure (TDEE)
GET /v2/calculator/tdee
Calories burned in a day: the BMR times the factor of the activity level (sedentary 1.375, lightlyActive 1.56, active 1.64, veryActive 1.82). Rounded to the unit.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
height | query | number | Height in centimeters. Required. |
age | query | number | Age. Required. |
weight | query | number | Body weight in kilograms. Required. |
gender | query | string | Gender, which changes the constant of the equation. Required. Values: male, female. |
activityLevel | query | string | Level of physical activity. Required. Values: sedentary, lightlyActive, active, veryActive. |
Example request
curl "https://api.gymfit-api.com/v2/calculator/tdee?height=180&age=25&weight=78&gender=male&activityLevel=active" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Successful TDEE calculation
Example response
{
"result": 2927
}
Body mass index (BMI)
GET /v2/calculator/bmi
Weight in kilograms divided by the square of the height in meters. Rounded to one decimal.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
height | query | number | Height in centimeters. Required. |
weight | query | number | Body weight in kilograms. Required. |
Example request
curl "https://api.gymfit-api.com/v2/calculator/bmi?height=180&weight=78" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Successful BMI calculation
Example response
{
"result": 24.1
}
Ideal body weight (IBW)
GET /v2/calculator/ibw
Ideal weight in kilograms for a height, with the Devine formula. Rounded to one decimal.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
height | query | number | Height in centimeters. Required. |
Example request
curl "https://api.gymfit-api.com/v2/calculator/ibw?height=180" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200: Successful IBW calculation
Example response
{
"result": 75.1
}
Usage
Your consumption and what is left of your quota. Free, not counted in the quota.
Get your usage
GET /v2/usage
Requests and errors per day, month or endpoint (updated every 5 minutes). Defaults to the current month.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
from | query | string | First day (UTC), defaults to the start of the current month. |
to | query | string | Last day (UTC, included), defaults to today. |
Example request
curl "https://api.gymfit-api.com/v2/usage?from=2026-09-01&to=2026-09-30" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200:403: Only available with a key created in the dashboard
Example response
{
"from": "2026-09-01",
"to": "2026-09-28",
"groupBy": {},
"totals": {
"key": "2026-09-28",
"requests": 0,
"success": 0,
"errors": {
"invalidRequests": 0,
"authErrors": 0,
"notFound": 0,
"rateLimited": 0,
"otherClientErrors": 0,
"serverErrors": 0
},
"averageLatencyMs": 0
},
"data": [
{
"key": "2026-09-28",
"requests": 0,
"success": 0,
"errors": {
"invalidRequests": 0,
"authErrors": 0,
"notFound": 0,
"rateLimited": 0,
"otherClientErrors": 0,
"serverErrors": 0
},
"averageLatencyMs": 0
}
]
}
Get your quota
GET /v2/usage/current
Plan and quota of the current billing period, in real time.
Example request
curl "https://api.gymfit-api.com/v2/usage/current" \
-H "X-API-Key: YOUR_API_KEY"
Responses
200:403: Only available with a key created in the dashboard
Example response
{
"plan": "pro",
"quota": 0,
"used": 0,
"remaining": 0,
"overage": 0,
"hardLimit": false,
"overageCostUsd": 0,
"periodStart": "2026-10-13T00:00:00.000Z",
"periodEnd": "2026-10-13T00:00:00.000Z",
"status": "string",
"cancelAtPeriodEnd": false
}