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

  1. Create a free account and create a key in your dashboard: 1,000 requests a month, no credit card.
  2. Send the key in the X-API-Key header:
curl "https://api.gymfit-api.com/v2/exercises/search?query=bench%20press&limit=3" \
  -H "X-API-Key: YOUR_API_KEY"
  1. Each result has an id and a slug. Read the whole exercise (muscles, steps, tips, variants, alternatives) with GET /v2/exercises/{id}, and draw its muscles with GET /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).

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.

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:

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

PlanPrice / monthRequests / monthBeyond the quotaRequests / minute
Free$01,000Refused30
Starter$920,000$0.002 per request60
Pro$29100,000$0.001 per request300

Only successful (2xx) responses count in the quota. Every response carries:

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:

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

NameInTypeDescription
queryquerystringSearch query to filter exercises by name (case-insensitive).
bodyPartquerystringFilter by target body part. Values: Legs, Back, Chest, Shoulders, Arms, Core, Neck.
typequerystringFilter by exercise type (compound or isolation). Values: Compound, Isolation.
limitquerynumberNumber of results to return. Default 20.
offsetquerynumberNumber of results to skip for pagination. Default 0.
equipmentqueryarray of stringEquipment 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.
musclequerystringA muscle: its id, its name (Pectoralis major) or its common name (Pecs).
muscleRolequerystringWith 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.
familyquerystringFamily of movements (GET /v2/families): squat, bench-press...
tierquerystringHow common the exercise is. Values: Standard, Variant, Niche.
trackingTypequerystringHow a set is logged: weight and reps, time, distance... Values: WeightReps, Reps, WeightedBodyweightReps, AssistedReps, Duration, WeightDuration, DistanceDuration, WeightDistance.
lateralityquerystringHow the sides work: both, one at a time, or taking turns. Values: Bilateral, Unilateral, Alternating.
idsquerystringExercises to fetch at once: up to 50 ids or slugs, separated by commas (bench-press-barbell,squat-barbell). The rare exercises are included.
sortquerystringOrder of the results. relevance is for a text search, the others sort the matches. Default relevance. Values: relevance, popularity, name, difficulty.
categoryquerystringKind of exercise. Values: Strength, Weightlifting, Plyometrics, Cardio, Stretching, Mobility, Yoga.
difficultyquerystringHow hard the exercise is. Values: Beginner, Intermediate, Advanced.
muscleGroupquerystringMuscle group the exercise works the most (GET /v2/muscle-groups), e.g. Quadriceps.
purposequerystringPurpose of the exercise: rehab, yoga, plyometrics... Values: Strength, Calisthenics, Weightlifting, Strongman, Plyometrics, Cardio, Aerobics, Stretching, Mobility, Yoga, Pilates, Rehab, WarmUp.
forcequerystringPush, pull or static. Values: Push, Pull, Static.
includequerystringdefault 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.
groupquerybooleanShows each movement once, with its variants counted under it. Default false.
suggestquerybooleanAdds suggestion to the answer when a word of the query looks misspelled: the query put right, for a "Did you mean" line. Default false.
facetsquerybooleanAdds 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

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

NameInTypeDescription
qquerystringThe beginning of what is typed, two characters at least. Required.
limitquerynumberNumber 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

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:

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:

Parameters

NameInTypeDescription
idpathstringId (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

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:

Results are sorted by similarity score (highest first)

Use cases:

Parameters

NameInTypeDescription
idpathstringId (UUID) or slug of the source exercise. Required.
limitquerynumberMaximum 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

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

NameInTypeDescription
idpathstringId (UUID) or slug of the exercise. Required.
viewquerystringSide of the body to draw. Default both. Values: front, back, both.
targetquerystringColor of the target muscles (hex, the # is optional).
secondaryquerystringColor of the secondary muscles (hex, the # is optional).
basequerystringColor of the muscles the exercise does not work (hex, the # is optional). Defaults to the colors of the drawing.
bodyquerystringColor of the body and of the lines between the muscles (hex, the # is optional). Defaults to the colors of the drawing.
outlinequerystringColor 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

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:

Use cases:

Parameters

NameInTypeDescription
queryquerystringSearch query to filter muscles by name (case-insensitive).
bodyPartquerystringFilter by body part. Values: Legs, Back, Chest, Shoulders, Arms, Core, Neck.
limitquerynumberNumber of results to return. Default 50.
offsetquerynumberNumber of results to skip. Default 0.
groupquerystringGroup 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

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:

The exercises that work it are listed by GET /v2/muscles/{id}/exercises.

Parameters

NameInTypeDescription
idpathstringMuscle 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

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

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

NameInTypeDescription
idpathstringMuscle UUID. Required.
queryquerystringSearch query to filter exercises by name (case-insensitive).
typequerystringFilter by exercise type (compound or isolation). Values: Compound, Isolation.
limitquerynumberNumber of results to return. Default 20.
offsetquerynumberNumber of results to skip for pagination. Default 0.
equipmentqueryarray of stringEquipment 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.
muscleRolequerystringWith 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.
tierquerystringHow common the exercise is. Values: Standard, Variant, Niche.
sortquerystringOrder of the results. relevance is for a text search, the others sort the matches. Default relevance. Values: relevance, popularity, name, difficulty.
categoryquerystringKind of exercise. Values: Strength, Weightlifting, Plyometrics, Cardio, Stretching, Mobility, Yoga.
difficultyquerystringHow hard the exercise is. Values: Beginner, Intermediate, Advanced.
includequerystringdefault 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

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

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

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

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

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

NameInTypeDescription
heightquerynumberHeight in centimeters. Required.
agequerynumberAge. Required.
weightquerynumberBody weight in kilograms. Required.
genderquerystringGender, 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

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

NameInTypeDescription
heightquerynumberHeight in centimeters. Required.
agequerynumberAge. Required.
weightquerynumberBody weight in kilograms. Required.
genderquerystringGender, which changes the constant of the equation. Required. Values: male, female.
activityLevelquerystringLevel 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

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

NameInTypeDescription
heightquerynumberHeight in centimeters. Required.
weightquerynumberBody 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

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

NameInTypeDescription
heightquerynumberHeight in centimeters. Required.

Example request

curl "https://api.gymfit-api.com/v2/calculator/ibw?height=180" \
  -H "X-API-Key: YOUR_API_KEY"

Responses

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

NameInTypeDescription
fromquerystringFirst day (UTC), defaults to the start of the current month.
toquerystringLast 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

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

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
}