Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/azahel79/Spartans-gym/llms.txt

Use this file to discover all available pages before exploring further.

The Spartans Gym API uses stateless JSON Web Token (JWT) authentication. When a staff member logs in, the server signs a token containing their identity and role. That token must then be included in the Authorization header of every subsequent request to a protected endpoint. There are no sessions, cookies, or API keys — just the signed token.

How Bearer Authentication Works

After a successful login, include the token as a Bearer credential in every protected request:
# Use the token from login in all subsequent requests
curl https://YOUR_API/api/clients \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
The authenticate middleware on each protected route extracts the token from the Authorization header, verifies the signature against JWT_SECRET, and — if valid — attaches the decoded payload to req.user so controllers can read the caller’s id, email, and role.

Token Payload

Every JWT issued by the API contains the following claims:
ClaimTypeDescription
idnumberInternal database ID of the staff user
emailstringEmail address used to log in
role'admin' | 'recepcionista'Permission level determining resource access

Token Expiry

Tokens expire according to the JWT_EXPIRES_IN environment variable (default: 7d). After expiry the server returns 401 Unauthorized with "error": "Token inválido o expirado". The client must re-authenticate via POST /api/auth/login to obtain a fresh token.
Set JWT_EXPIRES_IN to a shorter value (e.g. 8h) in production environments to reduce the window of exposure if a token is ever leaked.

Endpoints

POST /api/auth/login

Authenticates a staff user by email and password, and returns a signed JWT alongside the user record (without the password hash). This is the only auth endpoint that does not require a token.
curl -X POST https://YOUR_API/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@spartansgym.com","password":"ChangeMe123!"}'

Request Body

email
string
required
The staff user’s registered email address.
password
string
required
The staff user’s plaintext password. Verified server-side against the stored bcrypt hash — never stored or logged.

Success Response 200

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "email": "admin@spartansgym.com",
      "role": "admin",
      "createdAt": "2024-01-10T08:00:00.000Z",
      "updatedAt": "2024-11-01T14:30:00.000Z"
    }
  }
}

Error Responses

Statuserror valueCause
400 Bad Request"Email y contraseña son requeridos"Either email or password was omitted from the request body
401 Unauthorized"Credenciales incorrectas"No user found with that email, or the password does not match the stored hash

GET /api/auth/me

Returns the database record for the currently authenticated user. Useful for bootstrapping a frontend session after a page load — call this endpoint with a stored token to confirm the token is still valid and retrieve fresh user data. Requires: Authorization: Bearer <token>
curl https://YOUR_API/api/auth/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Success Response 200

{
  "success": true,
  "data": {
    "id": 1,
    "email": "admin@spartansgym.com",
    "role": "admin",
    "createdAt": "2024-01-10T08:00:00.000Z"
  }
}
The updatedAt field is intentionally omitted from this response — only id, email, role, and createdAt are returned. The password hash is never included in any auth response.

Error Responses

Statuserror valueCause
401 Unauthorized"Token no proporcionado"Authorization header is missing or does not start with Bearer
401 Unauthorized"Token inválido o expirado"Token signature is invalid or the token has expired
404 Not Found"Usuario no encontrado"Token is valid but the user record no longer exists in the database

POST /api/auth/logout

Signals the client to discard the current session. Because the API is stateless, logout is handled entirely on the client side — the server does not maintain a denylist of revoked tokens. This endpoint simply confirms the action and returns a success message. Requires: Authorization: Bearer <token>
curl -X POST https://YOUR_API/api/auth/logout \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Success Response 200

{
  "success": true,
  "message": "Sesión cerrada correctamente"
}
Tokens are not invalidated server-side when logout is called. A token remains cryptographically valid until its exp claim is reached. If a token is compromised, the only way to revoke it immediately is to rotate the JWT_SECRET environment variable and restart the server — this invalidates all currently issued tokens at once.

Frontend Token Storage

The Spartans Gym frontend stores the JWT in Zustand state (in-memory). This means the token is held in JavaScript memory only and is automatically discarded when the browser tab is closed or the page is refreshed. There is no automatic persistence to localStorage or cookies unless the frontend is explicitly configured to do so.
1

Login

Call POST /api/auth/login and receive the data.token string in the response.
2

Store the token

Save the token in your Zustand auth store (or equivalent state manager). For persistent sessions across page refreshes, also write it to localStorage and rehydrate on startup.
3

Attach to requests

Add Authorization: Bearer <token> to every API call that targets a protected route.
4

Handle 401 responses

If any request returns 401, clear the stored token and redirect the user to the login screen to re-authenticate.
5

Logout

Call POST /api/auth/logout to notify the server (optional but good practice), then clear the token from state and any persisted storage.

Build docs developers (and LLMs) love