Classes API
Auto-generated from the OpenAPI spec. Run
node docs-site/scripts/fetch-openapi.jsto regenerate.
POST /api/v1/classes/recurring
Schedule Recurring Classes
Request body
| Field | Required | Type | Description |
|---|---|---|---|
template_id | Yes | integer | |
instructor_id | No | integer | |
location_id | No | integer | |
starts_at | Yes | string | |
ends_at | Yes | string | |
capacity | Yes | integer | |
notes | No | string | |
days_of_week | Yes | array | |
recurrence_end_date | No | string | |
max_occurrences | No | integer | |
required_tag_id | No | integer | Tag restriction (PRODUCT_SPEC.md §4.1a) applied to every instance in the series. Omit to inherit the template's required_tag_id; send explicit null to create the series with no restriction regardless of the template. |
is_online | No | boolean |
Responses
- 201 — Successful Response
- 422 — Validation Error
GET /api/v1/classes
List Classes
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
start_date | query | No | ||
end_date | query | No | ||
instructor_id | query | No | ||
template_id | query | No | ||
location_id | query | No | ||
status | query | No |
Each returned class includes required_tag_id, required_tag_name, and required_tag_color
(denormalized from the tag, null when the class has no restriction), and location_name
(denormalized from the class's location_id, null when it doesn't resolve to a real location —
same pattern as location_name on Bookings / Appointments).
Responses
- 200 — Successful Response
- 422 — Validation Error
POST /api/v1/classes
Schedule Single Class
Request body
| Field | Required | Type | Description |
|---|---|---|---|
template_id | Yes | integer | |
instructor_id | No | integer | |
location_id | No | integer | |
starts_at | Yes | string | |
ends_at | Yes | string | |
capacity | Yes | integer | |
notes | No | string | |
is_online | No | boolean | |
required_tag_id | No | integer | Tag restriction (PRODUCT_SPEC.md §4.1a) for this instance. Omit to inherit the template's required_tag_id; send explicit null to schedule with no restriction regardless of the template. |
Responses
- 201 — Successful Response
- 422 — Validation Error
GET /api/v1/classes/{class_id}
Get Class
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Includes the same required_tag_id/required_tag_name/required_tag_color and location_name
denormalized fields as GET /classes above.
Responses
- 200 — Successful Response
- 422 — Validation Error
PUT /api/v1/classes/{class_id}
Update Class
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Request body
| Field | Required | Type | Description |
|---|---|---|---|
instructor_id | No | integer | |
location_id | No | integer | |
starts_at | No | string | |
ends_at | No | string | |
capacity | No | integer | |
notes | No | string | |
is_online | No | boolean | |
required_tag_id | No | integer | Change or clear this instance's tag restriction. Send explicit null to clear it; omit the field to leave it unchanged. Does not affect the template or other instances. |
Responses
- 200 — Successful Response
- 422 — Validation Error
DELETE /api/v1/classes/{class_id}
Cancel Class
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
POST /api/v1/classes/{class_id}/zoom-meeting/retry
Retry Zoom Meeting
Manually retry Zoom meeting creation for an online class whose previous attempt failed (zoom_meeting_status == 'failed').
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
GET /api/v1/classes/{class_id}/roster
Get Roster
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
GET /api/v1/classes/{class_id}/waitlist
Get Waitlist
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
GET /api/v1/classes/{class_id}/eligible-memberships
Get Eligible Memberships
Returns only the target client's active memberships that are actually usable to book this
specific class right now — reusing the same eligibility logic (_membership_is_usable) that
POST /bookings applies when resolving a membership at booking time: the membership's purpose
must apply to class bookings, the class's tag restriction (if any) must be satisfied, and the
membership must be unlimited or have enough credits_remaining for this class's credit cost.
Expired and non-active memberships are never included.
Backs the mobile and backoffice membership pickers shown when a client has more than one active
membership and the studio manager (or the client, in the app) must choose which one to use —
replacing a previous behavior where every active membership was listed regardless of whether it
could actually be used for that class, which could fail with a 409 at booking time.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer | |
client_id | query | No | integer | The client whose memberships to check. Required when called with a manager/instructor token. Optional for a client token — if omitted, defaults to the caller's own id; if provided, it must match the caller's own id. |
Mixed-audience, same IDOR pattern as the rest of this router and bookings.py:
- Client token — resolves the target client from the token's own
sub. Passing aclient_idquery param that doesn't match the caller's own id is rejected with403 FORBIDDEN(never silently coerced to the caller's own id). - Manager/instructor token — must pass
client_idexplicitly; omitting it returns422 VALIDATION_ERROR.
Each item in the response array is a MembershipResponse, the same shape returned by the
Memberships endpoints — including the denormalized membership_type_name,
is_unlimited, and usable_for convenience fields.
Responses
- 200 — Successful Response — array of
MembershipResponse, possibly empty if the client has no membership usable for this class. - 403
FORBIDDEN— a client token requested aclient_idother than its own. - 404
NOT_FOUND— no scheduled class with thisclass_id. - 422
VALIDATION_ERROR— a manager/instructor token omitted the requiredclient_id.
POST /api/v1/classes/{class_id}/complete
Complete Class
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
DELETE /api/v1/classes/{class_id}/remove
Remove Class
Permanently delete a scheduled class. Only allowed when there are no confirmed bookings.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
class_id | path | Yes | integer |
Responses
- 204 — Successful Response
- 422 — Validation Error