AI Move API
AI Move provides authenticated client-facing exercise and session APIs used by GOFA mobile and web experiences.
Authentication
Use a Firebase user token in the Authorization: Bearer <firebase_jwt> header.
The AI Move module must be enabled for your client. The visible exercise catalog is tenant-aware — end users only receive exercises that are currently available to their client.
Exercises
GET /api/ai-move/exercises
Returns the exercises visible to the current client.
- For the GOFA tenant: returns enabled GOFA library exercises ordered by the library default order.
- For other clients: returns the client's enabled custom exercises plus the GOFA library exercises currently selected for that client.
{
"exercises": [
{
"exerciseId": "squat-basic",
"clientId": "gofa",
"name": "Basic Squat",
"type": "rep",
"targetValue": 10,
"category": "strength",
"difficulty": "beginner",
"enabled": true,
"sortOrder": 10
}
]
}
GET /api/ai-move/exercises/[exerciseId]
Returns a single exercise with full algorithm data if that exercise is visible to the current client.
- A GOFA library exercise is only returned when it is currently enabled and included in the requesting client's catalog.
- A client custom exercise is returned when it belongs to the current client and is enabled.
{
"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
}
}
Error Responses:
| Status | Description |
|---|---|
| 404 | Exercise not found |
Sessions
POST /api/ai-move/sessions
Create a new exercise session for the authenticated user.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
exerciseId | string | Yes | The exercise to perform |
exerciseType | "rep" | "timer" | Yes | Exercise mode |
targetReps | number | No | Target rep count (min: 1, for rep type) |
targetDurationSeconds | number | No | Target duration in seconds (min: 1, for timer type) |
{
"exerciseId": "squat-basic",
"exerciseType": "rep",
"targetReps": 10
}
{
"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
}
GET /api/ai-move/sessions
List sessions for the authenticated user.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 20 | Max results per page (max: 100) |
startAfter | string | — | Session ID for cursor-based pagination |
{
"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"
}
]
}
GET /api/ai-move/sessions/[sessionId]
Fetch detailed data for a specific session. The authenticated user must own the session.
{
"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"
}
}
Error Responses:
| Status | Description |
|---|---|
| 403 | User does not own this session |
| 404 | Session not found |
PATCH /api/ai-move/sessions/[sessionId]
Update a session with exercise results. The authenticated user must own the session.
Request Body (all fields optional):
| Field | Type | Description |
|---|---|---|
status | "created" | "in-progress" | "completed" | "failed" | "abandoned" | Session status |
completionOutcome | "success" | "failed" | Final outcome |
repsCompleted | number | Reps completed (min: 0) |
durationSeconds | number | Duration in seconds (min: 0) |
caloriesBurned | number | Calories burned (min: 0) |
poseAccuracy | number | Pose accuracy score (0–1) |
formScore | number | Form quality score (0–1) |
holdTimeSeconds | number | Total hold time (min: 0) |
retryCountRemaining | number | Retries remaining (min: 0) |
retryCountUsed | number | Retries used (min: 0) |
failureReason | string | Reason for failure |
formViolations | array | Form violation records (see below) |
Form Violation Record:
| Field | Type | Description |
|---|---|---|
key | string | Violation identifier |
label | string | Display label |
labelZh | string | Chinese display label (optional) |
weight | number | Scoring weight |
totalChecks | number | Total times checked |
violationCount | number | Times violated |
violationRate | number | Violation rate |
{
"status": "completed",
"completionOutcome": "success",
"repsCompleted": 10,
"durationSeconds": 45,
"caloriesBurned": 8,
"poseAccuracy": 0.92,
"formScore": 0.88
}
{
"success": true
}
When a session is marked as "completed", the user's aggregate exercise statistics are automatically updated.
Error Responses:
| Status | Description |
|---|---|
| 403 | User does not own this session |
| 404 | Session not found |
Admin Records
GET /api/ai-move/records
Admin-only endpoint to list AI Move session records for a client. Requires admin authentication.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
clientId | string | — | Target client ID (admin can query other clients) |
limit | number | 50 | Max results (1–500) |
{
"data": [
{
"id": "session-001",
"clientId": "gofa",
"userId": "user-001",
"exerciseId": "squat-basic",
"exerciseType": "rep",
"status": "completed",
"repsCompleted": 10,
"durationSeconds": 45,
"caloriesBurned": 8,
"createdAt": "2026-03-17T10:00:00.000Z",
"completedAt": "2026-03-17T10:01:00.000Z"
}
],
"count": 1
}
Error Responses:
| Status | Description |
|---|---|
| 401 | Unauthorized — admin authentication required |
| 403 | AI Move module not enabled for this client |
| 500 | Internal server error |
Results are ordered by createdAt descending. The AI Move module must be enabled for the target client.
Notes
- AI Move catalog-management endpoints are intentionally not documented on this public site.
- Client administrators configure library selection and ordering through GOFA-managed admin experiences.