client.activities covers the full activity lifecycle: listing, uploading, editing and deleting activities, plus their streams, intervals, comments, and derived analysis (map, weather, curves, best efforts). List and upload routes are athlete-scoped; single-activity routes address the activity directly by id.
| Method | What it does |
|---|---|
| ActivityService.listActivities | List activities for a date range (descending order) |
| ActivityService.uploadActivity | Upload a new activity from file (fit, tcx, gpx, or zip/gz) |
| ActivityService.createManualActivity | Create a manual activity |
| ActivityService.createManualActivitiesBulk | Create multiple manual activities (upsert on external_id) |
| ActivityService.downloadFitFiles | Download a zip of Intervals.icu-generated FIT files for the given activities |
| ActivityService.getActivity | Get an activity |
| ActivityService.updateActivity | Update an activity (Strava activities cannot be updated) |
| ActivityService.deleteActivity | Delete an activity |
| ActivityService.getStreams | Get activity streams (JSON) |
| ActivityService.updateStreams | Update activity streams (JSON) |
| ActivityService.getStreamsCSV | Download activity streams as CSV |
| ActivityService.updateStreamsCSV | Replace activity streams from a CSV file (PUT multipart/form-data) |
| ActivityService.getIntervals | Get activity intervals |
| ActivityService.updateIntervals | Update intervals (replace all or merge) |
| ActivityService.updateInterval | Update/create a single interval |
| ActivityService.deleteIntervals | Delete intervals |
| ActivityService.splitInterval | Split an interval at an index |
| ActivityService.downloadFile | Download the original activity file (gzip compressed) |
| ActivityService.downloadFitFile | Download the Intervals.icu generated fit file |
| ActivityService.getMap | Get map data (bounds, latlngs, route, weather) |
| ActivityService.getWeatherSummary | Get activity weather summary |
| ActivityService.getPowerCurve | Get power curve for an activity |
| ActivityService.getPaceCurve | Get pace curve for an activity |
| ActivityService.getHRCurve | Get HR curve for an activity |
| ActivityService.getBestEfforts | Get best efforts for an activity |
| ActivityService.getPowerVsHR | Get power vs HR analysis |
| ActivityService.getHRLoadModel | Get HR load model for an activity |
| ActivityService.getSegments | Get segments matched in an activity |
| ActivityService.listMessages | List all messages (comments) for an activity |
| ActivityService.sendMessage | Add a message (comment) to an activity |
| ActivityService.getActivities | Fetch multiple activities by id in one call |
| ActivityService.listActivitiesAround | Activities before and after another activity, closest first; optionally only those on a route |
| ActivityService.searchActivitiesFull | Search by name or tag and return full Activity objects (search.searchActivities returns summaries) |
| ActivityService.searchIntervals | Find activities containing intervals that match a duration and intensity window |
| ActivityService.listActivityTags | Every tag that has been applied to the athlete's activities |
| ActivityService.downloadActivitiesCSV | All activities as CSV |
| ActivityService.downloadGPX | The activity as a GPX file, optionally with power and heart-rate extensions |
| ActivityService.deleteTombstone | Remove the tombstone left by a deleted activity so the same file can be re-uploaded |
List the last 30 days of activities, pick the newest with a type, and download it as a FIT file and as a GPX file with power extensions.
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 monthAgo = new Date(now);
monthAgo.setDate(monthAgo.getDate() - 29);
const newest = localDate(now);
const oldest = localDate(monthAgo);
const activities = await client.activities.listActivities({ oldest, newest });
const activity = activities.find((a) => a.type);
if (!activity) {
console.log('No activities with a type in the last 30 days');
} else {
const id = activity.id!;
const full = await client.activities.getActivity(id);
console.log(`${full.name ?? id}: ${full.type ?? 'unknown type'}`);
const fit = await client.activities.downloadFitFile(id);
console.log(`FIT file: ${fit.length} bytes`);
const gpx = await client.activities.downloadGPX(id, { power: true });
console.log(`GPX (first 60 chars): ${gpx.toString('utf8').slice(0, 60)}`);
}
Find activities with 3-10 minute power intervals at 95-130% intensity, and search activities by name or tag.
const client = new IntervalsClient({ apiKey });
const matches = await client.activities.searchIntervals({
minSecs: 180,
maxSecs: 600,
minIntensity: 95,
maxIntensity: 130,
type: 'POWER',
limit: 10,
});
if (matches.length === 0) {
console.log('No activities with matching power intervals');
} else {
for (const activity of matches) {
console.log(`${activity.id} ${activity.name ?? ''}`);
}
}
const tempo = await client.activities.searchActivitiesFull('tempo', { limit: 5 });
console.log(`${tempo.length} activit${tempo.length === 1 ? 'y' : 'ies'} matching "tempo"`);
For the newest typed activity in the last year, fetch its watts/heartrate streams, detected intervals, and best efforts.
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 yearAgo = new Date(now);
yearAgo.setFullYear(yearAgo.getFullYear() - 1);
const newest = localDate(now);
const oldest = localDate(yearAgo);
const activities = await client.activities.listActivities({ oldest, newest });
const activity = activities.find((a) => a.type);
if (!activity) {
console.log('No activities with a type in the last year');
} else {
const id = activity.id!;
const streams = await client.activities.getStreams(id, ['watts', 'heartrate']);
for (const stream of streams) {
console.log(`${stream.type}: ${stream.data?.length ?? 0} sample(s)`);
}
const intervals = await client.activities.getIntervals(id);
console.log(`${intervals.icu_intervals?.length ?? 0} interval(s)`);
const efforts = await client.activities.getBestEfforts(id);
console.log(`${efforts.efforts?.length ?? 0} best effort(s)`);
}
ids as a comma-joined value, and the live API returns 422 "No activities found" for malformed import stubs. See API behaviour.power-curves route (GET /activity/{id}/power-curves, AnalyticsService.getCurves) returns a 422 with an empty body when an activity cannot serve the requested streams or fatigue variants; see the analytics service page and API behaviour.