Introduction
FitGif is a REST API for fitness exercise media. It has three endpoints: the GIF API for animated exercise loops, the Video API for HD male/female exercise videos, and an optional Data API toggle that attaches structured exercise metadata to either response.
All endpoints accept POSTrequests with a JSON body and return JSON. Media isn't returned inline. Every result includes a short-lived, unguessable URL to the asset instead.
Authentication
Every request must include your API key in an X-API-Key header. Grab a key from your dashboard.
curl -X POST https://fitgif.vercel.app/api/gif \ -H "X-API-Key: fg_your_key_here" \ -H "Content-Type: application/json" \ -d '{"query": "push up", "count": 3}'Requests without a valid key are rejected with a 401.
Plans & limits
Every plan has a daily request cap and a maximum count per request. The Indie plan is also restricted to a small generic subset of the library rather than the full catalog, and can't use theming.
| Plan | Max count / request | Daily requests | Theming | Library |
|---|---|---|---|---|
| Indie | 5 | 200 | No | Generic subset |
| Startup | 15 | 5,000 | Yes | Full |
| Scale | 25 | 20,000 | Yes | Full |
| Lifetime | 25 | 50,000 | Yes | Full |
GIF API: Overview
Searches the exercise GIF library by name and returns matching results, each with a signed link to the actual GIF. Results can optionally be tinted to one of nineteen color themes on plans with theming enabled.
GIF API: Request
POST /api/gif { "query": "push up", "theme": "black", "count": 5, "data": true}GIF API: Response
{ "results": [ { "name": "push up", "gif": "https://fitgif.vercel.app/api/gif/aB3xQ9", "data": null, "confidence": 1 } ]}gifis a one-time link valid for a short window after the request. Fetch it promptly; it isn't a permanent URL you should store and reuse later. confidence is a 0 to 1 relevance score for how well the result matched your query.
Video API: Overview
Same shape as the GIF API, searching HD exercise videos instead. Every clip exists for both a male and a female performer under the same exercise name, so a sex parameter picks which one comes back.
Video API: Request
POST /api/video { "query": "dumbbell curl", "sex": "female", "count": 3, "data": true}sexstringoptionalEither "male" or "female". Determines which performer's clip is returned for each matched exercise.
Video API: Response
{ "results": [ { "name": "dumbbell curl", "video": "https://fitgif.vercel.app/api/video/tFBrOibHsTUg", "data": null, "confidence": 1 } ]}video is a one-time link to the MP4, same expiry behavior as the GIF API's links.
Data API: Overview
Set data: true on either the GIF or Video API to have each result include a data object of structured exercise information alongside the media link: muscle groups, equipment, and instructions, so you don't have to maintain your own exercise database just to show that alongside the visual asset. It's a flag on the existing endpoints, not a separate one.
Data API: Request
POST /api/gif { "query": "push up", "count": 1, "data": true}databooleanrequiredMust be set to true to receive the data object. Omitting it, or setting it to false, returns null for that field.
Data API: Response
{ "results": [ { "name": "push up", "gif": "https://fitgif.vercel.app/api/gif/aB3xQ9", "confidence": 1, "data": { "primaryMuscles": ["chest", "triceps"], "secondaryMuscles": ["shoulders", "core"], "equipment": "bodyweight", "difficulty": "beginner", "instructions": [ "Start in a high plank with hands under your shoulders.", "Lower your chest to the floor, keeping your body straight.", "Push back up to the starting position." ] } } ]}Field coverage varies by exercise. Less common movements may return null for fields we don't have data on yet rather than omitting the key.
Errors
Errors are returned as JSON with a single message field and a matching HTTP status.
| Status | Meaning |
|---|---|
| 400 | The request body is missing a required field or fails validation (e.g. count exceeds your plan's limit). |
| 401 | Missing or invalid X-API-Key header. |
| 429 | You've hit your plan's daily request cap. |
| 500 | Something went wrong on our end. |
{ "error": "Maximum count of 5 allowed on the Indie plan"}