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 typedataType
filter parameter |
Record type |
Available operations |
Scope | Webhook support |
True zeros support |
|---|---|---|---|---|---|
Exercise
exerciseexercise
|
Session | list, get, reconcile, create, update, batchDelete | activity_and_fitness |
Related telemetry data types
While workout sessions use the exercise data type as a container, typical
workout trackers write and read detailed, high-frequency telemetry during the
session. These measurements (such as heart rate or step count) must be read or
written using their own respective data types.
The following table maps the fields inside the metricsSummary object of the
exercise data type to the corresponding raw telemetry data types of the
Google Health API:
Summary field (metricsSummary) |
Intraday telemetry data type name | API telemetry data type ID |
|---|---|---|
caloriesKcal |
Active Energy Burned | active-energy-burned |
distanceMillimeters |
Distance | distance |
steps |
Steps | steps |
averageHeartRateBeatsPerMinute |
Heart Rate | heart-rate |
activeZoneMinutes |
Active Zone Minutes | active-zone-minutes |
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 (for example, "Afternoon Trail Run"). - Active Duration (
activeDuration): The true active time of the workout, excluding paused intervals. Standard formatting usesDurationformat (for example,"1800s").
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), use
splitSummaries.
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 data points
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"
},
"exercise": {
"interval": {
"startTime": "2026-04-20T08:00:00Z",
"startUtcOffset": "0s",
"endTime": "2026-04-20T08:35:00Z",
"endUtcOffset": "0s"
},
"exerciseType": "RUNNING",
"displayName": "Morning Trail Run",
"activeDuration": "1800s",
"metricsSummary": {
"caloriesKcal": 380.0,
"distanceMillimeters": 5000000.0,
"steps": "6200",
"averageSpeedMillimetersPerSecond": 2777.78,
"averagePaceSecondsPerMeter": 360.0,
"averageHeartRateBeatsPerMinute": "148",
"activeZoneMinutes": "30"
},
"exerciseMetadata": {
"hasGps": true
},
"exerciseEvents": [
{
"eventTime": "2026-04-20T08:15:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "PAUSE"
},
{
"eventTime": "2026-04-20T08:20:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "RESUME"
}
],
"splitSummaries": [
{
"startTime": "2026-04-20T08:00:00Z",
"startUtcOffset": "0s",
"endTime": "2026-04-20T08:15:00Z",
"endUtcOffset": "0s",
"splitType": "DISTANCE",
"metricsSummary": {
"distanceMillimeters": 2500000.0,
"caloriesKcal": 190.0
}
}
]
}
}Response
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.devicesandservices.health.v4main.DataPoint",
"name": "users/me/dataTypes/exercise/dataPoints/morning-trail-run-123456",
"dataSource": {
"recordingMethod": "ACTIVELY_MEASURED",
"application": {
"packageName": "com.example.workoutapp"
},
"platform": "GOOGLE_WEB_API"
},
"exercise": {
"interval": {
"startTime": "2026-04-20T08:00:00Z",
"startUtcOffset": "0s",
"endTime": "2026-04-20T08:35:00Z",
"endUtcOffset": "0s"
},
"exerciseType": "RUNNING",
"displayName": "Morning Trail Run",
"activeDuration": "1800s",
"metricsSummary": {
"caloriesKcal": 380.0,
"distanceMillimeters": 5000000.0,
"steps": "6200",
"averageSpeedMillimetersPerSecond": 2777.78,
"averagePaceSecondsPerMeter": 360.0,
"averageHeartRateBeatsPerMinute": "148",
"activeZoneMinutes": "30"
},
"exerciseMetadata": {
"hasGps": true
},
"exerciseEvents": [
{
"eventTime": "2026-04-20T08:15:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "PAUSE"
},
{
"eventTime": "2026-04-20T08:20:00Z",
"eventUtcOffset": "0s",
"exerciseEventType": "RESUME"
}
],
"splitSummaries": [
{
"startTime": "2026-04-20T08:00:00Z",
"startUtcOffset": "0s",
"endTime": "2026-04-20T08:15:00Z",
"endUtcOffset": "0s",
"activeDuration": "900s",
"splitType": "DISTANCE",
"metricsSummary": {
"distanceMillimeters": 2500000.0,
"caloriesKcal": 190.0
}
}
]
}
}
}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 read or write data for GPS routes and location tracking, request the following OAuth scopes in your application's access token:
- Read access:
https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly - Write access:
https://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly - Read access:
https://www.googleapis.com/auth/googlehealth.location.readonly
If a required scope is missing from the authorization headers, the Google Health API returns an authorization error.
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), set activeDuration to "1800s" (2,100 -
300). The API uses active duration to calculate averages, dividing total
distance by 1,800 seconds instead of 2,100.
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.
Real-time 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 in real time.
When your server receives a webhook notification, it contains the
healthUserId and the specific physical time interval of the workout. Your
server should process the notification asynchronously and then request the new
exercise data point from the /users/me/dataTypes/exercise/dataPoints
endpoint. For details on how to set up subscriptions, see
Webhook subscriptions.
Maintain consistent metrics
To provide a complete workout experience, your app must synchronize
high-frequency telemetry data points alongside the overall exercise session.
This ensures that the user's daily totals, historical trends, and detail charts
remain fully aligned.
Sync telemetry and sessions (write path)
When importing or writing a completed workout to the Google Health API, implement a multi-step write pattern:
- Write the session: File the summary event by posting a data point to
POST /users/me/dataTypes/exercise/dataPoints. - Write time-series intervals: Concurrently write the granular data
points logged during the workout (for example, minute-by-minute steps or
calorie burn intervals) to their respective collections:
POST /users/me/dataTypes/steps/dataPointsPOST /users/me/dataTypes/active-energy-burned/dataPointsPOST /users/me/dataTypes/heart-rate/dataPoints
Query detailed data for charts (read path)
When rendering historical workout dashboards or performance graphs for a specific workout session, query the granular telemetry using the session's time window:
- Query the session summaries: Call
/users/me/dataTypes/exercise/dataPointsto fetch the overall workout details and the finalmetricsSummary. - Fetch chart metrics: Inspect the workout's
interval.startTimeandinterval.endTime. Make secondaryGETcalls to the telemetry collections for that specific time window:GET /users/me/dataTypes/heart-rate/dataPoints?startTime=2026-04-20T08:00:00Z&endTime=2026-04-20T08:35:00Z
- Fetch GPS routes: If the session's metadata indicates GPS data is
present (
exerciseMetadata.hasGpsistrue), invoke theexportExerciseTcxhelper method to download route coordinates.