Developer docs

Agent API

Give an external AI agent narrow access to training context and confirmed actions. The app stays the source of truth; the agent supplies structured requests and the API validates them.

Authentication

Requests use a bearer token created from Settings. Tokens start withtra_live_and are stored in the database as hashes. The full token is only shown once.

curl https://training.cjarhodes.com/api/agent/today \
  -H "Authorization: Bearer tra_live_..." \
  -H "Accept: application/json"

Create a token

In the app

  1. 1. Go to Settings.
  2. 2. Open Agent access.
  3. 3. Select the scopes the agent needs.
  4. 4. Store the token in the agent's secret store.

Available scopes

Scopes are independent. Give OpenClaw only the actions it should perform.

read:todayread:weekread:contextwrite:wodwrite:checkinwrite:completionwrite:availabilitywrite:sorenesswrite:plannerwrite:profilewrite:racessync:refresh

Endpoints

GET/api/agent/todayread:today

Today workout and check-in status.

GET/api/agent/weekread:week

Current or requested training week.

GET/api/agent/contextread:context

Training context for a recent range and upcoming plan.

POST/api/agent/wodwrite:wod

Save confirmed imported WOD text.

POST/api/agent/checkinwrite:checkin

Submit athlete-local daily readiness.

POST/api/agent/completionwrite:completion

Log workout completion status, RPE, and notes.

POST/api/agent/availabilitywrite:availability

Add confirmed blackout/availability constraints.

POST/api/agent/sorenesswrite:soreness

Log confirmed soreness after a user check.

POST/api/agent/planner/movewrite:planner

Move a confirmed workout slot without recalibration.

PATCH/api/agent/profilewrite:profile

Update confirmed profile fields.

POST/api/agent/raceswrite:races

Create a confirmed race entry.

POST/api/agent/syncsync:refresh

Refresh Strava and Oura data with rate limiting.

Confirmation model

The API does not create a normal pending-review queue. When a write is ambiguous or not explicitly confirmed, the route returns 409 confirmation_required. OpenClaw should ask the athlete in chat, then retry the same request withuserConfirmed: true.

{
  "ok": false,
  "error": "confirmation_required",
  "message": "Confirm the extracted WOD before saving it.",
  "requiresConfirmation": true,
  "details": {
    "date": "2026-04-27",
    "confidence": 0.72,
    "uncertainItems": ["Workout date was not visible"]
  }
}
GET/api/agent/today

Returns the athlete-local date, readiness/check-in status, and the workout generated for that date. Responses are marked Cache-Control: no-store.

{
  "ok": true,
  "date": "2026-04-26",
  "timezone": "America/Chicago",
  "user": {
    "id": "f3b8...",
    "email": "alex@example.com"
  },
  "readiness": {
    "submitted": true,
    "submittedAt": "2026-04-26T12:03:11.000Z",
    "trainedAlready": false,
    "overallFatigue": 3,
    "motivation": 4,
    "currentlyIll": false,
    "illnessDays": null,
    "returningFromIllness": false,
    "notes": "Slept well. Legs a little heavy."
  },
  "workout": {
    "exists": true,
    "restDay": false,
    "completionStatus": null,
    "triSession": {
      "type": "run",
      "title": "Easy aerobic run",
      "durationMinutes": 70,
      "tss": 65,
      "intensity": "Zone 1-2"
    },
    "secondTriSession": null,
    "wod": null
  }
}
GET/api/agent/context

Returns recent fitness, workouts, activities, readiness, soreness, upcoming races, and open attention items. Use rangeDaysto request 7 to 90 days of recent history. Upcoming workouts and races are included so the agent can reason about schedule changes before asking for confirmation.

POST/api/agent/wod

OpenClaw should perform OCR/vision itself, ask for confirmation when details are unclear, then submit text only. The app does not accept screenshots on this endpoint.

{
  "date": "2026-04-27",
  "source": "openclaw",
  "rawText": "exact OCR text from the screenshot",
  "cleanText": "cleaned WOD text, preserving original structure",
  "confidence": 0.93,
  "userConfirmed": true,
  "uncertainItems": []
}

If confidence is below 0.85 or uncertainItems is not empty, the request returns confirmation_requiredunless userConfirmed is true.

POST/api/agent/planner/move

Moves a confirmed planner slot. The agent can move the whole day, the primary triathlon session, the secondary triathlon session, or the WOD. Recalibration is not run automatically; moved sessions keep their existing content until the athlete explicitly recalibrates.

{
  "fromDate": "2026-04-28",
  "toDate": "2026-04-30",
  "slot": "tri",
  "userConfirmed": true
}

Response fields

date

Athlete-local date used for lookup.

readiness.submitted

Whether a check-in row exists for the date.

readiness.overallFatigue

Athlete-entered fatigue score, or null if not submitted.

workout.exists

Whether a generated workout exists for the date.

workout.triSession

Primary endurance session, including title, content, duration, intensity, and TSS.

workout.secondTriSession

Optional second endurance session.

workout.wod

Optional CrossFit content if there is a prescribed or group WOD.

workout.completionStatus

Current workout completion state if logged in the app.

How the right user is selected

The agent does not send an email address, user id, or search query. The bearer token is hashed, matched against the agent_tokenstable, and the matched row supplies the user id. That user id is then used for reads and writes.

Errors

Error responses use the same shape across the endpoint.

{
  "ok": false,
  "error": "Invalid bearer token"
}

401 Missing, invalid, revoked, or expired token.

402 Subscription required.

403 Token does not have the required scope.

409 Confirmation required, date conflict, or planner collision.

500 Lookup failed.

Security model

  • - Tokens are hashed before storage.
  • - Tokens are scoped by capability.
  • - Tokens are revocable from Settings.
  • - Agent writes are logged to an audit table.
  • - Low-confidence or unconfirmed writes return a confirmation-required response.
  • - The endpoint does not expose Strava, Oura, billing, or service-role credentials.
  • - Store tokens as secrets in the external agent, not in prompts or source control.