Tools Reference
All tools authenticate via your personal API key (set in FITREPO_API_KEY). Date strings use ISO 8601 format (YYYY-MM-DD or full RFC 3339).
get_activities
Section titled “get_activities”Returns a paginated list of activities, newest first.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
sport | string | No | Filter by sport type (e.g. cycling, running, swimming) |
from | string | No | Start date (inclusive), e.g. 2025-01-01 |
to | string | No | End date (inclusive), e.g. 2025-03-31 |
limit | integer | No | Results per page (default 50, max 200) |
offset | integer | No | Pagination offset (default 0) |
Returns
{ "activities": [ { "id": "uuid", "sport": "cycling", "started_at": "2025-03-15T07:30:00Z", "duration_secs": 3720, "distance_meters": 48200, "elevation_gain": 420, "tss": 82, "normalized_power": 218, "intensity_factor": 0.87, "avg_hr": 148, "max_hr": 172 } ], "total": null, "offset": 0, "limit": 50}Example prompt
“List my cycling activities from January 2025.”
get_activity
Section titled “get_activity”Returns full detail for a single activity, including all stored fields, best efforts, and a fitness snapshot at the time of the activity.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Activity UUID |
Returns — full activity object plus a fitness_at_activity field:
{ "fitness_at_activity": { "date": "2026-05-30", "ctl": 68.4, "atl": 82.1, "tsb": -13.7, "note": "Computed from power-based TSS only..." }}fitness_at_activity is null if the activity has no date or there is no TSS history to compute from. TSB is positive when fresh, negative when fatigued. See Fitness Model for definitions.
Example prompts
“Show me the details of my last race.” “How fatigued was I during yesterday’s ride?” “Was my power output good given my fitness at the time?”
get_activity_streams
Section titled “get_activity_streams”Returns the per-second data inside an activity’s stored FIT file, downsampled into time-aligned arrays — the shape of the ride rather than its summary.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Activity UUID |
resolution | number | No | Seconds per bucket (default 5; 1 = full resolution) |
channels | string[] | No | Any of power, heart_rate, cadence, altitude, speed, distance, grade, temperature, latitude, longitude. Default: all present except latitude/longitude |
startOffset | number | No | Window start, seconds from activity start (inclusive) |
endOffset | number | No | Window end, seconds from activity start (exclusive) |
Returns — streams.time plus one array per channel, all the same length:
poweris the bucket mean andpower_maxthe bucket max, so short surges stay visible at 5 s.heart_rate,cadence,speed,temperatureare bucket means (cadence zeros are kept — coasting is signal).altitude,distance,latitude,longitudeare the last sample in the bucket;gradeis derived from smoothed altitude and clamped to ±25%.- Buckets with no samples (sensor dropout, auto-pause) are
null. - Channels with no sensor are listed in
missingChannels.
Requests are capped at 3000 buckets: asking for 1 s over a whole long ride is coarsened automatically and a note explains why. Zoom with startOffset/endOffset to get 1 s detail. Returns an error if the original FIT file isn’t stored for the activity.
Example prompts
“Show me how my power and heart rate evolved over the first 20 minutes of the Gralloch.” “Where did I surge hardest in yesterday’s race?”
get_activity_laps
Section titled “get_activity_laps”Returns device lap markers plus climbs detected from the altitude stream (useful when the lap button was never pressed).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Activity UUID |
detectClimbs | boolean | No | Detect climbs from altitude (default true) |
Returns — laps (source device) and climbs (source climb-detect). Each segment has startOffset, endOffset, durationSecs, distance_m, elevation_gain_m, avg_grade_pct, avg_power, np, avg_hr, max_hr, avg_cadence, avg_speed.
A climb is a sustained stretch at ≥3% grade, at least 500 m or 2 minutes long with ≥10 m gain; short dips (under 30 s or 200 m) are merged. Feed a segment’s offsets into get_activity_streams to zoom in.
Example prompts
“What were the climbs in my last race and how hard did I ride each one?” “How long was the opening climb and what was my NP on it?”
get_fitness_timeline
Section titled “get_fitness_timeline”Returns daily CTL, ATL and TSB (training stress balance) for a date range.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
from | string | No | Start date, e.g. 2025-01-01 |
to | string | No | End date, e.g. 2025-03-31 |
Returns
{ "timeline": [ { "date": "2025-01-01", "ctl": 68.4, "atl": 72.1, "tsb": -3.7 } ], "meta": { "ctl_time_constant_days": 42, "atl_time_constant_days": 7, "note": "TSB = yesterday CTL − ATL. Positive = fresh, negative = fatigued." }}See Fitness Model for how CTL/ATL/TSB are calculated.
Example prompts
“What was my CTL at the start of my build block in February?” “Plot my TSB over the last 3 months.”
get_best_efforts
Section titled “get_best_efforts”Returns mean-maximal power (MMP) records — your best average power for standard durations — plus a per-activity breakdown.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
sport | string | No | Sport to filter by (default: cycling) |
from | string | No | Only consider activities on or after this date |
to | string | No | Only consider activities on or before this date |
Returns
{ "sport": "cycling", "from": null, "to": null, "all_time_best": { "p5s": 920, "p10s": 840, "p30s": 620, "p1m": 520, "p2m": 460, "p5m": 380, "p10m": 340, "p20m": 312, "p60m": 268 }, "per_activity": [ { "id": "uuid", "started_at": "2025-03-15T07:30:00Z", "best_efforts": { "p5s": 820, "p20m": 305 } } ]}Duration keys: p5s (5 s), p10s, p30s, p1m, p2m, p5m, p10m, p20m, p60m — values are watts. A key is omitted from all_time_best if no activity has data for that duration.
See Best Efforts (MMP) for methodology.
Example prompts
“What’s my best 20-minute power in the last 6 months?” “How does my 5-second sprint compare to 12 months ago?”
get_wellness
Section titled “get_wellness”Returns wellness log entries (HRV, resting HR, sleep, readiness).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
from | string | No | Start date |
to | string | No | End date |
source | string | No | Filter by data source (e.g. oura, garmin, manual) |
Returns
{ "wellness": [ { "date": "2025-03-15", "source": "oura", "weight_kg": 72.1, "rhr_bpm": 42, "hrv_rmssd": 68.2, "sleep_hours": 7.8, "sleep_score": 82, "readiness": 84 } ]}See Wellness for field definitions.
Example prompts
“How does my HRV trend around hard training weeks?” “Show me my sleep hours and readiness scores for March.”
get_thresholds
Section titled “get_thresholds”Returns your FTP and lactate threshold heart rate (LTHR) history.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
metric | string | No | Filter by metric: ftp or lthr — omit for all |
Returns
{ "thresholds": [ { "metric": "ftp", "value": 265, "effective_from": "2025-01-15", "source": "auto", "notes": null } ], "note": "Use effective_from to find the threshold active on any given date."}source is auto (detected from activity data) or manual (entered in Settings).
See Thresholds for full documentation.
Example prompts
“How has my FTP changed over the last year?” “When did I last update my LTHR?”
get_athlete_profile
Section titled “get_athlete_profile”Returns your athlete profile.
Parameters — none.
Returns
{ "date_of_birth": "1988-04-12", "sex": "male", "height_cm": 178, "created_at": "2025-01-01T00:00:00Z", "updated_at": "2025-03-15T09:00:00Z"}Returns {} if no profile has been set up yet.
Example prompt
“What’s my weight-to-power ratio based on my current FTP?”
create_planned_workouts
Section titled “create_planned_workouts”Pushes planned workouts and race/note markers to your Intervals.icu calendar. Requires an Intervals.icu connection whose API key can write to the calendar. See Intervals.icu Integration.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
workouts | object[] | Yes | One or more events (fields below) |
dryRun | boolean | No | Build the Intervals payloads and return them without calling the API |
Each workout:
| Field | Type | Required | Description |
|---|---|---|---|
ref | string | Yes | Your stable id for this event. Re-pushing the same ref updates the event in place |
date | string | Yes | Local date YYYY-MM-DD |
time | string | No | Local start HH:mm (default 07:00 for workouts, 00:00 for notes/races) |
name | string | Yes | Calendar title |
category | string | No | WORKOUT (default), NOTE, RACE_A, RACE_B, RACE_C, HOLIDAY, SICK, INJURED |
type | string | No | Ride (default), Run, Swim, WeightTraining, … |
indoor | boolean | No | Mark as an indoor (turbo/Zwift) session |
description | string | No | Intervals workout text, e.g. - 15m 55% Warmup — percentages are %FTP |
load | number | No | Planned TSS |
movingTime | number | No | Planned duration in seconds |
color | string | No | Colour for NOTE markers |
Events are stored in Intervals with external_id = "fitrepo:<ref>", so FitRepo’s events never collide with other integrations. Every push writes an audit row. Your API key is never returned.
Example prompts
“Put this week’s sessions on my Intervals calendar.” “Add the Gralloch on 16 May as my A race.”
get_planned_workouts
Section titled “get_planned_workouts”Reads planned events back off your Intervals.icu calendar — the reverse of create_planned_workouts. Use it to reschedule or edit workouts without creating duplicates.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
oldest | string | Yes | Inclusive start date YYYY-MM-DD |
newest | string | Yes | Inclusive end date YYYY-MM-DD |
onlyFitrepo | boolean | No | Only events FitRepo created (default true); false includes everything on the calendar |
categories | string[] | No | Restrict to categories, e.g. ["WORKOUT"] (default: all) |
Returns
{ "ok": true, "count": 1, "rows": [ { "ref": "p1-w2-fri-z2", "id": 137794367, "date": "2026-10-02", "time": "12:30", "name": "Lunch Z2", "category": "WORKOUT", "type": "Ride", "load": 42, "movingTime": 3600, "description": "- 60m 60-70% Easy endurance" } ]}To move or edit an event, pass its ref back to create_planned_workouts with the changed fields — the event updates in place. ref is null for events FitRepo didn’t create (made in the Intervals UI or by another integration); those can’t be moved this way. Every read writes an audit row.
Example prompts
“What’s on my calendar this week?” “Move any Z2 that falls the day before a long ride.”
get_backfill_status
Section titled “get_backfill_status”Reports on imports from Wahoo and Intervals.icu: which sources are connected, your most recent stored activity, and recent import jobs.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
jobIds | string[] | No | Jobs to report on (default: the 3 most recent) |
waitSeconds | number | No | Wait up to this long (max 25) for running jobs to finish |
Returns
{ "today": "2026-09-28", "sources": { "wahoo": true, "intervals": true }, "lastActivity": { "id": "…", "started_at": "2026-09-27T08:02:11+00:00", "source": "intervals_backfill", "sport": "cycling" }, "suggestedFrom": "2026-09-27", "jobs": [ { "id": "…", "source": "intervals", "status": "completed", "from_date": "2026-09-27", "to_date": "2026-09-28", "inRange": 2, "imported": 1, "skipped": 1, "failed": 0, "error": null } ]}suggestedFrom is the date of your latest stored activity — the natural start for “backfill new workouts”. If a running import has stalled, checking its status restarts it ("resumed": true).
start_backfill
Section titled “start_backfill”Imports workouts from Wahoo and/or Intervals.icu (including Garmin and Zwift rides that reach Intervals) into FitRepo. Rides already stored are skipped.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
source | string | Yes | wahoo, intervals or both |
from | string | No | Start date YYYY-MM-DD (default: the date of your latest stored activity) |
to | string | No | End date YYYY-MM-DD (default: today) |
force | boolean | No | Re-import rides even if already stored (default false) |
Returns — the date range and one jobId per source. Imports run in the background; call get_backfill_status with those ids (and waitSeconds) for the result.
If you don’t name a source and both are connected, Claude asks which to use. both imports a ride from each source it appears in — if Wahoo auto-syncs to Intervals, that means duplicates, so prefer the source the ride was recorded on. Up to 5 imports can be started per hour.
Example prompts
“Backfill new workouts.” “Pull in today’s ride from Intervals.” “Import everything from Wahoo since June.”
Coaching documents
Section titled “Coaching documents”Your coaching skill (how Claude should coach you) and training plans are stored in FitRepo as versioned markdown. They’re loaded lazily: on connect Claude only gets a two-sentence pointer, and a casual ride question never touches them. Manage them on the Coaching page — download, copy, upload, switch versions.
| Tool | What it does |
|---|---|
get_active_documents | Active skill and plan — metadata only (slug, name, version, id, source). newerDefaultVersion is set when you run a customised skill and FitRepo ships a newer default. |
get_document | Full markdown by id or slug (optionally slug@version). |
upsert_document | Save a new version (type, content, optional slug, name, activate, basedOn). History is never overwritten; if the previous version was active, the new one becomes active. |
set_active_document | Make a version active by id or slug. Activating the FitRepo default skill reverts to it. |
list_documents | All versions of your skills and plans, plus the shipped defaults. Metadata only. |
Everyone starts on the FitRepo Coach skill — casual by default; it only coaches or builds a plan when you ask. Saving a skill under the fitrepo-coach slug creates your own copy, and later FitRepo updates never overwrite it.
Example prompts
“Plan my season around the Gralloch in May.” “Load my current plan — what’s this week?” “Save this plan to FitRepo and make it active.”