---
title: "One activity, with its load, power and speed bests and route"
method: GET
path: "/activities/{id}"
tags: ["Activities"]
---

# One activity, with its load, power and speed bests and route

`GET /activities/{id}`

## Request

- Base URL: `https://bodylab.lol/api/v1`
- URL: `https://bodylab.lol/api/v1/activities/{id}`
- Auth: HTTP bearer

## Path parameters

- `id` string, required: Opaque identifier.

## Headers

- `X-Client-Platform` string
- `X-Client-Version` string

## Response `200`

OK

- ActivityDetail
  - `id` string, required: Opaque identifier.
  - `source` string, required: Where the activity came from. manual (typed in) and file (uploaded) are Body Lab's own; any other value is the service the athlete synced it from.
  - `duplicateOf` string, nullable, required: Opaque identifier.
  - `alsoRecordedBy` object[], required: Other sources' copies of this same session, grouped under this one because it's the counted copy. Empty when nothing else recorded it, or when this row is itself duplicateOf another (see that one's alsoRecordedBy instead). Separate a member with activities.separate.
    - `activityId` string, required: Opaque identifier.
    - `source` string, required: Where the activity came from. manual (typed in) and file (uploaded) are Body Lab's own; any other value is the service the athlete synced it from.
  - `name` string, nullable, required
  - `activityType` string, required: Sport, from the engine's vocabulary (packages/engine/src/sports.ts), e.g. road_biking, running, hiking, strength_training. Known values: road_biking, running, hiking, strength_training, other. Treat unknown values as "other".
  - `typeLabel` string, required
  - `startTime` string, date-time, required: An instant: ISO-8601 with offset, e.g. 2026-09-13T06:30:00Z.
  - `durationS` number, nullable, required
  - `elapsedDurationS` number, nullable, required
  - `movingDurationS` number, nullable, required
  - `distanceM` number, nullable, required
  - `elevationGainM` number, nullable, required
  - `avgHr` integer, nullable, required: Beats per minute.
  - `maxHr` integer, nullable, required: Beats per minute.
  - `avgPowerW` integer, nullable, required
  - `sessionRpe` number, nullable, required: Session RPE, 1–10.
  - `notes` string, nullable, required
  - `file` object, nullable, required: The recording the activity was imported from, if any.
    - `filename` string, required
    - `format` 'fit' | 'gpx' | 'samples-json', required
    - `sizeBytes` integer, required
  - `load` object, nullable, required
    - `load` number, required
    - `source` string, required: Which evidence an activity's load was derived from, best first. Known values: provider, stream_trimp, avg_hr_trimp, srpe, duration. Treat unknown values as "other".
    - `zoneSeconds` number[], nullable, required: Seconds in heart-rate zones 1–5, when there's a stream.
  - `powerBests` object[], required
    - `durationS` integer, required
    - `watts` integer, required
  - `speedBests` object[], required: Runs only: the fastest average speed over each duration within this run. As with power, a longer duration's best can be faster than a shorter one's after intervals. Empty for other sports and runs without a recorded distance.
    - `basis` string, required: raw is the distance as recorded; gap is grade-adjusted, the flat-ground equivalent, and absent where the altitude couldn't support it. Known values: raw, gap. Treat unknown values as "other".
    - `durationS` integer, required
    - `speedMs` number, required: The fastest average over durationS within this run, metres per second.
    - `startS` integer, required: Where that window starts, seconds from the start of the recording.
  - `environment` object, nullable, required: Altitude and temperature read from the recording; null for an activity without one.
    - `altitudeM` number, nullable, required: Median altitude over the recording, metres. Null without an altitude channel or for a virtual course.
    - `startAltitudeM` number, nullable, required: Median altitude over the first minute, metres.
    - `temperatureC` number, nullable, required: Median temperature from the best source the recording carries, °C.
    - `temperatureSource` string, nullable, required: Where temperatureC was measured. external_sensor, bike_computer and weather_report are air temperature; wearable is a watch's own sensor, warmed by the wrist, and reads well above the air. Known values: external_sensor, bike_computer, weather_report, wearable. Treat unknown values as "other".
    - `temperatureIsAir` boolean, required: Whether temperatureC is air temperature, which only the engine's air sources are.
    - `recorder` string, nullable, required: The recording device as manufacturer/product, e.g. garmin/edge540.
  - `polyline` array[], required: The route, simplified for drawing; empty without a track.
    - unknown[]: [longitude, latitude] in degrees.
      - unknown
  - `profile` array[], nullable, required: Elevation profile as [distanceM, elevationM] pairs.
    - unknown[]
      - unknown

## Other responses

- `401`: Error: UNAUTHORIZED.
- `404`: Error: NOT_FOUND.

---

[API](https://skmtc.dev/bodylab/apis/body-lab-api.md) · [All operations](https://skmtc.dev/bodylab/apis/body-lab-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bodylab/apis/body-lab-api/revisions/544c201eaf88?raw)
