Skip to main content

Lessons API

GET /api/lessons

List all lessons for the authenticated client.

Query Parameters

  • clientId: string (required) — The client identifier. Requests without this parameter will return a 400 error.
note

Authenticated B2B API requests to the lessons API family are usage-metered at the platform level. Commercial plans may apply request tracking, quota checks, or billing rules to these endpoints as GOFA's public API platform expands. This note does not change the current request or response contract for existing integrations.

Headers:

  • Authorization: Bearer <JWT>

Response

  • 200 OK: { data: Array<LessonConfig> }
  • 400 Bad Request: { error: 'clientId is required.' }
  • 401 Unauthorized: { error: string }
  • 500 Internal Server Error: { error: string }

Each LessonConfig object includes (fields may be optional):

  • id: string
  • idHtmlEncoded: string
  • clientId: string
  • status: GENERAL_STATUS
  • uniqueID: string
  • baseLessonID: string
  • imageUrl: string
  • imageBlurDataUrl: string
  • thumbImageUrl: string
  • title: Localizable (object with language keys, e.g. { en: "...", zh_Hans: "..." })
  • description: Localizable
  • videoURLs: string[]
  • videoId: string
  • subtitleUrl: Localizable
  • planEnrollmentId: string
  • MET: number
  • duration: number (seconds)
  • isIndividual: boolean
  • intensity: number | string
  • algorithm: WORKOUT_ALGORITHM
  • sessions: SessionConfig[] (see below)
  • groupByIntensity: GROUP_INTENSITY
  • groupByStyles: GROUP_STYLE[]
  • groupByTypes: GROUP_TYPE[]
  • groupByMuscles: GROUP_MUSCLE[]
  • groupByGoals: GROUP_GOAL[]
  • groupByEquipments: GROUP_EQUIPMENT[]
  • groupByTrainers: string[]
  • requiredWarmup: boolean
  • requiredCooldown: boolean
  • sync: boolean
  • batch: number
  • relatedLessons: LessonConfig[]
  • modifiedBy: string
  • modifyDatetime: { _seconds: number, _nanoseconds: number }
  • createdBy: string
  • createDatetime: { _seconds: number, _nanoseconds: number }

GET /api/lessons/[id]

Fetch a lesson by its ID.

Headers:

  • Authorization: Bearer <JWT>

Path Parameters:

  • id: string (required) — The lesson's unique identifier

Response:

  • 200 OK: { lesson: LessonConfig }
  • 404 Not Found: { error: string }
  • 401 Unauthorized: { error: string }
  • 500 Internal Server Error: { error: string }

GET /api/b2b/lessons/catalog

List the lessons available in the B2B Lessons configuration workspace for the authenticated client admin.

note

This endpoint is intended for the GOFA B2B admin workspace. It requires administrator access for the target client. GOFA platform administrators may include a clientId query parameter when managing another client.

Headers:

  • Authorization: Bearer <Firebase JWT>

Query Parameters:

NameRequiredDescription
clientIdNoTarget client identifier. Only GOFA platform administrators can use this to manage a different client.

Response:

  • 200 OK: lesson catalog summary
  • 401 Unauthorized: missing or invalid authentication
  • 403 Forbidden: authenticated admin cannot manage the requested client
  • 404 Not Found: target client was not found
  • 500 Internal Server Error: unexpected server error
Sample Response
{
"clientId": "demo",
"lessons": [
{
"id": "lesson_123",
"name": { "en": "Balance Basics", "zh": "平衡基礎" },
"duration": 12,
"categories": ["Strength"],
"areas": ["Lower Body"],
"equipment": "No Equipment",
"intensity": "Low",
"algorithm": "Engagement",
"status": "active",
"createdDate": "2026-05-09T00:00:00.000Z",
"isLive": true,
"membershipTiers": ["standard"],
"subtitleUrl": { "en": "/api/media/path/to/subtitle.vtt" },
"sessions": [
{
"title": { "en": "Warm up" },
"startSeconds": 0,
"endSeconds": 60,
"type": "Warm Up"
}
]
}
],
"liveLessonIds": ["lesson_123"],
"allTiers": ["standard", "premium"]
}

PATCH /api/b2b/lessons/catalog

Update lesson visibility and membership-tier assignment for the authenticated client's B2B Lessons configuration workspace.

Headers:

  • Authorization: Bearer <Firebase JWT>
  • Content-Type: application/json

Query Parameters:

NameRequiredDescription
clientIdNoTarget client identifier. Only GOFA platform administrators can use this to manage a different client.

Request Body:

FieldTypeDescription
liveLessonIdsstring[]Complete list of lessons that should be live for the managed lesson catalog.
lessonTierUpdatesArray<{ lessonId: string, membershipTiers: string[] }>Membership-tier assignment updates for one or more lessons.
forcebooleanWhen true, allows a live-status update to proceed even when affected live plans also need to be turned off.

At least one of liveLessonIds or lessonTierUpdates is required.

Sample Request
{
"liveLessonIds": ["lesson_123", "lesson_456"],
"lessonTierUpdates": [
{ "lessonId": "lesson_123", "membershipTiers": ["standard", "premium"] }
]
}

Response:

  • 200 OK: { "success": true, "catalog": { ... } }
  • 400 Bad Request: invalid payload or unknown lesson IDs
  • 401 Unauthorized: missing or invalid authentication
  • 403 Forbidden: authenticated admin cannot manage the requested client
  • 409 Conflict: one or more live plans include a lesson that would be turned off
  • 500 Internal Server Error: unexpected server error
Conflict Response
{
"error": "Unable to update lessons catalog",
"conflicts": [
{
"id": "plan_123",
"title": { "en": "Balance Starter Plan" }
}
]
}

When a 409 response is returned, send the same intended liveLessonIds with force: true only after the administrator confirms that affected plans should be turned off together with the lesson.


POST /api/b2b/lessons/catalog

Create a lesson for the authenticated client's B2B Lessons workspace.

Headers:

  • Authorization: Bearer <Firebase JWT>
  • Content-Type: application/json

Query Parameters:

NameRequiredDescription
clientIdNoTarget client identifier. Only GOFA platform administrators can use this to manage a different client.

Request Body:

FieldTypeDescription
title.enstringRequired English lesson title.
title.zh_HantstringTraditional Chinese lesson title.
descriptionobjectLocalized lesson description fields.
durationnumberLesson duration in minutes.
METnumberMetabolic equivalent value used for activity calculations.
algorithmstringLesson AI type, such as Engagement, Reps, Mirroring, or Video.
intensitystringDisplay intensity, such as Low, Medium, or High.
categoriesstring[]Lesson categories shown in the lesson library.
areasstring[]Target areas shown in the lesson library.
equipmentstringMain equipment label.
imageUrlstringLesson poster image URL.
thumbImageUrlstringLesson thumbnail URL.
thumbnailTimeInSecondsnumberVideo timestamp used when deriving a thumbnail from the lesson video.
videoURLsstring[]Lesson video URLs.
subtitleUrlobjectLocalized subtitle URLs, for example { "en": "...", "zh_Hant": "..." }.
sessionsArray<object>Lesson session timeline entries. Each entry can include title, startSeconds, endSeconds, type, repPoseId, and repCount.
isLivebooleanWhether the lesson should appear in the app lesson list.
membershipTiersstring[]Membership tiers that can access the lesson.
Sample Request
{
"title": { "en": "Balance Basics", "zh_Hant": "平衡基礎" },
"description": { "en": "A guided balance lesson." },
"duration": 12,
"MET": 3,
"algorithm": "Engagement",
"intensity": "Low",
"categories": ["Strength"],
"areas": ["Lower Body"],
"equipment": "No Equipment",
"imageUrl": "https://cdn.example.com/lesson.jpg",
"thumbImageUrl": "https://cdn.example.com/lesson-thumb.jpg",
"videoURLs": ["https://cdn.example.com/lesson.m3u8"],
"subtitleUrl": { "en": "https://cdn.example.com/lesson-en.vtt" },
"sessions": [
{
"title": { "en": "Main set", "zh_Hant": "主要訓練" },
"startSeconds": 0,
"endSeconds": 600,
"type": "Engagement"
}
],
"isLive": false,
"membershipTiers": ["standard"]
}

Response:

  • 201 Created: { "success": true, "lessonId": "lesson_123", "catalog": { ... } }
  • 400 Bad Request: invalid payload
  • 401 Unauthorized: missing or invalid authentication
  • 403 Forbidden: authenticated admin cannot manage the requested client
  • 500 Internal Server Error: unexpected server error

PATCH /api/b2b/lessons/catalog/[lessonId]

Update editable lesson metadata, media URLs, lesson-list visibility, and membership-tier assignment for one lesson.

Headers:

  • Authorization: Bearer <Firebase JWT>
  • Content-Type: application/json

Query Parameters:

NameRequiredDescription
clientIdNoTarget client identifier. Only GOFA platform administrators can use this to manage a different client.

Request Body:

Send any subset of the fields accepted by POST /api/b2b/lessons/catalog. To hide a lesson from the app lesson list without deleting it, send isLive: false.

Sample Request
{
"title": { "en": "Balance Basics - Updated" },
"isLive": false,
"membershipTiers": ["premium"]
}

Response:

  • 200 OK: { "success": true, "catalog": { ... } }
  • 400 Bad Request: invalid payload
  • 401 Unauthorized: missing or invalid authentication
  • 403 Forbidden: authenticated admin cannot manage the requested client
  • 404 Not Found: lesson was not found for the managed client
  • 409 Conflict: one or more live plans include a lesson that would be turned off
  • 500 Internal Server Error: unexpected server error

POST /api/b2b/lessons/catalog/[lessonId]/subtitle

Upload or replace one localized WebVTT subtitle file for a lesson managed in the B2B Lessons workspace.

Headers:

  • Authorization: Bearer <Firebase JWT>
  • Content-Type: multipart/form-data

Query Parameters:

NameRequiredDescription
clientIdNoTarget client identifier. Only GOFA platform administrators can use this to manage a different client.

Form Data:

FieldTypeDescription
localestringSubtitle locale. Supported values are en, zh_Hant, and zh_Hans.
fileFileWebVTT subtitle file (.vtt).

Response:

  • 200 OK: { "success": true, "subtitleUrl": "...", "catalog": { ... } }
  • 400 Bad Request: unsupported locale, missing file, or unsupported file type
  • 401 Unauthorized: missing or invalid authentication
  • 403 Forbidden: authenticated admin cannot manage the requested client
  • 404 Not Found: lesson was not found for the managed client
  • 500 Internal Server Error: unexpected server error

SessionConfig (in sessions array)

Each lesson contains an array of SessionConfig objects. See src/types/lesson/session-config.ts for full details, but typical fields include:

  • index: number
  • category: string
  • title: Localizable
  • start: number (seconds)
  • end: number (seconds)
  • repPoseId: string
  • targetRepCount: number

note

All fields may not be present on every lesson.

For the most up-to-date schema, refer to src/types/lesson/lesson-config.ts and src/types/lesson/session-config.ts.

Only documented fields are guaranteed; additional fields may be present depending on lesson data.