The Google Health API tracks user workout sessions and exercise history using the
exercise session data type. A session acts as a container that bundles
activity metadata, pause and resume events, laps or splits, and summary
metrics.
Understand how to read, write, and structure workouts in your application to deliver the best experience for your users.
Supported data types
The API supports the following data type for tracking workouts and activity sessions:
| Data type | Available operations |
Scope |
|---|---|---|
|
Exercise
dataType:
exercisefilter parameter: exercise
Record type: Session
Compatible devices
|
list, get, reconcile, create, update, batchDelete | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
Related telemetry data types
While workout sessions use the exercise data type as a container, wearable
devices also record detailed, high-frequency telemetry during a session. In the
Google Health API, these granular intraday telemetry data types are read-only
and cannot be created or modified directly through their own REST endpoints.
When writing a workout session through the REST API, pass aggregate workout
metrics inside the metricsSummary object of the exercise data point.
The following table maps the summary fields inside exercise.metricsSummary to
the corresponding read-only intraday telemetry data types that you can query for
that workout's time window:
Summary field (metricsSummary) |
Intraday telemetry data type name | API telemetry data type ID (read-only) | Filter field (?filter=) |
Required read OAuth scope |
|---|---|---|---|---|
caloriesKcal |
Active Energy Burned | active-energy-burned |
active_energy_burned.interval.start_time |
activity_and_fitness.readonly |
distanceMillimeters |
Distance | distance |
distance.interval.start_time |
activity_and_fitness.readonly |
steps |
Steps | steps |
steps.interval.start_time |
activity_and_fitness.readonly |
averageHeartRateBeatsPerMinute |
Heart Rate | heart-rate |
heart_rate.sample_time.physical_time |
health_metrics_and_measurements.readonly |
activeZoneMinutes |
Active Zone Minutes | active-zone-minutes |
active_zone_minutes.interval.start_time |
activity_and_fitness.readonly |
The following sections provide technical details for the exercise data type,
including REST representation examples, GPS route handling, and integration
guidelines.
Workout sessions
Write daily activities or workouts as exercise session data points. Each
data point describes the overall session, details event intervals (such as
pause and resume actions), and supplies summary metrics (like overall distance,
steps, and average heart rate).
Session attributes
When structuring an exercise data point, verify the following core components:
- Session Time (
interval): The start time and end time of the overall workout session, along with the timezone offsets active at those points. - Activity Type (
exerciseType): The category of activity performed (such asRUNNING,WALKING,BIKING, orAEROBIC_WORKOUT). Specify the exact type of physical training. - Display Name (
displayName): A user-friendly name for the workout session. When created through the REST API, the server populates the localized display name for theexerciseType, such as"Run"forRUNNING. - Active Duration (
activeDuration): The true active time of the workout, excluding paused intervals. Standard formatting usesDurationformat (for example,"1800s"). On the server,activeDurationis calculated from the sessionintervalminus anyPAUSE/RESUMEorAUTO_PAUSE/AUTO_RESUMEintervals inexerciseEvents.
Summary metrics
The metricsSummary nested object contains total and average metrics
calculated across the entire duration of the exercise session:
caloriesKcal: Total active calories burned during the workout, measured in kilocalories (kcal).distanceMillimeters: Total distance covered, measured in millimeters to maintain high precision across units.steps: Total steps taken during the exercise.averageHeartRateBeatsPerMinute: The user's average heart rate during active minutes of the session.activeZoneMinutes: Cumulative active zone minutes earned during the workout.averageSpeedMillimetersPerSecond: Average movement speed in millimeters per second.averagePaceSecondsPerMeter: Average pace during active minutes of the session, measured in seconds per meter.elevationGainMillimeters: Total elevation gain during the session.
Laps and splits
For workouts that involve laps (such as track runs or pool swimming) synced from
supported devices, splitSummaries segments the session by lap or split.
Each split contains:
- A specific
startTimeandendTime. - An
activeDurationrepresenting true lap time. - A
metricsSummaryscoped only to that segment. - A
splitTypeto define the split boundaries (such asDISTANCE,DURATION, orMANUAL).
Exercise events
To accurately compute active duration, track state transitions (like manual or
automatic pause events) using exerciseEvents.
Each event contains the timestamp (eventTime) and type:
START/STOP: Indicates boundary timestamps of when the user explicitly started or stopped the record.PAUSE/RESUME: Indicates when the session was manually paused or resumed.AUTO_PAUSE/AUTO_RESUME: Indicates sensor-driven auto-pauses/resumes.
Write a workout session
To create, update, or import a workout session, write a data point to the
exercise data type collection. Use the create dataPoints
endpoint.
REST representation example
The following example shows how to write a workout session using a POST
method:
Request
POST https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints
Authorization: Bearer access-token
Content-Type: application/json
{
"dataSource": {
"recordingMethod": "ACTIVELY_MEASURED",
"platform": "GOOGLE_WEB_API"
},
"exercise": {
"interval": {
"startTime": "2026-04-20T08:00:00Z",
"startUtcOffset": "0s",
"endTime": "2026-04-20T08:35:00Z",
"endUtcOffset": "0s"
},
"exerciseType": "RUNNING",
"activeDuration": "1800s",
"metricsSummary": {
"caloriesKcal": 380.0,
"distanceMillimeters": 5000000.0,
"steps": "6200",
"averageHeartRateBeatsPerMinute": "148",
"averagePaceSecondsPerMeter": 0.36
},
"exerciseEvents": [
{
"eventTime": "2026-04-20T08:15:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "PAUSE"
},
{
"eventTime": "2026-04-20T08:20:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "RESUME"
}
]
}
}Response
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.devicesandservices.health.v4.DataPoint",
"name": "users/999298779973222220/dataTypes/exercise/dataPoints/3054085373369111216",
"dataSource": {
"recordingMethod": "ACTIVELY_MEASURED",
"application": {
"googleWebClientId": "438076457939-example.apps.googleusercontent.com"
},
"platform": "GOOGLE_WEB_API"
},
"exercise": {
"interval": {
"startTime": "2026-04-20T08:00:00Z",
"startUtcOffset": "0s",
"endTime": "2026-04-20T08:35:00Z",
"endUtcOffset": "0s"
},
"exerciseType": "RUNNING",
"metricsSummary": {
"caloriesKcal": 380,
"distanceMillimeters": 5000000,
"steps": "6200",
"averagePaceSecondsPerMeter": 0.36,
"averageHeartRateBeatsPerMinute": "148"
},
"exerciseMetadata": {},
"displayName": "Run",
"activeDuration": "1800s",
"exerciseEvents": [
{
"eventTime": "2026-04-20T08:15:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "PAUSE"
},
{
"eventTime": "2026-04-20T08:20:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "RESUME"
}
],
"updateTime": "2026-04-20T08:35:10.123456Z",
"createTime": "2026-04-20T08:35:10.123456Z"
}
}
}GPS routes and location tracking
The API saves basic session summaries directly within the exercise data
point, but handles detailed location history and GPS route coordinates as a
separate stream.
To download the detailed route data for an outdoor session, call the
exportExerciseTcx custom method. This endpoint returns the route in the
industry-standard Training Center XML (TCX) format.
Export GPS route
Request
GET https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints/exercise-data-point-id:exportExerciseTcx?alt=media Authorization: Bearer access-token
Response
An HTTP payload with Content-Type: application/tcx+xml and
headers instructing the browser to save the file.
<?xml version="1.0" encoding="UTF-8"?>
<TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2">
<Activities>
<Activity Sport="Running">
<Id>2026-04-20T08:00:00Z</Id>
<Lap StartTime="2026-04-20T08:00:00Z">
<TotalTimeSeconds>1800</TotalTimeSeconds>
<DistanceMeters>5000</DistanceMeters>
<Calories>380</Calories>
<Intensity>Active</Intensity>
<TriggerMethod>Manual</TriggerMethod>
<Track>
<Trackpoint>
<Time>2026-04-20T08:00:00Z</Time>
<Position>
<LatitudeDegrees>37.7749</LatitudeDegrees>
<LongitudeDegrees>-122.4194</LongitudeDegrees>
</Position>
<AltitudeMeters>15.0</AltitudeMeters>
<DistanceMeters>0.0</DistanceMeters>
</Trackpoint>
</Track>
</Lap>
</Activity>
</Activities>
</TrainingCenterDatabase>Required scopes and location
To use the GPS routes and location tracking feature, your app must request the following OAuth scopes:
- Read:
https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly - Write:
https://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly - Read:
https://www.googleapis.com/auth/googlehealth.location.readonly
Guidelines
When integrating workout tracking into your app, follow these design and implementation guidelines.
Active versus total duration
To calculate speed or pace metrics, always use activeDuration rather than the
difference between startTime and endTime. This prevents paused intervals
from skewing your metrics.
For example, if a user starts a workout at 08:00 and finishes at 08:35, the
workout has a total elapsed duration of 2,100 seconds. If the user paused the
workout for 5 minutes (300 seconds) and you include PAUSE and RESUME events
in exerciseEvents, the active duration is "1800s" (2,100 - 300). The API
uses active duration to calculate averages, dividing total distance by 1,800
seconds instead of 2,100.
Speed and pace calculation
The Google Health API uses standard formulas to calculate speed and pace:
- Speed =
distance / time(hour) - Pace =
time(seconds) / distance
The Accept-Language header specified in the request determines the unit of
distance.
Request location early
If your app maps workout routes, request location permissions and the Google
Health location scope in addition to the activity and fitness scope. Explain
to users why your app requires the location scope when reviewing GPS exercises.
When your app requests the location scope
(https://www.googleapis.com/auth/googlehealth.location.readonly), Google
OAuth displays a consent prompt to the user. Explain to your users that this
permission is necessary to render route overlays and export GPS track files
(TCX). If a user grants the activity scope but denies location permission,
exportExerciseTcx returns an authorization error, though you can still
access session aggregates in metricsSummary.
Sync using webhooks
Subscribe to the exercise data type to notify your backend using webhooks
when new workout data becomes available. This lets you trigger post-workout
experiences automatically.
When your server receives a webhook notification, it contains the
healthUserId and the civil time interval (civilIso8601TimeInterval) of the
updated workout. Your server should acknowledge the notification immediately
with 204 No Content, process the payload asynchronously, and query the
reconciled exercise endpoint using an exercise.interval.civil_start_time
filter (note that exercise only supports filtering by civil_start_time):
GET https://health.googleapis.com/v4/users/healthUserId/dataTypes/exercise/dataPoints:reconcile?filter=exercise.interval.civil_start_time >= "2026-04-20T08:00:00" AND exercise.interval.civil_start_time < "2026-04-20T10:00:00"
For details on how to set up subscriptions, see Webhook subscriptions.
Maintain consistent metrics
To provide a complete workout experience, include summary metrics when writing
exercise sessions and query the read-only telemetry endpoints using time-range
filters when rendering detail charts.
Write workout summary metrics (write path)
When importing or writing a completed workout to the Google Health API, include the
workout's aggregate telemetry metrics (steps, caloriesKcal,
distanceMillimeters, averageHeartRateBeatsPerMinute, and
averagePaceSecondsPerMeter) inside the metricsSummary object of the
exercise data point:
POST https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints
Query detailed data for charts (read path)
To build workout dashboards or charts for a specific session, query the reconciled telemetry endpoints for that workout's time window:
Fetch the workout session from the
exerciseendpoint using acivil_start_timefilter to get itsintervalandmetricsSummary:GET https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints:reconcile?filter=exercise.interval.civil_start_time >= "2026-04-20T00:00:00" AND exercise.interval.civil_start_time < "2026-04-21T00:00:00"
Use the session's
interval.startTimeandinterval.endTimeto query the telemetry endpoints for that physical time window.If
exerciseMetadata.hasGpsistrue, callexportExerciseTcxto download the route coordinates.