#
Authentication API
sTvOS supports multiple authentication flows for end users, trainers, and partner staff.
#
Client User Authentication
All client user auth endpoints require the X-API-Key header.
#
Register
POST /auth/register
Create a new user account under the client identified by the API key.
{
"email": "user@example.com",
"password": "securepassword",
"name": "Jane Doe",
"voucherCode": "STUDIO-ABC123",
"sessionId": "onboarding-session-id",
"coachId": 5,
"profile": {
"age": 28,
"gender": "female",
"fitnessLevel": "intermediate"
},
"settings": {
"notifications": true
}
}
Only email and password are required. All other fields are optional.
{
"success": true,
"data": {
"user": {
"id": 1,
"email": "user@example.com",
"name": "Jane Doe",
"role": "user"
},
"accessToken": "eyJhbGciOi...",
"refreshToken": "eyJhbGciOi..."
}
}
Onboarding merge
If sessionId is provided, the pending onboarding profile is automatically merged into the new account. If voucherCode is provided, it is redeemed and the user is assigned to the voucher's partner client.
#
Login
POST /auth/login
Authenticate a user with email and password.
{
"email": "user@example.com",
"password": "securepassword"
}
{
"success": true,
"data": {
"user": {
"id": 1,
"email": "user@example.com",
"name": "Jane Doe",
"role": "user"
},
"accessToken": "eyJhbGciOi...",
"refreshToken": "eyJhbGciOi...",
"client": {
"id": 1,
"name": "Studio Name",
"branding": { }
}
}
}
Universal API key
When using the universal API key, the response includes a client object so the app knows which branding to apply. This enables a single mobile app to serve multiple studio clients.
#
Refresh Token
POST /auth/refresh
Exchange a refresh token for a new access token.
{
"refreshToken": "eyJhbGciOi..."
}
{
"success": true,
"data": {
"accessToken": "eyJhbGciOi..."
}
}
#
Logout
POST /auth/logout
Bearer
Stateless logout. The server does not invalidate tokens -- the client should discard stored tokens.
{
"success": true,
"data": {
"message": "Logged out successfully"
}
}
#
Current User
GET /auth/me
Get the current authenticated user. Requires both X-API-Key and Authorization: Bearer <token>.
{
"success": true,
"data": {
"user": {
"id": 1,
"email": "user@example.com",
"name": "Jane Doe",
"role": "user",
"profile": { },
"settings": { }
},
"client": {
"id": 1,
"name": "Studio Name"
}
}
}
#
Voucher Validation
#
Validate Code
POST /auth/voucher/validate
Validate a voucher code before registration. Requires X-API-Key only (no bearer token).
{
"code": "STUDIO-ABC123"
}
{
"success": true,
"data": {
"valid": true,
"partner": {
"name": "Partner Name",
"clientId": 1
}
}
}
#
Trainer Authentication
Trainer auth endpoints accept either X-API-Key or X-Master-Trainer-Key.
#
Check Email
POST /trainer-auth/check-email
Check if a trainer email is enabled for registration.
{
"email": "trainer@example.com"
}
{
"success": true,
"data": {
"exists": false,
"canRegister": true,
"trainer": { "id": 5, "name": "Coach Mike" }
}
}
#
Register Trainer
POST /trainer-auth/register
Register a trainer as a user account. The trainer record must already exist (created by admin).
{
"email": "trainer@example.com",
"password": "securepassword"
}
{
"success": true,
"data": {
"user": {
"id": 10,
"email": "trainer@example.com",
"name": "Coach Mike",
"role": "trainer"
},
"accessToken": "eyJhbGciOi...",
"refreshToken": "eyJhbGciOi..."
}
}
#
Trainer Login
POST /trainer-auth/login
Authenticate a trainer. Returns user tokens and trainer-specific information.
{
"email": "trainer@example.com",
"password": "securepassword"
}
{
"success": true,
"data": {
"user": {
"id": 10,
"email": "trainer@example.com",
"name": "Coach Mike",
"role": "trainer"
},
"trainer": {
"id": 5,
"name": "Coach Mike",
"specialisations": ["strength", "hiit"]
},
"accessToken": "eyJhbGciOi...",
"refreshToken": "eyJhbGciOi..."
}
}
#
Partner Staff Authentication
Partner auth endpoints do not require a client API key.
#
Login
POST /partner-auth/login
Authenticate a partner staff member. Returns JWT tokens with 8-hour expiry.
{
"email": "staff@partner.com",
"password": "securepassword"
}
{
"success": true,
"data": {
"staff": {
"id": 1,
"email": "staff@partner.com",
"name": "Staff Name",
"role": "admin",
"clientId": 1
},
"accessToken": "eyJhbGciOi...",
"refreshToken": "eyJhbGciOi..."
}
}
#
Refresh
POST /partner-auth/refresh
Refresh a partner staff access token.
{
"refreshToken": "eyJhbGciOi..."
}
{
"success": true,
"data": {
"accessToken": "eyJhbGciOi..."
}
}
#
Current Staff
GET /partner-auth/me
Partner JWT
Get the current authenticated partner staff member.
{
"success": true,
"data": {
"staff": {
"id": 1,
"email": "staff@partner.com",
"name": "Staff Name",
"role": "admin",
"clientId": 1,
"client": {
"id": 1,
"name": "Partner Studio"
}
}
}
}
#
Logout
POST /partner-auth/logout
Partner JWT
Stateless logout for partner staff. Discard stored tokens on the client side.
#
FAQ
How long do access tokens last?
Access tokens are short-lived JWTs. When a 401 response is received, call /auth/refresh with the stored refresh token to obtain a new access token.
What happens if a voucher code is invalid or expired?
The /auth/voucher/validate endpoint returns { "valid": false } with a reason. Registration with an invalid voucher code will be rejected with a 400 error.
Can a user belong to multiple clients?
No. Each user belongs to exactly one client. The client is determined at registration time by the API key (or voucher code for universal key flows).