{
  "surface": "https://www.fitfo.app/a",
  "note": "Machine interface. If you are a person, use the FitFo app.",
  "actions": [
    {
      "id": "auth.login.view",
      "url": "/agent/login",
      "method": "GET",
      "description": "Show the pairing-code sign-in form.",
      "scope": null,
      "writes": false
    },
    {
      "id": "auth.login.submit",
      "url": "/agent/login",
      "method": "POST",
      "description": "Redeem a pairing code from the FitFo app for a scoped session.",
      "scope": null,
      "writes": true,
      "fields": [
        {
          "name": "code",
          "type": "text",
          "required": true,
          "description": "The pairing code shown in the app. Spaces and dashes are ignored."
        }
      ]
    },
    {
      "id": "auth.logout.submit",
      "url": "/agent/logout",
      "method": "POST",
      "description": "End this web session by clearing its cookie. Does not revoke the grant.",
      "scope": null,
      "writes": true
    },
    {
      "id": "orientation.view",
      "url": "/agent",
      "method": "GET",
      "description": "Who you are, streak, what is scheduled, links to everything.",
      "scope": null,
      "writes": false
    },
    {
      "id": "workout.history.view",
      "url": "/agent/workouts",
      "method": "GET",
      "description": "Logged workout history.",
      "scope": "workouts:read",
      "writes": false,
      "fields": [
        {
          "name": "limit",
          "type": "number",
          "description": "Query param."
        },
        {
          "name": "since",
          "type": "date",
          "description": "Query param."
        },
        {
          "name": "until",
          "type": "date",
          "description": "Query param."
        }
      ]
    },
    {
      "id": "workout.history.item.view",
      "url": "/agent/workouts/{id}",
      "method": "GET",
      "description": "One logged session, every set.",
      "scope": "workouts:read",
      "writes": false
    },
    {
      "id": "workout.log.view",
      "url": "/agent/log",
      "method": "GET",
      "description": "A textarea for writing a workout as text or JSON.",
      "scope": null,
      "writes": false,
      "fields": [
        {
          "name": "draft",
          "type": "hidden",
          "description": "Optional: re-open a prior draft to edit."
        }
      ]
    },
    {
      "id": "workout.log.submit",
      "url": "/agent/log",
      "method": "POST",
      "description": "Parse a workout written as plain text (one exercise per line) or JSON. Redirects to a preview; does not log anything yet.",
      "scope": null,
      "writes": true,
      "fields": [
        {
          "name": "workout",
          "type": "textarea",
          "required": true,
          "description": "Plain text, one exercise per line ('Bench press 3x5 @185'), or a JSON object with title/notes/exercises."
        }
      ]
    },
    {
      "id": "workout.log.preview.view",
      "url": "/agent/log/preview",
      "method": "GET",
      "description": "Parsed result: each exercise resolved against the catalog, sets, and anything unresolved flagged.",
      "scope": "workouts:read",
      "writes": false,
      "fields": [
        {
          "name": "draft",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "workout.log.preview.confirm",
      "url": "/agent/log/preview",
      "method": "POST",
      "description": "Log the previewed workout. Idempotency-Key is derived from the draft, so a double submit cannot double-log.",
      "scope": "workouts:write",
      "writes": true,
      "fields": [
        {
          "name": "draft",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "workout.log.preview.edit",
      "url": "/agent/log/preview",
      "method": "POST",
      "description": "Go back to /a/log with the original text reloaded for editing.",
      "scope": null,
      "writes": true,
      "fields": [
        {
          "name": "draft",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "workout.log.done.view",
      "url": "/agent/log/done",
      "method": "GET",
      "description": "States what happened: points awarded, streak now N, and the side effects note.",
      "scope": null,
      "writes": false
    },
    {
      "id": "schedule.list.view",
      "url": "/agent/schedule",
      "method": "GET",
      "description": "Planned workouts in a date range.",
      "scope": "workouts:read",
      "writes": false,
      "fields": [
        {
          "name": "start",
          "type": "date",
          "description": "Query param, YYYY-MM-DD."
        },
        {
          "name": "end",
          "type": "date",
          "description": "Query param, YYYY-MM-DD."
        }
      ]
    },
    {
      "id": "schedule.new.view",
      "url": "/agent/schedule/new",
      "method": "GET",
      "description": "Form to put a workout on a date.",
      "scope": null,
      "writes": false
    },
    {
      "id": "schedule.create",
      "url": "/agent/schedule/new",
      "method": "POST",
      "description": "Put a workout on the calendar.",
      "scope": "schedule:write",
      "writes": true,
      "fields": [
        {
          "name": "title",
          "type": "text",
          "required": true
        },
        {
          "name": "scheduled_for",
          "type": "date",
          "required": true,
          "description": "YYYY-MM-DD"
        },
        {
          "name": "scheduled_time_minutes",
          "type": "number",
          "description": "Minutes after midnight, optional."
        },
        {
          "name": "description",
          "type": "textarea"
        },
        {
          "name": "_nonce",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "schedule.item.view",
      "url": "/agent/schedule/{id}",
      "method": "GET",
      "description": "One scheduled workout, with a form to move it and a link to cancel it.",
      "scope": "workouts:read",
      "writes": false
    },
    {
      "id": "schedule.move",
      "url": "/agent/schedule/{id}",
      "method": "POST",
      "description": "Change the date or time of a scheduled workout.",
      "scope": "schedule:write",
      "writes": true,
      "fields": [
        {
          "name": "scheduled_for",
          "type": "date",
          "required": true
        },
        {
          "name": "scheduled_time_minutes",
          "type": "number"
        },
        {
          "name": "_nonce",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "schedule.cancel.view",
      "url": "/agent/schedule/{id}/cancel",
      "method": "GET",
      "description": "Confirm page for canceling a scheduled workout. Never a one-click link.",
      "scope": "workouts:read",
      "writes": false
    },
    {
      "id": "schedule.cancel.confirm",
      "url": "/agent/schedule/{id}/cancel",
      "method": "POST",
      "description": "Cancel the scheduled workout.",
      "scope": "schedule:write",
      "writes": true,
      "fields": [
        {
          "name": "_nonce",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "exercises.search.view",
      "url": "/agent/exercises",
      "method": "GET",
      "description": "Search and resolve exercises against the catalog.",
      "scope": "workouts:read",
      "writes": false,
      "fields": [
        {
          "name": "q",
          "type": "text",
          "description": "Query param."
        }
      ]
    },
    {
      "id": "progress.view",
      "url": "/agent/progress",
      "method": "GET",
      "description": "PRs, weekly volume, frequency, body-weight trend.",
      "scope": "progress:read",
      "writes": false
    },
    {
      "id": "recovery.view",
      "url": "/agent/recovery",
      "method": "GET",
      "description": "Per-muscle fatigue from logged training.",
      "scope": "recovery:read",
      "writes": false
    },
    {
      "id": "fuel.view",
      "url": "/agent/fuel",
      "method": "GET",
      "description": "Today's macros and entries.",
      "scope": "nutrition:read",
      "writes": false
    },
    {
      "id": "fuel.log.view",
      "url": "/agent/fuel/log",
      "method": "GET",
      "description": "Three small forms: log a meal, log water, log steps.",
      "scope": null,
      "writes": false
    },
    {
      "id": "fuel.log.meal",
      "url": "/agent/fuel/log",
      "method": "POST",
      "description": "Log a meal by name (and, optionally, its macros).",
      "scope": "nutrition:write",
      "writes": true,
      "fields": [
        {
          "name": "kind",
          "type": "hidden",
          "required": true
        },
        {
          "name": "food_name",
          "type": "text",
          "required": true
        },
        {
          "name": "meal_type",
          "type": "select",
          "options": [
            "breakfast",
            "lunch",
            "dinner",
            "snack"
          ]
        },
        {
          "name": "portion_label",
          "type": "text"
        },
        {
          "name": "calories",
          "type": "number"
        },
        {
          "name": "protein_g",
          "type": "number"
        },
        {
          "name": "carbs_g",
          "type": "number"
        },
        {
          "name": "fat_g",
          "type": "number"
        },
        {
          "name": "notes",
          "type": "text"
        },
        {
          "name": "logged_on",
          "type": "date",
          "description": "Defaults to today."
        },
        {
          "name": "_nonce",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "fuel.log.water",
      "url": "/agent/fuel/log",
      "method": "POST",
      "description": "Log water in ounces.",
      "scope": "nutrition:write",
      "writes": true,
      "fields": [
        {
          "name": "kind",
          "type": "hidden",
          "required": true
        },
        {
          "name": "water_oz",
          "type": "number",
          "required": true
        },
        {
          "name": "logged_on",
          "type": "date",
          "description": "Defaults to today."
        },
        {
          "name": "_nonce",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "fuel.log.steps",
      "url": "/agent/fuel/log",
      "method": "POST",
      "description": "Log a step count.",
      "scope": "nutrition:write",
      "writes": true,
      "fields": [
        {
          "name": "kind",
          "type": "hidden",
          "required": true
        },
        {
          "name": "steps",
          "type": "number",
          "required": true
        },
        {
          "name": "source",
          "type": "text",
          "description": "Defaults to \"manual\"."
        },
        {
          "name": "logged_on",
          "type": "date",
          "description": "Defaults to today."
        },
        {
          "name": "_nonce",
          "type": "hidden",
          "required": true
        }
      ]
    },
    {
      "id": "actions.index",
      "url": "/agent/actions.json",
      "method": "GET",
      "description": "Every action on this surface: URL, method, fields, what it does, what it costs.",
      "scope": null,
      "writes": false
    }
  ]
}