Programmatic API reference and examples for trainingpeaks-unofficial.
The README is CLI-first. Use this document when embedding the client in Python code, tests, or automation that needs direct access to the transport/domain modules.
from trainingpeaks_unofficial import TrainingPeaksClient
client = TrainingPeaksClient(token="YOUR_BEARER_TOKEN")
athlete_id = client.infer_athlete_id()For reusable auth flows, use a token provider:
from trainingpeaks_unofficial import TrainingPeaksClient, UsernamePasswordTokenProvider
client = TrainingPeaksClient(
token_provider=UsernamePasswordTokenProvider(username="...", password="..."),
)from trainingpeaks_unofficial import PlannedWorkoutInput, TrainingPeaksClient
client = TrainingPeaksClient(token="YOUR_BEARER_TOKEN")
athlete_id = client.infer_athlete_id()
planned = PlannedWorkoutInput(
workout_day="2026-04-28",
workout_type_value_id=3,
title="Planned Run",
)
created = client.workouts.create_planned_workout(
athlete_id=athlete_id,
payload=planned,
)
print(created.workout_id)create_planned_workout and update_planned_workout run through WorkoutPlanner, which merges payloads, validates structure semantics, rebuilds geometry, and estimates planned metrics by default.
workout = client.workouts.get_workout(athlete_id, workout_id=123)
details = client.workouts.get_workout_details(athlete_id, workout_id=123)
updated = client.workouts.update_planned_workout(
athlete_id=athlete_id,
workout_id=123,
patch={"title": "Updated title"},
)
client.workouts.delete_workout(athlete_id, workout_id=123)metrics = client.workouts.estimate_planned_metrics_from_structure(
athlete_id=athlete_id,
workout_type_value_id=3,
structure={
"primaryIntensityMetric": "percentOfThresholdPace",
"structure": [
{
"type": "step",
"length": {"value": 3600, "unit": "second"},
"steps": [
{
"length": {"value": 3600, "unit": "second"},
"targets": [{"minValue": 80, "maxValue": 90}],
}
],
}
],
},
)
print(metrics["tssPlanned"], metrics["ifPlanned"])See api-payloads.md for structure and payload schemas.
from trainingpeaks_unofficial import AthleteInsight, TrainingPeaksClient
client = TrainingPeaksClient(token="...")
athlete_id = client.infer_athlete_id()
insight = AthleteInsight.for_client(client=client, athlete_id=athlete_id)
readiness = insight.readiness_snapshot(weeks=0)
performance = insight.performance_snapshot(
start_date="2026-04-01",
end_date="2026-04-28",
)
print(readiness["today"])
print(performance["trend"])from trainingpeaks_unofficial import TrainingPeaksClient
client = TrainingPeaksClient(token="...")
athlete = client.get_athlete()
ctx = athlete.get_builder_context(workout_type_id=3) # Run
res = ctx.resolve_zone(metric="percentOfThresholdPace", zone=2)
print(res.to_display())
print(res.threshold)from trainingpeaks_unofficial import TrainingPeaksClient
client = TrainingPeaksClient(token="YOUR_BEARER_TOKEN")
athlete_id = client.infer_athlete_id()
plans = client.atp.list_plans(athlete_id)
if plans:
detail = client.atp.get_plan(athlete_id, plans[0].id)
weeks = client.atp.list_weeks(
athlete_id,
plans[0].start_week.split("T", 1)[0],
plans[0].end_week.split("T", 1)[0],
)
print(detail.atp.name, len(weeks))ATP plan updates are currently available through the Python API, not the CLI:
updated = client.atp.update_plan(
athlete_id=athlete_id,
payload={"atp": {"id": plans[0].id}, "events": [], "calculation": {}},
)