# Airon: instructions for AI agents This site is a workout tracker (an installable web app). Users ask you to make them a workout; you turn it into a short import code by calling the API below, and the user pastes that code into the app's **Import** button. You do not need to run the app or use a browser. Just call the API. ## Steps 1. Design the workout the user asked for. 2. Send it as JSON to the encode endpoint (either form works): - `POST /api/encode` with `Content-Type: application/json` and the JSON as the body - `GET /api/encode?w=` if you can only make GET requests 3. The response contains a `code` starting with `WK1-`. Give it to the user **exactly as returned, in a code block**. Tell them to open the app, tap **Import**, and paste it. 4. If the response has `errors`, fix the fields listed (each has a `path` such as `exercises[2].reps`) and call the endpoint again. If you cannot call the API at all, give the user the workout JSON itself in a code block instead. The Import button accepts that too. The app logs what the user actually lifted. Users may paste their recent history (it starts with "My recent workout history"); use it to pick weights and progress sensibly from what they did last time. ## JSON format ```json { "title": "Push Day A", "unit": "kg", "notes": "Warm up first. Stop 1-2 reps short of failure.", "rest": 90, "exercises": [ { "name": "Bench Press", "sets": 4, "reps": 8, "weight": 60, "rest": 150 }, { "name": "Overhead Press", "sets": [ { "reps": 5, "weight": 40 }, { "reps": 5, "weight": 42.5 }, { "reps": 3, "weight": 45 } ] }, { "name": "Incline Dumbbell Press", "sets": 3, "reps": "8-12", "weight": 22.5, "notes": "Weight is per dumbbell" }, { "name": "Dips", "sets": 3, "reps": "AMRAP", "weight": "BW", "superset": "A" }, { "name": "Plank", "sets": 3, "reps": "45s", "superset": "A" } ] } ``` ### Fields Workout: | Field | Required | Description | |---|---|---| | `title` | yes | Up to 100 characters. | | `unit` | no | `"kg"` (default) or `"lb"`. Applies to every weight in the workout. | | `notes` | no | Up to 1000 characters. Warm-up, goals, etc. | | `rest` | no | Rest between sets for the whole workout, in seconds (`90`) or as `"90s"` / `"1:30"`. The app starts a rest timer after each set. | | `exercises` | yes | 1 to 50 exercises, in order. | Exercise: | Field | Required | Description | |---|---|---| | `name` | yes | Up to 80 characters. | | `sets` | yes | Either a number of identical sets (1 to 30), or an array of set objects `{ "reps": ..., "weight": ... }` when sets differ. | | `reps` | when `sets` is a number | The reps for every set. In a set array it is the default for sets that omit `reps`. | | `weight` | no | The weight for every set; in a set array it is the default for sets that omit `weight`. Omit for no weight. | | `rest` | no | Rest between sets for this exercise; overrides the workout's `rest`. Same format. | | `superset` | no | A label like `"A"`. Exercises next to each other with the same label form a superset: the user alternates their sets and rests after each round. | | `notes` | no | Up to 500 characters. Tempo, cues, per-dumbbell, etc. | Reps can be: - a whole number: `8` - a range: `"8-12"` - `"AMRAP"` (as many reps as possible) - a duration for timed sets: `"45s"`, `"90s"` or `"1:30"` Weight can be: - a number in the workout's unit: `60`, `22.5` - `"BW"` for bodyweight - `"BW+10"` for bodyweight plus added weight - omitted (or `null`) when there is no load, e.g. for stretches or cardio Use the same exercise names from one workout to the next (e.g. always "Bench Press", not sometimes "Barbell Bench Press"); the app tracks progress per exercise name. Other fields (tempo, RPE, ...) are not part of the format. Put that information in `notes`. Unknown fields are ignored and reported as `warnings`. ## Programs (several workouts) For a split or a weekly plan, send a program instead: an object with a `title`, optional `notes`, and a `workouts` array of 1 to 14 workouts in the format above. The user does them in order; the app suggests the next one. The response `code` then starts with `WP1-` and imports all workouts at once. ```json { "title": "Push Pull Legs", "notes": "Run it twice a week. Add 2.5 kg when you hit the top of a rep range.", "workouts": [ { "title": "Push", "rest": 120, "exercises": [ { "name": "Bench Press", "sets": 3, "reps": "6-8", "weight": 70 }, { "name": "Overhead Press", "sets": 3, "reps": "8-10", "weight": 40 } ] }, { "title": "Pull", "rest": 120, "exercises": [ { "name": "Barbell Row", "sets": 3, "reps": "8-10", "weight": 60 }, { "name": "Pull-ups", "sets": 3, "reps": "AMRAP", "weight": "BW" } ] }, { "title": "Legs", "rest": 150, "exercises": [ { "name": "Squat", "sets": 3, "reps": 5, "weight": 100 }, { "name": "Romanian Deadlift", "sets": 3, "reps": "8-10", "weight": 80 } ] } ] } ``` Program codes are longer than workout codes. Keep notes short, and copy the code exactly; the app detects copy mistakes. ## Response Success (HTTP 200): ```json { "code": "WK1-…", "summary": "Push Day A: 5 exercises, 16 sets", "warnings": [], "instructions": "Give the user the code exactly as shown, in a code block. They import it with the Import button in the app." } ``` Error (HTTP 400): every problem is listed at once. ```json { "error": "invalid workout", "errors": [{ "path": "exercises[1].reps", "message": "is required when \"sets\" is a number" }], "docs": "/llms.txt" } ``` ## Other endpoints - `GET /api/decode?code=WK1-…` (or `WP1-…`) returns the workout or program inside a code, useful for checking a code before giving it to the user.