Activity Library API
The Open Activity Library exposes a public REST API for browsing and searching exercises. Read endpoints require no authentication — anonymous callers get 120 requests an hour, and a free read-only key raises that to 5,000 a day. Write endpoints require an Authorization: Bearer <token> header; admin endpoints additionally require the caller to be an admin account.
Want everything at once? The full library is free on GitHub as YAML (CC BY-SA 4.0) — no key, no rate limit.
Authentication
Authenticated endpoints identify you from the bearer token — the acting user is never read from the request body or a custom header. Library write endpoints accept a Firebase ID token for the signed-in user. Library reads need nothing at all; send a library key (ows_lib_…, see Keys) for a higher limit. Personal API tokens (ows_…, generated on your Account page) authenticate the Remote Agent API and the MCP connector instead — see Connect your AI.
curl -X POST https://your-domain.com/api/library/activities/propose \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"draft": {"name": "Bulgarian Split Squat", "primaryMuscles": ["quadriceps"]}}'Base URL
https://your-domain.comAll endpoints are relative to the application root. Replace with your deployment URL.
Keys
Anonymous requests get 120 an hour; a free key gets 5,000 a day. Keys are instant and read-only, and if you want the whole library rather than an API, the bulk data is free on GitHub.
| Tier | Limit | How |
|---|---|---|
| Anonymous | 120 requests / hour per IP | Nothing — just call the API |
| Signed-in app user | 2,000 requests / day | The app sends your Firebase ID token |
| Free key | 5,000 requests / day | Authorization: Bearer ows_lib_… — get one below |
| Commercial | On request | Coming when someone asks |
Using a key
curl "https://your-domain.com/api/library/activities?q=squat" \ -H "Authorization: Bearer ows_lib_…"
When you hit the limit
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1788373440
X-Library-Tier: anonymous
{
"error": "rate_limited",
"tier": "anonymous",
"limit": 120,
"remaining": 0,
"resetAt": "2026-09-02T18:24:00.000Z",
"message": "Anonymous requests are limited to 120 per hour. Sign in or create a free key for 5,000 a day.",
"getKey": {
"docs": "https://your-domain.com/docs/api#keys",
"signIn": "https://your-domain.com/login?returnTo=%2Fdocs%2Fapi%23keys",
"create": "POST https://your-domain.com/api/library/keys",
"agents": {
"register": "https://your-domain.com/api/oauth/register",
"scope": "ows:library",
"docs": "https://your-domain.com/docs/connect-ai"
}
},
"bulk": "https://github.com/openworkoutsystem/open-activity-library"
}Agents: the 429 tells you where to register; request the ows:library scope.
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-Library-Tier, so you can pace yourself before a 429.
Public Endpoints
/api/library/activitiesList and search exercises in the library. Public — no authentication required.
Query Parameters
qstringSearch query (name, description, muscles)musclestringFilter by primary muscle groupequipmentstringFilter by equipment typetagstringFilter by tagsourcestringFilter by source: "user", "ai", or "migration"limitnumberMax results (default 50, max 200)offsetnumberPagination offsetResponse
{
"activities": [
{
"id": "lib-1710500000-abc123",
"name": "Barbell Back Squat",
"description": "...",
"primaryMuscles": ["quadriceps", "glutes"],
"equipment": ["barbell", "squat rack"],
"source": "user",
"provenance": {
"confidence": 0.85,
"reviewCount": 3,
"contributors": [...]
},
"validationStatus": "validated"
}
],
"total": 1247
}/api/library/activities/:idGet a single exercise by ID with full details including provenance and feedback summary.
Response
{
"id": "lib-1710500000-abc123",
"name": "Barbell Back Squat",
"description": "...",
"primaryMuscles": ["quadriceps", "glutes"],
"secondaryMuscles": ["hamstrings", "core"],
"equipment": ["barbell", "squat rack"],
"trackableMetrics": [...],
"defaults": { "sets": 3, "reps": 8 },
"provenance": {
"confidence": 0.85,
"contributors": [...],
"citations": [...],
"reviewCount": 3
},
"feedbackSummary": {
"thumbsUp": 12,
"thumbsDown": 1,
"totalFeedback": 13
},
"validationStatus": "validated"
}/api/library/statsLibrary-wide statistics: total exercises, breakdown by source/status, average confidence.
Response
{
"total": 1247,
"bySource": { "user": 340, "ai": 780, "migration": 127 },
"byStatus": { "active": 1100, "pending_review": 47, "archived": 100 },
"averageConfidence": 0.72,
"validatedCount": 980,
"pendingValidation": 167,
"staleCount": 100
}/api/library/schemaReturns the YAML schema definition for exercises. Useful for building tools or validators.
Response
{
"schema": "# Open Activity Library Exercise Schema\n..."
}Authenticated Endpoints
/api/library/activities/proposeRequires Authorization: Bearer <Firebase ID token>; submitter is the verified callerPropose a new exercise. Goes through Tier 2 AI review (expert model with research).
Request Body
draftobjectFull exercise object (name, description, primaryMuscles, etc.)contextstringOptional note for the reviewer (sources, why it belongs in the library)Response
{
"decision": "approve",
"reasoning": "Well-structured exercise with accurate anatomy...",
"exerciseId": "lib-1710500000-xyz789",
"validationStatus": "pending_validation"
}/api/library/activities/:id/suggestRequires Authorization: Bearer <Firebase ID token>; submitter is the verified callerSuggest an edit to an existing exercise. Tier 1 for minor edits (descriptions, tags), Tier 2 for structural changes (muscles, equipment).
Request Body
proposedChangesobjectObject with changed field valueschangedFieldsstring[]List of changed field namescontextstringOptional context for the changeResponse
{
"decision": "approve",
"reasoning": "Tag additions are accurate and follow conventions.",
"tier": 1
}/api/library/activities/:id/feedbackRequires Authorization: Bearer <Firebase ID token>; feedback is recorded for the verified callerSubmit feedback (thumbs up/down) on an exercise. Used for Tier 3 crowdsourced validation.
Request Body
rating"up" | "down"Thumbs up or downfeedbackTypestringCurrently always "validation"Response
{ "success": true }/api/library/activities/:id/feedbackRequires Authorization: Bearer <Firebase ID token>Get the verified caller's feedback for an exercise. Check if you already submitted.
Response
{
"feedback": {
"rating": "up",
"feedbackType": "validation",
"createdAt": "2026-03-15T..."
}
}/api/library/keysRequires Authorization: Bearer <Firebase ID token>; guests get 403 sign_in_requiredCreate a read-only library key (up to 5 per account). The plaintext key is returned once and never again — store it. No approval step; keys are instant.
Request Body
labelstringOptional, up to 40 characters — shown on your Account pageResponse
{
"key": "ows_lib_…",
"id": "k_7f3a…",
"prefix": "ows_lib_7f3a",
"label": "My script",
"createdAt": "2026-09-02T17:04:00.000Z",
"tier": "free",
"dailyLimit": 5000
}
// 409 when you already have 5 keys
{ "error": "key_limit", "limit": 5 }/api/library/keysRequires Authorization: Bearer <Firebase ID token>List your library keys with today's usage. Prefixes only — the plaintext key is never returned after creation.
Response
{
"keys": [
{
"id": "k_7f3a…",
"prefix": "ows_lib_7f3a",
"label": "My script",
"createdAt": "2026-09-02T17:04:00.000Z",
"lastUsedAt": null,
"usageToday": 0,
"dailyLimit": 5000
}
]
}/api/library/keys/:idRequires Authorization: Bearer <Firebase ID token>Revoke a library key. Takes effect immediately.
Response
{ "ok": true }Admin Endpoints
/api/library/reviewAdmin only — Authorization: Bearer <Firebase ID token> of an admin accountAdmin endpoint. Manually trigger AI review on an exercise.
Request Body
exerciseIdstringExercise to reviewchangedFieldsstring[]Fields that changedproposedChangesobjectNew field valuestiernumberForce tier 1 or 2Response
{
"decision": "approve",
"reasoning": "...",
"tier": 2
}/api/library/syncAdmin only — Authorization: Bearer <Firebase ID token> of an admin accountAdmin endpoint. Sync library to GitHub repository as YAML files.
Request Body
dryRunbooleanIf true, returns file list without pushingResponse
{
"fileCount": 1247,
"commitSha": "abc123...",
"dryRun": false
}/api/library/recalculateAdmin only — Authorization: Bearer <Firebase ID token> of an admin accountAdmin endpoint. Recalculate confidence scores for all exercises, flag stale ones.
Request Body
dryRunbooleanDefaults to true. Set false to apply changes.staleThresholdDaysnumberDays before marking stale (default 180)Response
{
"dryRun": true,
"total": 1247,
"recalculated": 45,
"flaggedStale": 12,
"flaggedArchive": 3,
"changes": [...]
}