Documentation
Agent guide and API reference

Fitness Dashboard — Agent Documentation

Complete guide for AI agents operating Sandy's fitness tracking system. This documentation covers the training philosophy, available data, API operations, and recommended workflows.

Quick Start for Agents

  1. Read the Training Philosophy — understand the four-vector model
  2. Review Context Sources — know what data is available
  3. Study Common Workflows — learn how to design workouts
  4. Reference API Documentation — for implementation details

Training Philosophy

Sandy trains with a four-vector model. Every workout must contribute to at least one vector. These vectors are fixed — do not invent new ones.

VectorWhat It MeasuresUnit
StrengthPeak load per movement planekg
EnduranceTotal session volume (sets × reps × weight)kg
EfficiencyVolume per minute of working timekg/min
MobilityQuality of movement, range, symmetryQualitative (Good/Fair/Poor)

Movement Planes

Every exercise maps to exactly one movement plane:

  • Push — Horizontal pushing (push-ups, bench press)
  • Pull — Horizontal pulling (rows, pull-ups)
  • Press — Vertical pushing (overhead press, lateral raises)
  • Hinge — Hip hinge (swings, deadlifts, cleans, get-ups)
  • Squat — Bilateral squat pattern (goblet squats)
  • SideSquat — Unilateral/lateral squat (cossacks, side lunges)
  • Twist — Rotational/anti-rotational (windmills, Turkish get-ups)
  • Run — Locomotion (sprints, running)

Authentication

Every API call requires authentication. Prefer JWT tokens via the Authorization: Bearer <token> header. Legacy API key fallback uses X-API-Key.

Base URLs

  • Production: https://fitness-dashboard.netlify.app/api
  • Local Dev: http://localhost:8888/api

How Agents Should Operate

Core Principles

  1. Read before writing — Always check existing data (goals, recent workouts, equipment) before making recommendations
  2. Respect the four vectors — Every workout design must address at least one vector
  3. Use correct movement planes — Never invent new planes; use the 8 defined ones
  4. Work within equipment constraints — Only recommend exercises with available equipment
  5. Track progress toward goals — Reference active goals when giving advice

Designing a Workout

When designing a new workout, agents should:

  1. Query /goals — identify active targets
  2. Query /equipment — know what's available
  3. Query recent /workouts — see what was done recently
  4. Query /analytics/summary — understand current capacity
  5. Design balanced workout covering needed vectors
  6. POST to /workouts with status planned

Logging a Completed Workout

  1. Take raw input from user (what they did)
  2. Parse into structured exercises with movement planes
  3. Calculate volume (sets × reps × weight)
  4. POST to /workouts with status logged
  5. POST exercises linked to workout
  6. Update workout with analysed status when complete

Context Sources

Agents have access to the following data sources to inform decisions:

SourceEndpointPurpose
Active GoalsGET /goalsWhat vectors/planes to prioritize
Equipment InventoryGET /equipmentWhat weights/tools are available
Workout HistoryGET /workoutsRecent training patterns
Analytics SummaryGET /analytics/summaryAggregate stats by vector/plane
Agent OutputsGET /agent-outputsPrevious advice and analyses
Meta AnalysisGET /analysis-cyclesPeriodic aggregated insights

Common Workflows

1. Design Next Workout

// Step 1: Get context
GET /goals?status=Active
GET /equipment
GET /workouts?limit=5&status=analysed
GET /analytics/summary

// Step 2: Analyze gaps
- Which goals are behind?
- Which planes haven't been trained recently?
- What equipment is available?

// Step 3: Design workout
POST /workouts
{
  "date": "2026-04-23",
  "type": "KB",
  "status": "planned",
  "title": "KB Push/Pull Focus",
  "intensity": "Moderate",
  "exercises": [...]
}

2. Log Completed Workout

// Step 1: Create workout entry
POST /workouts
{
  "date": "2026-04-23",
  "type": "KB",
  "status": "logged",
  "duration_minutes": 35,
  "intensity": "Hard",
  "notes": "User raw input: '8:15 start. 5x10 double cleans @ 12kg...'"
}

// Step 2: Add exercises
POST /exercises (for each exercise)
{
  "workout_id": "w_xxx",
  "name": "Double KB Cleans",
  "movement_plane": "Hinge",
  "actual_sets": 5,
  "actual_reps": 10,
  "actual_weight_kg": 24,
  "volume_kg": 1200,
  "status": "completed"
}

// Step 3: Upload photo to Netlify Blobs
POST /api/blobs/upload
{ "data": "base64encodedstring...", "content_type": "image/jpeg" }

// Step 4: Attach blob key to workout
PUT /workouts/w_xxx
{ "photo_key": "blob_xxx..." }

// Step 5: Mark complete
PUT /workouts/w_xxx
{ "status": "analysed" }

3. Generate Periodic Analysis

// Step 1: Get recent completed workouts
GET /workouts?status=analysed&date_from=2026-04-01

// Step 2: Analyze patterns
- Volume trends
- Plane coverage
- Goal progress
- Strength/efficiency changes

// Step 3: Store meta-analysis
POST /analysis-cycles
{
  "start_date": "2026-04-01",
  "end_date": "2026-04-21",
  "workouts_analyzed": 12,
  "summary": "Weekly analysis...",
  "recommendations": "Next week focus on..."
}

API Overview

The REST API follows standard patterns with JSON request/response bodies. All endpoints require authentication.

Response Format

{
  "data": [...],      // Array of results
  "total": 42,        // Total count (for pagination)
  "limit": 20,        // Page size
  "offset": 0         // Current offset
}

Error Format

{
  "error": "NotFound",
  "message": "Workout not found"
}

Workouts API

MethodEndpointDescription
GET /workouts List workouts with optional filters
POST /workouts Create new workout
GET /workouts/:id Get single workout with exercises
PUT /workouts/:id Update workout
DELETE /workouts/:id Delete workout

Query Parameters

  • type — Filter by workout type (KB, GYM, PB, Yoga, Other)
  • status — Filter by status (planned, logged, analysed). Comma-separated for multiple.
  • date_from — Start date (YYYY-MM-DD)
  • date_to — End date (YYYY-MM-DD)
  • limit — Page size (default 20)
  • offset — Pagination offset

Workout Statuses

  • planned — Future workout, not yet performed
  • logged — Completed but awaiting analysis
  • analysed — Fully processed and counted

Exercises API

Exercises are always linked to a workout. They represent individual movements with volume tracking.

MethodEndpointDescription
GET /workouts/:id/exercises List exercises for a workout
POST /exercises Add exercise to workout
PUT /exercises/:id Update exercise
DELETE /exercises/:id Delete exercise

Exercise Fields

  • name — Exercise name (e.g., "Double KB Cleans")
  • movement_plane — One of: Push, Pull, Press, Hinge, Squat, SideSquat, Twist, Run
  • planned_sets/reps/weight — Targets for the exercise
  • actual_sets/reps/weight — What was actually done
  • volume_kg — Calculated: sets × reps × weight
  • status — completed, modified, skipped

Equipment API

Inventory of available fitness equipment. Used by agents to design feasible workouts.

MethodEndpointDescription
GET /equipment List all equipment
POST /equipment Add new equipment
PUT /equipment/:id Update equipment
DELETE /equipment/:id Delete equipment

Categories

  • KB — Kettlebells
  • DB — Dumbbells
  • Barbell — Barbells and plates
  • Machine — Weight machines
  • Other — Miscellaneous equipment

Goals API

Goal tracking organized by training vector and optional movement plane.

MethodEndpointDescription
GET /goals List all goals
POST /goals Create new goal
GET /goals/:id Get single goal
PUT /goals/:id Update goal progress
DELETE /goals/:id Delete goal

Goal Vectors

  • Strength — Peak load targets
  • Endurance — Total volume targets
  • Efficiency — kg/min targets
  • Mobility — Range/quality targets

Goal Statuses

  • Active — Currently pursuing
  • Achieved — Target reached
  • Paused — Temporarily suspended
  • Abandoned — No longer pursuing

Analytics API

Aggregate statistics for tracking progress across vectors and movement planes.

GET /analytics/summary

Returns aggregate metrics. Optionally filter by date range with date_from and date_to query params.

{
  "total_workouts": 42,
  "total_volume_kg": 45000,
  "avg_efficiency": 145.5,
  "by_type": { "KB": 35, "GYM": 7 },
  "by_vector": {
    "Strength": { "peak_load_kg": 60, "exercises": 120 },
    "Endurance": { "total_volume_kg": 45000 },
    "Efficiency": { "avg_kg_per_min": 145.5 },
    "Mobility": { "sessions_count": 42 }
  },
  "by_movement_plane": {
    "Hinge": { "total_volume": 15000, "peak_load": 60 },
    "Press": { "total_volume": 8000, "peak_load": 32 }
  }
}

Data Model Reference

Workouts Table

FieldTypeDescription
idTEXTUnique identifier
titleTEXTHuman-readable workout name
dateDATEWorkout date (YYYY-MM-DD)
typeTEXTKB, GYM, PB, Yoga, Other
statusTEXTplanned, logged, analysed
intensityTEXTLight, Moderate, Hard
duration_minutesINTEGERTotal session time
working_time_minutesINTEGERActive work time only
total_volume_kgREALSum of all exercise volumes
efficiency_kg_per_minREALVolume / working_time
notesTEXTUser or agent notes
photo_urlTEXTWorkout photo blob key

Exercises Table

FieldTypeDescription
idTEXTUnique identifier
workout_idTEXTParent workout reference
nameTEXTExercise name
movement_planeTEXTPush, Pull, Press, Hinge, Squat, SideSquat, Twist, Run
planned_sets/reps/weightINTEGER/REALTarget values
actual_sets/reps/weightINTEGER/REALActual values
volume_kgREALCalculated: sets × reps × weight
statusTEXTcompleted, modified, skipped
order_indexINTEGERSequence in workout

Statuses & Enums

Photo Upload

Photos are uploaded via Netlify Blobs. The frontend uploads the file to POST /api/blobs/upload, which returns a blob key. The photo_url field on the workout stores this key.

To display a photo, use GET /api/blobs/<key>. Agents should use the blob endpoints rather than storing base64 data in the database.

Workout Status Lifecycle

planned → logged → analysed
  • planned — Workout designed but not yet performed. Shows in "Next Workout" box.
  • logged — Workout completed but data not fully processed. Not counted in analytics.
  • analysed — Fully processed workout. Counted in all statistics and analytics.

Exercise Status

  • completed — Done as planned
  • modified — Changed during workout (different reps/weight)
  • skipped — Not performed

Workout Types

  • KB — Kettlebell training
  • GYM — Gym/machine work
  • PB — Plyo/box work
  • Yoga — Yoga session
  • Other — Miscellaneous