Log a workout from a description
Parses a freeform description of a workout into a normalized row (activity type, duration, distance, heart rate, strength exercises) and logs it.
/api/workouts/describe__Secure-better-auth.session_tokenAPI key · cookierequiredBetter Auth session. Signing in (Google or email magic link) sets an HttpOnly session cookie that scopes every request to that account. The web app and CLI use this; agents use the OAuth 2.1 flow of the MCP server.
AuthorizationBearer token · headerrequiredPersonal API key sent as Authorization: Bearer skcal_…. Create and scope keys in the app under your profile → API keys. Keys default to full access; a scoped key is limited to its granted resource:action permissions and cannot manage other keys.
application/jsonThe workout description and optional local day.
textstringrequiredThe workout in the user's own words.
datestring<date>Local day to log against (YYYY-MM-DD); defaults to now.
tzintegerTimezone offset in minutes, as from getTimezoneOffset.
The workout was parsed and logged.
idstring<uuid>requiredWorkout identifier.
sourcestringrequiredWhere the workout came from; manual for described/photographed logs.
manualapple_healthgarminstravaactivityTypestringrequiredNormalized activity type (run, ride, swim, walk, hike, strength_training, yoga, rowing, elliptical, crossfit, other).
summarystringrequiredShort AI-generated title.
descriptionstringrequiredThe user's original words (or the summary for photo-only logs).
startedAtintegerrequiredStart time as Unix milliseconds.
durationSinteger | nullrequiredElapsed duration in seconds.
movingDurationSinteger | nullrequiredMoving time in seconds, when distinct from elapsed.
distanceMnumber | nullrequiredDistance in meters.
elevationGainMnumber | nullrequiredElevation gain in meters.
energyKcalnumber | nullrequiredActive energy in kilocalories.
avgHrinteger | nullrequiredAverage heart rate in bpm.
maxHrinteger | nullrequiredMax heart rate in bpm.
avgPowerWnumber | nullrequiredAverage power in watts.
avgCadencenumber | nullrequiredAverage cadence (spm or rpm as reported).
exercisesWorkoutExercise[]requiredStrength breakdown; empty for pure cardio.
Show propertiesHide properties
WorkoutExerciseexercisestringrequiredExercise name as the user gave it.
setsinteger | nullrequiredNumber of sets, when stated.
repsinteger | nullrequiredReps per set, when stated.
weightLbnumber | nullrequiredWorking weight in pounds, when stated.
durationSinteger | nullrequiredDuration in seconds for timed pieces, when stated.
distanceMnumber | nullrequiredDistance in meters for distance pieces, when stated.
notesstring | nullrequiredAnything else the user said about the exercise.
createdAtintegerrequiredRow creation time as Unix milliseconds.
The request body or parameters failed validation.
errorstringrequiredHuman-readable failure reason.
detailstringOptional extra context, present on upstream failures.
The upstream model call failed.
errorstringrequiredHuman-readable failure reason.
detailstringOptional extra context, present on upstream failures.
A required secret (model key or ingest token) is not configured.
errorstringrequiredHuman-readable failure reason.
detailstringOptional extra context, present on upstream failures.