# API Documentation ## REST APIs ### Authentication #### POST /auth/login - **Method**: POST - **Path**: `/auth/login` - **Purpose**: Authenticate a user and receive JWT tokens - **Authorization**: Anonymous - **Request**: `{ "email": string, "password": string }` - **Response**: `{ "accessToken": string, "expiresAt": datetime, "user": { "id": guid, "email": string, "name": string, "role": string, "isActive": bool } }` - **Cookie set**: `refreshToken` (httpOnly, Secure, SameSite=Strict, Path=/api/v1/auth) #### POST /auth/refresh - **Method**: POST - **Path**: `/auth/refresh` - **Purpose**: Refresh an access token using the httpOnly refresh token cookie - **Authorization**: Anonymous - **Request**: (empty body — refresh token read from cookie) - **Response**: Same as `/auth/login` (new access token + new cookie) #### POST /auth/revoke - **Method**: POST - **Path**: `/auth/revoke` - **Purpose**: Revoke a refresh token (logout) - **Authorization**: Bearer JWT required - **Request**: `""` (string body) - **Response**: 204 No Content --- ### Setup #### GET /setup/status - **Method**: GET - **Path**: `/setup/status` - **Purpose**: Check if the system has been initialized (first owner created) - **Authorization**: Anonymous - **Response**: `{ "initialized": boolean }` #### POST /setup/owner - **Method**: POST - **Path**: `/setup/owner` - **Purpose**: Create the initial Owner account (only usable when system is not yet initialized) - **Authorization**: Anonymous - **Request**: `{ "email": string, "password": string }` - **Response**: `{ "message": string }` --- ### Users #### POST /users/invite - **Method**: POST - **Path**: `/users/invite` - **Purpose**: Invite a new user by email with a specified role - **Authorization**: Bearer JWT, Policy: AdminOnly - **Request**: `{ "email": string, "role": string }` - **Response**: `{ "inviteLink": string }` #### POST /users/complete-setup - **Method**: POST - **Path**: `/users/complete-setup` - **Purpose**: Complete account setup using an invitation token - **Authorization**: Anonymous - **Request**: `{ "token": string, "password": string }` - **Response**: `{ "message": string }` #### GET /users/validate-invitation - **Method**: GET - **Path**: `/users/validate-invitation?token={token}` - **Purpose**: Validate an invitation token before showing the setup form - **Authorization**: Anonymous - **Response**: `{ "valid": boolean, "email": string, "role": string }` or error --- ### Availability #### GET /availability/status - **Method**: GET - **Path**: `/availability/status` - **Purpose**: Get current system availability status - **Authorization**: Anonymous - **Response**: `{ "status": "Available|Maintenance|Unavailable", "checkedAt": datetime, "message": string }` #### POST /availability/admin/status - **Method**: POST - **Path**: `/availability/admin/status` - **Purpose**: Update the system availability status - **Authorization**: Bearer JWT, Policy: OwnerOnly - **Request**: `{ "newStatus": "Available|Maintenance|Unavailable", "reason": string }` - **Response**: 200 OK or 400 Bad Request --- ## Authorization Policies | Policy | Required Role | Description | |--------|--------------|-------------| | `OwnerOnly` | Owner | Full system access including availability management | | `AdminOnly` | Owner or Admin | User management access | ## Data Models ### AuthResponse - `accessToken` — short-lived JWT (e.g. 15 min) - `refreshToken` — long-lived opaque token - `expiresAt` — access token expiry datetime - `user` — authenticated user info ### Password Validation Rules (enforced by backend) Configured in `ServiceCollectionExtensions.cs` via ASP.NET Core Identity `PasswordOptions`: - `RequiredLength = 8` — minimum 8 characters - `RequireUppercase = true` — at least 1 uppercase letter - `RequireLowercase = true` — at least 1 lowercase letter - `RequireDigit = true` — at least 1 digit - `RequireNonAlphanumeric = true` — at least 1 non-alphanumeric character (e.g. `!@#$%^&*`) ### ApplicationUser (returned in auth responses) - `id` — Guid - `email` — string - `name` — string (display name) - `role` — string (Owner / Admin / User) - `isActive` — boolean ### Invitation - `token` — string (URL-safe token) - `email` — string - `role` — string - `expiryDate` — datetime - `isUsed` — boolean