Authorization header.
POST /api/v1/auth/request-verification
Send a verification email to begin the email-based signup flow. The token expires after 24 hours and the same email address is limited to 3 requests per hour.Request body
The email address to verify. Must be a valid email format and not already registered.
Response
Confirmation that the email was sent.
Seconds until the verification token expires. Currently
86400 (24 hours).POST /api/v1/auth/verify-token
Check whether a verification token is still valid and return the associated email address. Use this to prefill the registration form before the user submits their password.Request body
The verification token from the email link.
Response
true if the token exists and has not expired, false otherwise.The email address associated with the token. Only present when
valid is true.Human-readable reason the token is invalid. Only present when
valid is false.POST /api/v1/auth/complete-signup
Finish registration by consuming a valid verification token and setting a password. The token is deleted after a successful call — it cannot be reused.Request body
The verification token from the email link.
The user’s chosen password. Must be at least 8 characters and contain at least one uppercase letter, one lowercase letter, and one digit.
Response 201 Created
The Firebase UID assigned to the new user.
JWT access token for subsequent authenticated requests.
Always
"Bearer".ISO 8601 timestamp when the access token expires.
Account-level credentials record including roles and verification status.
Full user profile document created for the new account.
Always
true for this endpoint.POST /api/v1/auth/signup
Create or update a user account using a Firebase ID token. If the user already exists (for example they previously signed up on the mobile app), their membership role is updated instead of creating a duplicate account.Request body
A valid Firebase ID token obtained from Firebase Authentication on the client.
Desired username. 3–30 characters, letters, numbers, and underscores only. Auto-generated from the email prefix if omitted.
Optional profile fields to set on the new account. Only the fields listed below are accepted — any other fields are silently ignored.
| Field | Type | Description |
|---|---|---|
display_name | string | Public display name |
first_name | string | First name |
last_name | string | Last name |
membership_role | string | "athlete" or "coach" |
notification_settings | object | Notification preferences |
platform | string | Client platform identifier |
preferences | object | User preferences (timezone, language, unit system, etc.) |
Response 200 OK (existing user) / 201 Created (new user)
Same shape as complete-signup above, plus an is_new_user boolean indicating whether an account was created (true) or updated (false).
POST /api/v1/auth/token/refresh
Requires auth. Exchange the current access token for a new one. Call this before the current token expires to maintain a continuous session.Response
The new JWT access token.
Always
"Bearer".ISO 8601 timestamp when the new token expires.
GET /api/v1/auth/me
Requires auth. Return the authenticated user’s account credentials.Response
The user’s unique ID.
The user’s email address.
List of roles assigned to the account (e.g.
["user"], ["user", "coach"]).Whether the user’s email address has been verified.
Whether the account is active.
ISO 8601 timestamp of the last login.
POST /api/v1/auth/logout
Requires auth. Signal that the current session has ended. Because the API uses stateless JWTs, the server does not invalidate the token — the client is responsible for discarding it.Response
POST /api/v1/auth/password-reset
Request a password reset email. Always returns a success message regardless of whether the email is registered, to prevent user enumeration.Request body
The email address associated with the account.
Origin of the request.
"app" or "web". Defaults to "web". Controls which email template is sent.Response
POST /api/v1/auth/password-reset/confirm
Set a new password using the reset token from the email link.Request body
The password reset token from the email link.
The new password. Must be at least 8 characters long.