# API Reference All endpoints return HTML (full pages or HTMX partials) unless noted otherwise. Protected routes require a valid admin session cookie. --- ## Authentication ### `GET /login` Render the login form. - **Auth:** None - **Response:** Full page (`pages/login.html`) ### `POST /login` Authenticate admin credentials and start a session. - **Auth:** None - **Content-Type:** `application/x-www-form-urlencoded` - **Form fields:** - `username` (string) — admin username - `password` (string) — admin password - **Success:** 303 redirect to `/`, sets `session` cookie (httponly, samesite=lax, 24h TTL) - **Failure:** 200 with login page re-rendered and error message ### `GET /logout` End the admin session. - **Auth:** None (clears cookies regardless) - **Response:** 303 redirect to `/login`, deletes `session` and `active_profile_id` cookies --- ## Health ### `GET /health` Application health check for monitoring and readiness probes. - **Auth:** None - **Response:** JSON ```json { "app": "sneakyswole", "version": "0.1.0", "status": "ok" } ``` --- ## Pages ### `GET /` Home page. - **Auth:** None - **Response:** Full page (`pages/home.html`) --- ## Profiles All profile routes require admin authentication. ### `GET /profiles` List all user profiles (excludes admin). - **Auth:** Admin session - **Response:** Full page (`pages/profiles.html`) - **Template context:** `profiles`, `active_profile_id`, `admin` ### `POST /profiles/switch` Switch the active user profile. - **Auth:** Admin session - **Content-Type:** `application/x-www-form-urlencoded` - **Form fields:** - `profile_id` (string) — ID of the profile to activate - **Response:** 303 redirect to referring page, sets `active_profile_id` cookie ### `GET /profiles/{profile_id}/edit` Render the profile edit form. - **Auth:** Admin session - **Path params:** `profile_id` (int) - **Response:** Full page (`pages/profile_edit.html`) ### `POST /profiles/{profile_id}/edit` Update a user profile. - **Auth:** Admin session - **Path params:** `profile_id` (int) - **Content-Type:** `application/x-www-form-urlencoded` - **Form fields:** - `display_name` (string) - `height` (string) - `weight` (string) - `goals` (string) - **Response:** 303 redirect to `/profiles` --- ## Workouts All workout routes require admin authentication. ### `GET /workouts` List all workout days as clickable cards. - **Auth:** Admin session - **Response:** Full page (`pages/workout_days.html`) - **Template context:** `days`, `admin` ### `GET /workouts/{day_name}` Display a full workout day with warmups, exercises, programming targets, and inline logging. - **Auth:** Admin session - **Path params:** `day_name` (string) — URL-friendly name, e.g., "push", "pull", "lower", "full-body" - **Response:** Full page (`pages/workout_day.html`) - **Template context:** `day_name`, `warmups`, `exercises`, `programs`, `active_profile`, `existing_logs`, `suggestions`, `workout_day_id`, `admin` - **Notes:** Day name is normalized (e.g., "full-body" → "Full Body"). If an active profile is set, includes programming targets, progression suggestions, and today's existing logs. --- ## Exercises All exercise routes require admin authentication. ### `GET /exercises` Render the exercise browser with filter dropdowns. - **Auth:** Admin session - **Response:** Full page (`pages/exercise_browser.html`) - **Template context:** `exercises`, `workout_days`, `muscle_groups`, `admin` ### `GET /exercises/search` HTMX partial — return filtered exercise list. - **Auth:** Admin session - **Query params:** - `workout_day` (string, optional) — filter by workout day name - `muscle_group` (string, optional) — filter by muscle group - **Response:** HTMX partial (`partials/exercise_list.html`) - **Usage:** Called via `hx-get` from exercise browser filter dropdowns --- ## Workout Logging All logging routes require admin authentication. Responses are HTMX partials that update inline. ### `POST /log` Log a single set for an exercise. Auto-creates today's workout session if needed. - **Auth:** Admin session - **Content-Type:** `application/x-www-form-urlencoded` - **Form fields:** - `exercise_id` (int) - `workout_day_id` (int) - `set_number` (int, default=1) - `reps` (int) - `weight` (string) — e.g., "30 lbs", "BW" - `felt_easy` (checkbox, "on" = true) - **Response:** HTMX partial (`partials/log_entry.html`) with updated logs for this exercise - **Error:** If no active profile selected, returns `partials/flash_message.html` with error ### `POST /log/{log_id}/edit` Edit an existing log entry. - **Auth:** Admin session - **Path params:** `log_id` (int) - **Content-Type:** `application/x-www-form-urlencoded` - **Form fields:** - `reps` (int) - `weight` (string) - `felt_easy` (checkbox) - `notes` (string, optional) - **Response:** HTMX partial (`partials/log_entry.html`) with updated logs ### `POST /log/{log_id}/delete` Delete a log entry. - **Auth:** Admin session - **Path params:** `log_id` (int) - **Response:** HTMX partial (`partials/log_entry.html`) with remaining logs, or empty HTML if log not found --- ## History All history routes require admin authentication. ### `GET /history` Display log history for the active profile — list of past sessions, most recent first. - **Auth:** Admin session - **Response:** Full page (`pages/log_history.html`) - **Template context:** `sessions`, `days_by_id`, `active_profile`, `admin` - **Notes:** Requires active profile to show sessions ### `GET /history/{session_id}` Display detailed logs for a specific workout session, grouped by exercise. - **Auth:** Admin session - **Path params:** `session_id` (int) - **Response:** Full page (`pages/session_detail.html`) - **Template context:** `workout_session`, `logs_by_exercise`, `exercises_by_id`, `days_by_id`, `admin` --- ## Dashboard All dashboard routes require admin authentication. ### `GET /dashboard` Render the progress dashboard with summary stats, volume chart, and exercise links. - **Auth:** Admin session - **Response:** Full page (`pages/dashboard.html`) - **Template context:** `stats`, `volume_data_json`, `exercises`, `active_profile`, `admin` - **Notes:** Stats and volume data require an active profile. Chart.js renders client-side charts from JSON embedded in the template. ### `GET /dashboard/exercise/{exercise_id}` Per-exercise progress page with charts and progression suggestions. - **Auth:** Admin session - **Path params:** `exercise_id` (int) - **Response:** Full page (`pages/exercise_progress.html`) - **Template context:** `exercise`, `progress_data_json`, `suggestion`, `active_profile`, `admin` --- ## Schedule ### `GET /schedule` 4-week calendar view showing which workout day maps to which date. - **Auth:** Admin session - **Response:** Full page (`pages/schedule.html`) - **Template context:** `weeks`, `active_profile`, `admin` - **Notes:** Calendar starts from Monday of the current week. Days with completed sessions are highlighted. Requires active profile for session completion data. --- ## Authentication Details ### Cookies | Cookie | Purpose | Flags | TTL | |--------|---------|-------|-----| | `session` | Admin session token (itsdangerous signed) | httponly, samesite=lax | 24 hours | | `active_profile_id` | Currently selected user profile ID | httponly, samesite=lax | 24 hours | ### Auth Failure Behavior - Missing or invalid session cookie → 302 redirect to `/login` - Handled via `NotAuthenticatedError` exception + registered handler in `app/main.py`