curl -X POST "https://api.fitsociety.io/public/v1/workout/clients/{clientId}/exercises/search" \
-H "Authorization: Bearer <access_token>" \
-H "Idempotency-Key: <stable_request_key>" \
-H "Content-Type: application/json" \
-d '{}'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
page: 1,
limit: 20,
search: '',
favourites: false,
levels: ['Beginner'],
muscleGroups: ['Chest'],
equipments: ['barbell'],
categories: ['Strength'],
coaches: [],
clientOwn: false
})
};
fetch('https://api.fitsociety.io/public/v1/workout/clients/{clientId}/exercises/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.fitsociety.io/public/v1/workout/clients/{clientId}/exercises/search"
payload = {
"page": 1,
"limit": 20,
"search": "",
"favourites": False,
"levels": ["Beginner"],
"muscleGroups": ["Chest"],
"equipments": ["barbell"],
"categories": ["Strength"],
"coaches": [],
"clientOwn": False
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)List exercises for client with filters
Returns a paginated list of exercises visible to the client (global, company, and own exercises). All filters are optional and sent in the request body. exerciseType in each item is coach (added by a coach), personal (added by the client), or global (Everyone/Fitsociety visibility). availableFilters.coaches is populated dynamically from exercises visible in this company. Pass skipExercise=<exerciseId> (query or body) to exclude one exercise from the list — e.g. the exercise currently being replaced. An invalid/missing id is ignored. Pass excludeExerciseIds (the multi-value version of skipExercise) to exclude one or more exercises — e.g. movements already selected/prescribed. Both exclude exercises from the results and pagination totals. Pass clientOwn: true to return ONLY the client’s own exercises (same set as /my-exercises). Pass exerciseToTop=<exerciseId> to pin one exercise at page 1 / index 0 — but only if it also satisfies the active filters/visibility; otherwise it is not pinned and does not appear. The pinned item is de-duplicated from the rest of the list. Each item also returns a media array (images + videos, same shape as getExerciseHistory) and targetedMuscles (primary + secondary, de-duplicated).
Requires the workout_client_plans:write scope. This operation maps to /app/v1/workout/client/exercises and retains its Workout V2 permission, feature-flag, and resource-scope checks.
The clientId path parameter identifies the client represented by the request context.
curl -X POST "https://api.fitsociety.io/public/v1/workout/clients/{clientId}/exercises/search" \
-H "Authorization: Bearer <access_token>" \
-H "Idempotency-Key: <stable_request_key>" \
-H "Content-Type: application/json" \
-d '{}'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
page: 1,
limit: 20,
search: '',
favourites: false,
levels: ['Beginner'],
muscleGroups: ['Chest'],
equipments: ['barbell'],
categories: ['Strength'],
coaches: [],
clientOwn: false
})
};
fetch('https://api.fitsociety.io/public/v1/workout/clients/{clientId}/exercises/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.fitsociety.io/public/v1/workout/clients/{clientId}/exercises/search"
payload = {
"page": 1,
"limit": 20,
"search": "",
"favourites": False,
"levels": ["Beginner"],
"muscleGroups": ["Chest"],
"equipments": ["barbell"],
"categories": ["Strength"],
"coaches": [],
"clientOwn": False
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)Authorizations
Public API access token issued by /public/v1/oauth/token. Example: Authorization: Bearer fspt_.... Each resource request rechecks the token company's current provider access. Disabling access blocks existing tokens with 403 auth.provider_unavailable.
Headers
Required for Public API write requests. Reusing the same key with the same method, path, and body replays the stored successful response; reusing it with a different request returns 409 idempotency.conflict.
1 - 200"booking-create-20260714-001"
Path Parameters
Client in the company bound to the Public API token.
^[a-fA-F0-9]{24}$Query Parameters
Exclude this exercise id from the results (and from pagination totals). Typically the exercise being replaced. May also be sent in the request body. Invalid or missing ids are ignored.
"67f1234567890abcdef1234"
Body
x >= 11
1 <= x <= 10020
"bench press"
false
Filter by difficulty. Values: Beginner, Intermediate, Advance.
"Beginner,Intermediate"
Matches on primaryMuscle OR secondaryMuscles. Allowed values: Chest, Back, Lats, Traps, Shoulders …
"Chest,Shoulders"
Equipment key values from availableFilters.equipments.
"barbell,dumbbell"
Filters on primaryCategory. Allowed values: Agility & Speed, Strength, Hypertrophy, Strength - Dynamic, Strength - Explosive …
"Strength,Cardio"
Filter to exercises added by specific coaches. Restricts to addedByRole: Coach.
["67f1234567890abcdef1111"]
Exclude this exercise id from the results (and pagination totals). Typically the exercise being replaced. May also be passed as the skipExercise query param. Invalid/missing ids are ignored.
"67f1234567890abcdef1234"
Exclude one or more exercises from the results (movements already selected/prescribed). Comma-separated string or array of exercise ObjectIds. Aliases also accepted: excludeExerciseId / exerciseIds / exerciseId; also readable from the query string. Invalid id → 400 WORKOUTEXERCISE_EXERCISEID_INVALID. Echoed back in selectedFilters.excludeExerciseIds.
"6925d2764ac340a53e012927,6925d2764ac340a53e012928"
When true, return ONLY the client's own exercises (addedByRole: Client, addedBy = client) — the 'My Exercises' subset. Overrides the coaches filter.
false
Pin a single exercise to page 1 / index 0. Only pinned if it also satisfies the active filters + visibility (else omitted entirely). De-duplicated from the rest of the list. May also be passed as the exerciseToTop query param. Invalid id → 400 WORKOUTEXERCISE_EXERCISEID_INVALID.
"67f1234567890abcdef1234"