client.athletes manages the authenticated athlete's profile, training plan, and account-level settings, and lists the athletes the caller follows or coaches. Most routes are scoped to a single athlete; listAthletes and updateAthletePlans operate across athletes.
| Method | What it does |
|---|---|
| AthleteService.getAthlete | Get athlete information (includes sportSettings and custom_items) |
| AthleteService.updateAthlete | Update athlete information |
| AthleteService.getTrainingPlan | Get the athlete's training plan |
| AthleteService.updateTrainingPlan | Change the athlete's training plan |
| AthleteService.updateAthletePlans | Change training plans for a list of athletes |
| AthleteService.getProfile | Get athlete profile (public info, shared folders, custom items) |
| AthleteService.getSummary | Summary information (training load, fitness, categories) for the athlete and followed athletes over a date range |
| AthleteService.listAthletes | Athletes the caller follows or coaches, including the caller |
| AthleteService.getConnections | Which devices and platform apps the athlete has connected |
| AthleteService.getSettings | UI settings for a device class (a map of setting groups, each an open object) |
| AthleteService.disconnectApp | Disconnect the OAuth app that owns the current access token from the athlete's account |
Pull the 90-day fitness/fatigue/form summary, list which devices and apps are connected, and read the desktop UI settings.
const client = new IntervalsClient({ apiKey });
const localDate = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
const now = new Date(); // one timestamp for both bounds
const quarterAgo = new Date(now);
quarterAgo.setDate(quarterAgo.getDate() - 89);
const end = localDate(now);
const start = localDate(quarterAgo);
const summary = await client.athletes.getSummary({ start, end });
const latest = summary.at(-1);
if (latest) {
console.log(`Latest: fitness=${latest.fitness ?? 'n/a'} fatigue=${latest.fatigue ?? 'n/a'} form=${latest.form ?? 'n/a'}`);
} else {
console.log('No summary rows in the last 90 days');
}
const connections = await client.athletes.getConnections();
const connected = Object.entries(connections).filter(([key, value]) => key.endsWith('_connected') && value === true);
console.log(connected.length > 0 ? `Connected: ${connected.map(([key]) => key.replace(/_connected$/, '')).join(', ')}` : 'Nothing connected');
const settings = await client.athletes.getSettings('desktop');
console.log(`Desktop settings groups: ${Object.keys(settings).join(', ')}`);
List the athletes the API key's owner follows or coaches, then fetch one other athlete's profile.
const client = new IntervalsClient({ apiKey });
const me = await client.athletes.getAthlete();
const athletes = await client.athletes.listAthletes();
for (const athlete of athletes) {
console.log(`${athlete.id} ${athlete.name ?? ''} [${(athlete.icu_tags ?? []).join(', ')}]`);
}
const other = athletes.find((athlete) => athlete.id !== me.id);
if (other) {
const profile = await client.athletes.getProfile(other.id);
console.log(`Profile for ${other.name ?? other.id}: ${JSON.stringify(profile).slice(0, 80)}`);
} else {
console.log('No other coached/followed athletes');
}