Auth API
Auto-generated from the OpenAPI spec. Run
node docs-site/scripts/fetch-openapi.jsto regenerate.
POST /api/v1/auth/register/client
Register Client
Register a new client account (mobile app). Auto-logs in and returns tokens.
Request body
| Field | Required | Type | Description |
|---|---|---|---|
email | Yes | string | |
password | Yes | string | |
full_name | Yes | string | |
phone | No | string | |
date_of_birth | No | string |
Responses
- 201 — Successful Response
- 422 — Validation Error
POST /api/v1/auth/bootstrap
Bootstrap Studio
One-time first-run setup: create the studio's StudioSettings row, its default Location(id=1), and its one and only manager account, then log them straight in.
Public and unauthenticated by design — on a fresh install there is no manager JWT yet, so nothing else can gate this endpoint (the classic chicken-and-egg problem). Two restrictions keep that safe:
- Loopback-only. The backend binds 0.0.0.0:8000 (reachable from the LAN so the mobile app can connect — see api/client.ts on desktop, which always calls http://localhost:8000 for this very endpoint). Without this check, another device on the same network could race to claim the studio before its real owner finishes onboarding, permanently locking them out afterward (the single-use guard below would then reject the legitimate owner's own later attempt).
- Single-use. Rejects with STUDIO_ALREADY_CONFIGURED once any User row
exists. The
count() > 0check is the LAST thing evaluated before the db.add()/db.commit() sequence — no request-time gap between check and write — so it closes the same way the confirmed-bookings capacity check in bookings.py and the stock check in product_sale_service.py do: relying on SQLite's single-writer transaction serialization rather than row-level locking (which SQLite doesn't support cleanly).
Request body
| Field | Required | Type | Description |
|---|---|---|---|
studio_name | Yes | string | |
timezone | No | string | |
manager_full_name | Yes | string | |
manager_email | Yes | string | |
manager_password | Yes | string |
Responses
- 201 — Successful Response
- 422 — Validation Error
POST /api/v1/auth/login
Login
Login for managers, instructors, and clients. Tries users table first, then clients.
Request body
| Field | Required | Type | Description |
|---|---|---|---|
email | Yes | string | |
password | Yes | string |
Responses
- 200 — Successful Response
- 422 — Validation Error
POST /api/v1/auth/refresh
Refresh Token Endpoint
Issue a new access token from a valid refresh token.
The new access token's role is derived from the refresh token's own role
claim, NOT by probing the users table first. User.id and Client.id overlap,
so a "try users then clients" lookup would let a client refresh token mint a
manager access token whenever the ids collide (privilege escalation).
Request body
| Field | Required | Type | Description |
|---|---|---|---|
refresh_token | Yes | string |
Responses
- 200 — Successful Response
- 422 — Validation Error
POST /api/v1/auth/logout
Logout
Invalidate session (stateless — client should discard tokens).
Responses
- 200 — Successful Response
POST /api/v1/auth/forgot-password
Forgot Password
Request a password reset email.
Request body
| Field | Required | Type | Description |
|---|---|---|---|
email | Yes | string |
Responses
- 200 — Successful Response
- 422 — Validation Error
POST /api/v1/auth/reset-password
Reset Password
Reset password using a token.
Request body
| Field | Required | Type | Description |
|---|---|---|---|
token | Yes | string | |
new_password | Yes | string |
Responses
- 200 — Successful Response
- 422 — Validation Error
GET /api/v1/auth/invite/{token}
Validate Invite Token
Validate an invitation token and return basic client info.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
token | path | Yes | string |
Responses
- 200 — Successful Response
- 422 — Validation Error
GET /api/v1/auth/me
Get Me
Return the current authenticated user or client profile.
Responses
- 200 — Successful Response