# Exercise API > Normalized exercise data for apps, internal tools, and AI coding workflows. ## Authentication - All `/v1/*` data endpoints require the `X-API-Key` request header. - `GET /v1/health` is public and does not require auth. - Keys use the `exlib_` prefix plus 32 alphanumeric characters, for a total length of 38. - New keys are shown once after generation. The dashboard can regenerate a replacement key later. - Missing, malformed, and unknown keys all return `401 INVALID_API_KEY`. ```text X-API-Key: exlib_your32characterapikeygoeshere ``` ## Base URL ```text https://api.exerciseapi.dev/v1 ``` ## Rate Limits - Authenticated API data routes include rate limit headers. `GET /v1/health` is excluded. - Successful authenticated responses use `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` for the daily window. - `429 RATE_LIMIT_EXCEEDED` responses use the same headers for the window that was exceeded, plus `Retry-After`. - If Redis is unavailable, successful authenticated responses can fail open with `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` all set to `-1`. | Tier | Daily requests | Per-minute requests | Max results per request | | --- | ---: | ---: | ---: | | Free | 100 | 5 | 20 | | Starter | 1000 | 30 | 50 | | Pro | 10000 | 100 | 100 | | Business | 100000 | 500 | 100 | Successful response headers example: ```text X-RateLimit-Limit: 100 X-RateLimit-Remaining: 82 X-RateLimit-Reset: 1775184000 ``` 429 response headers example: ```text X-RateLimit-Limit: 5 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1775182500 Retry-After: 32 ``` ## Endpoints ### `GET /v1/exercises` Search, filter, paginate, or randomize the exercise catalog. Auth: `X-API-Key` required Query parameters: - `q` (string, optional): Full-text search query. Length: 1 to 200 characters. - `category` (enum, optional): Top-level training category. Allowed values: strength, yoga, mobility, physical_therapy, stretching, pilates, calisthenics, plyometrics, conditioning, olympic_weightlifting, powerlifting, strongman - `muscle` (string, optional): Display muscle group or anatomical muscle name. Length: 1 to 100 characters. - `equipment` (string, optional): Equipment filter. Length: 1 to 100 characters. - `level` (enum, optional): Difficulty level. Allowed values: beginner, intermediate, advanced - `force` (enum, optional): Movement force classification. Allowed values: push, pull, static - `mechanic` (enum, optional): Movement mechanic. Allowed values: compound, isolation - `random` (boolean, optional, default `false`): Return random results instead of the default order. - `limit` (integer, optional, default `20`): Requested page size before plan-based clamping. Validated up to 100, then clamped to the plan cap. - `offset` (integer, optional, default `0`): Zero-based offset into the result set. Free tier requires `offset + limit <= 500`. Notes: - `GET /v1/exercises` returns `total: null` when `q` is present. Filter-only requests return a numeric total. - `limit` is validated up to 100 and then clamped to your plan's per-request result cap. - Free-tier pagination depth is capped at `offset + limit <= 500`. - `muscle` accepts either a display group such as `chest` or an anatomical name. Request example: ```bash curl -H "X-API-Key: YOUR_API_KEY" \ "https://api.exerciseapi.dev/v1/exercises?q=bench%20press&limit=10" ``` Response example: ```json { "data": [ { "id": "barbell-bench-press", "name": "Barbell Bench Press", "keywords": [ "bench", "press", "chest", "barbell", "pecs" ], "primaryMuscles": [ "chest" ], "secondaryMuscles": [ "front delts", "triceps" ], "equipment": "barbell", "force": "push", "level": "intermediate", "mechanic": "compound", "category": "strength", "instructions": [ "Lie on a flat bench with your feet planted.", "Unrack the bar and lower it to mid-chest with control.", "Press the bar back to lockout while keeping your upper back tight." ], "exerciseTips": [ "Keep your shoulder blades retracted.", "Drive your feet into the floor throughout the rep." ], "commonMistakes": [ "Bouncing the bar off the chest.", "Letting the elbows flare aggressively at the bottom." ], "safetyInfo": "Use a spotter or safety pins when working near failure.", "overview": "A compound upper-body press that trains the chest, shoulders, and triceps.", "variations": [ "Close-Grip Bench Press", "Paused Bench Press" ], "images": [] } ], "total": null, "limit": 10, "offset": 0 } ``` ### `GET /v1/exercises/:id` Return the full public exercise payload for a single ID. Auth: `X-API-Key` required Path parameters: - `id` (string, required): Exercise ID from list or search responses. Notes: - Returns `404 NOT_FOUND` when the ID does not exist. - The public schema matches `transformExercise` and excludes internal fields such as `source`. Request example: ```bash curl -H "X-API-Key: YOUR_API_KEY" \ "https://api.exerciseapi.dev/v1/exercises/barbell-bench-press" ``` Response example: ```json { "data": { "id": "barbell-bench-press", "name": "Barbell Bench Press", "keywords": [ "bench", "press", "chest", "barbell", "pecs" ], "primaryMuscles": [ "chest" ], "secondaryMuscles": [ "front delts", "triceps" ], "equipment": "barbell", "force": "push", "level": "intermediate", "mechanic": "compound", "category": "strength", "instructions": [ "Lie on a flat bench with your feet planted.", "Unrack the bar and lower it to mid-chest with control.", "Press the bar back to lockout while keeping your upper back tight." ], "exerciseTips": [ "Keep your shoulder blades retracted.", "Drive your feet into the floor throughout the rep." ], "commonMistakes": [ "Bouncing the bar off the chest.", "Letting the elbows flare aggressively at the bottom." ], "safetyInfo": "Use a spotter or safety pins when working near failure.", "overview": "A compound upper-body press that trains the chest, shoulders, and triceps.", "variations": [ "Close-Grip Bench Press", "Paused Bench Press" ], "images": [] } } ``` ### `GET /v1/muscles` Return display groups and their anatomical muscle names. Auth: `X-API-Key` required Notes: - Use `displayGroup` values for user-facing filter pickers. - The `muscle` search parameter accepts either a `displayGroup` or an anatomical muscle name. Request example: ```bash curl -H "X-API-Key: YOUR_API_KEY" \ "https://api.exerciseapi.dev/v1/muscles" ``` Response example: ```json { "data": [ { "displayGroup": "chest", "muscles": [ "pectoralis major clavicular head", "pectoralis major sternal head" ] }, { "displayGroup": "back", "muscles": [ "latissimus dorsi", "trapezius" ] } ] } ``` ### `GET /v1/equipment` Return the canonical equipment names used by the API. Auth: `X-API-Key` required Notes: - Equipment values are returned as a simple string array. Request example: ```bash curl -H "X-API-Key: YOUR_API_KEY" \ "https://api.exerciseapi.dev/v1/equipment" ``` Response example: ```json { "data": [ "barbell", "dumbbell", "kettlebell", "pull-up bar" ] } ``` ### `GET /v1/categories` Return categories, counts, and descriptions. Auth: `X-API-Key` required Notes: - Descriptions are part of the response payload for each category. Request example: ```bash curl -H "X-API-Key: YOUR_API_KEY" \ "https://api.exerciseapi.dev/v1/categories" ``` Response example: ```json { "data": [ { "category": "strength", "count": 742, "description": "Traditional resistance training" }, { "category": "yoga", "count": 184, "description": "Asanas, flows, and breath work" } ] } ``` ### `GET /v1/stats` Return aggregate catalog metadata and category counts. Auth: `X-API-Key` required Notes: - Includes total exercise count, per-category counts, last import timestamp, and data version. Request example: ```bash curl -H "X-API-Key: YOUR_API_KEY" \ "https://api.exerciseapi.dev/v1/stats" ``` Response example: ```json { "data": { "totalExercises": 2198, "categories": { "strength": 742, "yoga": 184, "mobility": 133 }, "lastUpdated": "2026-03-31T04:12:00.000Z", "dataVersion": "2026-03-31" } } ``` ### `GET /v1/health` Return service health for Supabase and Redis dependencies. Auth: No auth required Notes: - This is the only public endpoint that does not require `X-API-Key`. - Returns `503` only when Supabase is unavailable. Redis-only failures degrade to `200` with a `degraded` status. Request example: ```bash curl "https://api.exerciseapi.dev/v1/health" ``` Response example: ```json { "status": "ok", "version": "1.0.0", "dataVersion": "2026-03-31", "exerciseCount": 2198, "checks": { "supabase": "ok", "redis": "ok" } } ``` ## Error Responses All API errors use this envelope: ```json { "error": { "code": "ERROR_CODE", "message": "Human-readable description", "details": {} } } ``` ### `INVALID_API_KEY` (401) Missing, malformed, or unknown API key. ```json { "error": { "code": "INVALID_API_KEY", "message": "Missing API key. Get one at https://exerciseapi.dev/signup" } } ``` ### `RATE_LIMIT_EXCEEDED` (429) Per-minute or daily rate limit exceeded. Details fields: upgrade_url, current_tier, limit, window, resets_at ```json { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Per-minute rate limit exceeded (5/min). Slow down.", "details": { "upgrade_url": "https://exerciseapi.dev/dashboard/billing", "current_tier": "free", "limit": 5, "window": "minute", "resets_at": "2026-04-02T18:15:00.000Z" } } } ``` ### `PAGINATION_DEPTH_EXCEEDED` (403) Free-tier request goes beyond the first 500 results. Details fields: upgrade_url, current_tier ```json { "error": { "code": "PAGINATION_DEPTH_EXCEEDED", "message": "Free tier limited to first 500 results. Upgrade for full access.", "details": { "upgrade_url": "https://exerciseapi.dev/dashboard/billing", "current_tier": "free" } } } ``` ### `INVALID_PARAMETER` (400) Query parameter or path parameter validation failed. Details fields: field, received ```json { "error": { "code": "INVALID_PARAMETER", "message": "Invalid query parameter: 'limit' Number must be less than or equal to 100", "details": { "field": "limit", "received": "500" } } } ``` ### `NOT_FOUND` (404) Requested resource does not exist. ```json { "error": { "code": "NOT_FOUND", "message": "Exercise not found: barbell-bench-press" } } ``` ### `INTERNAL_ERROR` (500) Unexpected server error. ```json { "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred" } } ``` ## Common Integration Pattern 1. Fetch https://exerciseapi.dev/llms.txt and keep it alongside your API integration instructions. 2. Store an API key securely and send it as the `X-API-Key` header on every authenticated request. 3. Use `GET /v1/exercises` for search and browse, then use the returned `id` with `GET /v1/exercises/:id` for detail views. 4. Read rate limit headers on authenticated responses and handle `429 RATE_LIMIT_EXCEEDED` with backoff using `Retry-After`. 5. Handle `403 PAGINATION_DEPTH_EXCEEDED` on the free tier and prompt for an upgrade when needed. ## Exercise Schema Fields - `id` (string): Stable exercise identifier. - `name` (string): Display name. - `keywords` (string[]): Search terms and synonyms for the exercise. - `primaryMuscles` (string[]): Primary muscle targets. - `secondaryMuscles` (string[]): Secondary muscle targets. - `equipment` (string | null): Required equipment when applicable. Nullable. - `force` ("push" | "pull" | "static" | null): Movement force classification when known. Nullable. - `level` ("beginner" | "intermediate" | "advanced"): Difficulty level. - `mechanic` ("compound" | "isolation" | null): Movement mechanic when known. Nullable. - `category` (string): Top-level training category. - `instructions` (string[]): Ordered step-by-step instructions. - `exerciseTips` (string[]): Form cues and setup tips. - `commonMistakes` (string[]): Frequent execution mistakes to avoid. - `safetyInfo` (string): Safety guidance and caution notes. - `overview` (string): Short summary of the movement and its purpose. - `variations` (string[]): Related variations or progressions. - `images` (string[]): Exercise image URLs. May be an empty array. ## Categories - `strength`: Traditional resistance training - `yoga`: Asanas, flows, and breath work - `mobility`: Joint range of motion and movement quality - `physical_therapy`: Rehab and prehab exercises - `stretching`: Flexibility and muscle lengthening - `pilates`: Core-focused mat and apparatus work - `calisthenics`: Bodyweight strength and skill training - `plyometrics`: Explosive power and jump training - `conditioning`: Cardiovascular and metabolic fitness - `olympic_weightlifting`: Snatch, clean & jerk, and derivatives - `powerlifting`: Squat, bench press, deadlift, and accessories - `strongman`: Implements, carries, and odd-object training