Authenticated client-scoped exercise catalogs and user exercise sessions.
AI Move provides authenticated, client-scoped exercise and session APIs for
user-facing GOFA applications. The request hostname selects the client; the
server does not take clientId from the request body.
Send a Firebase ID token in the Authorization header:
Authorization: Bearer <firebase-id-token>The AI Move module must be available for the client. A request is restricted to
the authenticated user's data. AI Training can use the same session routes for
its child exercise sessions when the request identifies sourceModule as
aiTraining.
/api/ai-move/exercisesReturns the exercises visible to the current client. The default catalog contains enabled exercises selected for that client. The GOFA library and client-owned exercises are filtered by the client's catalog and availability.
The optional includeTrainingOnly=true query parameter requests enabled
AI-Training-only exercises in addition to the normal catalog. It uses the AI
Training module gate and is intended for an authorized application runtime
rather than a public catalog browser. The single-exercise route can also load
an unselected library exercise for this training-only request.
{
"exercises": [
{
"exerciseId": "squat-basic",
"clientId": "gofa",
"name": "Basic Squat",
"type": "rep",
"targetValue": 10,
"category": "strength",
"difficulty": "beginner",
"enabled": true,
"sortOrder": 10
}
]
}/api/ai-move/exercises/[exerciseId]Returns one visible exercise and its algorithm data. Use
includeTrainingOnly=true with the same runtime restrictions described above
when the exercise is being loaded for AI Training.
{
"exercise": {
"exerciseId": "squat-basic",
"clientId": "gofa",
"name": "Basic Squat",
"nameZh": "基礎深蹲",
"description": "Lower into a squat and return to standing.",
"category": "strength",
"difficulty": "beginner",
"imageUrl": "/assets/ai-move/squat-basic.webp",
"type": "rep",
"targetValue": 10,
"estimatedCalories": 8,
"algorithm": {
"mode": "rule"
},
"enabled": true,
"sortOrder": 10
}
}The response is 404 when the exercise is absent or is not visible to the
requesting client.
/api/ai-move/sessionsCreates an exercise session for the authenticated user. The module gate is
selected from sourceModule when that field is present; otherwise AI Move is
used.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
exerciseId | string | Yes | Exercise to perform. |
exerciseName | string | No | Display name captured by the caller. |
exerciseNameZh | string | No | Traditional Chinese display name. |
exerciseType | "rep" | "hold" | "timer" | Yes | Exercise mode. |
targetReps | integer | No | Minimum 1; used for repetition exercises. |
targetDurationSeconds | number | No | Minimum 1; used for hold or timer exercises. |
sourceModule | "aiMove" | "aiTraining" | No | Runtime that owns the session. |
planId | string | No | AI Training plan context. |
routineTemplateId | string | No | Routine template context. |
routineInstanceId | string | No | Routine instance context. |
routineRunId | string | No | Parent routine run context. |
sequenceIndex | integer | No | Child step index; minimum 0. |
blockType | "warmup" | "main" | "cooldown" | No | Routine block context. |
{
"exerciseId": "squat-basic",
"exerciseType": "rep",
"targetReps": 10
}The endpoint returns the created session directly with status 201:
{
"sessionId": "abc123",
"clientId": "gofa",
"userId": "user-001",
"exerciseId": "squat-basic",
"exerciseType": "rep",
"targetReps": 10,
"repsCompleted": 0,
"durationSeconds": 0,
"caloriesBurned": 0,
"poseAccuracy": 0,
"formScore": null,
"holdTimeSeconds": 0,
"retryCountRemaining": null,
"retryCountUsed": 0,
"failureReason": null,
"formViolations": [],
"completionOutcome": null,
"status": "created",
"createdAt": "2026-03-17T10:00:00Z",
"completedAt": null
}/api/ai-move/sessionsLists sessions owned by the authenticated user.
| Query parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Maximum 100 results. |
startAfter | string | — | Session ID used as a pagination cursor. |
from | string | — | Optional lower date/time filter accepted by the session store. |
to | string | — | Optional upper date/time filter accepted by the session store. |
{
"sessions": [
{
"sessionId": "abc123",
"exerciseId": "squat-basic",
"exerciseType": "rep",
"status": "completed",
"repsCompleted": 10,
"durationSeconds": 45,
"caloriesBurned": 8,
"poseAccuracy": 0.92,
"formScore": 0.88,
"createdAt": "2026-03-17T10:00:00Z",
"completedAt": "2026-03-17T10:01:00Z"
}
]
}/api/ai-move/sessions/[sessionId]Fetches detailed data for a session owned by the authenticated user. A session created by AI Training is accessible while either the AI Move or AI Training module is available for the client.
{
"session": {
"sessionId": "abc123",
"clientId": "gofa",
"userId": "user-001",
"exerciseId": "squat-basic",
"exerciseType": "rep",
"targetReps": 10,
"repsCompleted": 10,
"durationSeconds": 45,
"caloriesBurned": 8,
"poseAccuracy": 0.92,
"formScore": 0.88,
"holdTimeSeconds": 0,
"retryCountUsed": 0,
"formViolations": [],
"completionOutcome": "success",
"status": "completed",
"createdAt": "2026-03-17T10:00:00Z",
"completedAt": "2026-03-17T10:01:00Z"
}
}The route returns 403 when the user does not own the session and 404 when
the session is not found.
/api/ai-move/sessions/[sessionId]Updates an owned session with exercise results. Every field is optional; the server validates supplied values.
| Field | Type | Description |
|---|---|---|
status | "created" | "in-progress" | "completed" | "failed" | "abandoned" | Session status. |
completionOutcome | "success" | "failed" | Final outcome. |
repsCompleted | integer | Minimum 0. |
durationSeconds | number | Minimum 0. |
caloriesBurned | number | Minimum 0. |
poseAccuracy | number | Between 0 and 1. |
formScore | number | Between 0 and 1. |
holdTimeSeconds | number | Minimum 0. |
holdBreakEvents | array | Hold interruption records, up to 100. |
retryCountRemaining | integer | Minimum 0. |
retryCountUsed | integer | Minimum 0. |
failureReason | string | Reason for failure. |
formViolations | array | Form violation records. |
postAnalysis | object | Post-session analysis result. |
telemetrySummary | object | Session telemetry summary. |
telemetryBasePoseSummary | object | Base-pose telemetry summary. |
A form violation record contains key, label, optional labelZh, weight,
totalChecks, violationCount, and violationRate.
{
"status": "completed",
"completionOutcome": "success",
"repsCompleted": 10,
"durationSeconds": 45,
"caloriesBurned": 8,
"poseAccuracy": 0.92,
"formScore": 0.88
}{
"success": true
}When a session is marked completed, the user's aggregate exercise statistics
are updated. The route returns 403 for a session owned by another user and
404 when the session does not exist.
The published user runtime does not expose AI Move catalog-management or operator record queries as this public integration contract. B2B authoring, physical playtest, diagnostic capture, and other admin routes are intentionally omitted from this page.