CONNECT APP
Build with Google Health
Productivity
- OAuth
MCP
Give your agent Google Health tools
Every Google Health action is exposed as an MCP tool on Pipedream's remote server. Point a client at it with your end user's ID and Connect resolves that user's Google Health account for each tool call — you store no tokens.
// accessToken: mint a short-lived token with the Connect SDK — see the MCP guide
const transport = new StreamableHTTPClientTransport(
new URL("https://remote.mcp.pipedream.net/v3"),
{
requestInit: {
headers: {
Authorization: `Bearer ${accessToken}`,
"x-pd-project-id": "{project_id}",
"x-pd-environment": "production",
"x-pd-external-user-id": "{external_user_id}", // any stable ID for this user in your system
"x-pd-app-slug": "google_health",
},
},
},
)
const mcp = new Client({ name: "my-agent", version: "1.0.0" })
await mcp.connect(transport)
const { tools } = await mcp.listTools()
// e.g. run Get Body Measurements:
const result = await mcp.callTool({
name: "google_health-get-body-measurements",
arguments: {
startDate: "Start Date",
endDate: "End Date",
},
})# access_token: mint a short-lived token with the Connect SDK — see the MCP guide
headers = {
"Authorization": f"Bearer {access_token}",
"x-pd-project-id": "{project_id}",
"x-pd-environment": "production",
"x-pd-external-user-id": "{external_user_id}", # any stable ID for this user in your system
"x-pd-app-slug": "google_health",
}
async with streamablehttp_client("https://remote.mcp.pipedream.net/v3", headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
# e.g. run Get Body Measurements:
result = await session.call_tool("google_health-get-body-measurements", {
"startDate": "Start Date",
"endDate": "End Date",
})API PROXY
Call the Google Health API directly
For an endpoint with no pre-built tool, the Connect proxy forwards your request to the Google Health API with the connected user's credentials attached. You store no tokens and write no refresh logic.
const resp = await pd.proxy.get({
externalUserId: "{external_user_id}", // any stable ID for this user in your system
accountId: "apn_xxxxxxx",
url: "https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints",
})
// Any allowed Google Health endpoint works here. Pipedream attaches the
// connected account's credentials to the outgoing request.# The path segment is the target URL, URL-safe base64 encoded:
# https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints
curl "https://api.pipedream.com/v1/connect/{project_id}/proxy/aHR0cHM6Ly9oZWFsdGguZ29vZ2xlYXBpcy5jb20vdjQvdXNlcnMvbWUvZGF0YVR5cGVzL3N0ZXBzL2RhdGFQb2ludHM?external_user_id={external_user_id}&account_id=apn_xxxxxxx" \
-H "Authorization: Bearer {access_token}" \
-H "x-pd-environment: production"SDK
Run Google Health actions from your backend
Connect a user's Google Health account once, then run Get Body Measurements on their behalf from your own code — TypeScript, Python, or plain HTTP.
import { PipedreamClient } from "@pipedream/sdk"
const pd = new PipedreamClient({
projectId: process.env.PIPEDREAM_PROJECT_ID!,
clientId: process.env.PIPEDREAM_CLIENT_ID!,
clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
projectEnvironment: "production",
})
const result = await pd.actions.run({
id: "google_health-get-body-measurements",
externalUserId: "{external_user_id}", // any stable ID for this user in your system
configuredProps: {
google_health: { authProvisionId: "apn_xxxxxxx" },
startDate: "Start Date",
endDate: "End Date",
},
})from pipedream import Pipedream
pd = Pipedream(
client_id="{oauth_client_id}",
client_secret="{oauth_client_secret}",
project_id="{project_id}",
project_environment="production",
)
result = pd.actions.run(
id="google_health-get-body-measurements",
external_user_id="{external_user_id}", # any stable ID for this user in your system
configured_props={
"google_health": {"authProvisionId": "apn_xxxxxxx"},
"startDate": "Start Date",
"endDate": "End Date",
},
)curl -X POST https://api.pipedream.com/v1/connect/{project_id}/actions/run \
-H "Content-Type: application/json" \
-H "X-PD-Environment: production" \
-H "Authorization: Bearer {access_token}" \
-d '{
"external_user_id": "{external_user_id}",
"id": "google_health-get-body-measurements",
"configured_props": {
"google_health": { "authProvisionId": "apn_xxxxxxx" },
"startDate": "Start Date",
"endDate": "End Date"
}
}'TOOLS
Google Health actions
On-demand operations your product or agent can configure and run on behalf of a connected user.
-
Get Body Measurements
actionGet the user's weight logs with computed BMI, their body-fat percentage logs, and their current height. Raw logs, so there is no date cap; at most 1000 weigh-ins per call, withtruncatedset when there were more. Example: startDate="2026-08-01", endDate="2026-08-25" →weightLogs: [{ time, weightKg: 74.2, weightLb: 163.6, bmi: 22.9, notes }],bodyFatLogs: [{ time, percentage }], andheight: { heightCm, heightIn, measuredAt }.weightLogsandbodyFatLogsare newest first. Two things to tell the user rather than guess: the API has no BMI field, so BMI is computed here as kg ÷ height in m² and isnullwhen no height is on record.heightis not measured over the requested range at all — it is the most recent height found in a ten-year lookback, capped at one page, so checkmeasuredAtbefore calling it current: it can be years old, and when nothing turns upbmiComputableisfalseand everybmiisnull. Body fat is measured separately from weight, so a weigh-in on a scale without body composition appears inweightLogswith no matchingbodyFatLogsentry. Set includeBodyFat=false to skip the body-fat request entirely —bodyFatLogsthen comes back empty because it was never asked for, which is not the same as the user having no body-fat data. See the documentationRead-onlyv0.0.2 -
Get Daily Activity Summary
actionGet a full day of activity at once: steps, distance, calories, active minutes by intensity, active zone minutes by heart rate zone, and floors. The right tool when the user wants an overall picture of a day rather than one metric — use Get Daily Step Count for steps alone or Get Heart Rate for heart rate detail. The range is inclusive and capped at 14 days (calories and active minutes impose that limit on the aggregation). Example: startDate="2026-08-24" →days: [{ date, steps: 8432, distanceKm: 6.1, totalCalories: 2380, activeCalories: 620, activeMinutes: { light, moderate, vigorous, total }, activeZoneMinutes: { fatBurn, cardio, peak, total }, floors: 12 }]. Set dataSourceFamily="google-wearables" to exclude manually logged activity. Anullmetric means that one metric did not sync for that day and says nothing about the rest of the day — a day can carry real steps alongside anulldistanceKm, so do not report the whole day as empty. An emptydaysarray is the separate case where no activity data synced at all for the range. Never report either as zero. The API has no concept of daily goals, so no targets are returned. See the documentationRead-onlyv0.0.3 -
Get Daily Step Count
actionGet the user's total step count per day — the tool for any "how many steps" question. Returns one pre-aggregated total per day, not raw samples. Use Get Daily Activity Summary instead when distance, calories, active minutes, or floors are wanted alongside steps. The range is inclusive and capped at 90 days, because these totals are server-aggregated. Example: startDate="2026-08-17", endDate="2026-08-23" →days: [{ date, steps: 8432 }, ...]plustotalSteps,averageSteps,daysRequestedanddaysWithData. Set dataSourceFamily="google-wearables" to count only tracker-recorded steps, excluding manual entries. Days the tracker never reported are omitted fromdaysentirely, sodaysWithDatacan be lower thandaysRequestedandaverageStepsis the mean overdaysWithData. An emptydaysarray means nothing synced, not zero steps —totalStepsandaverageStepsarenullin that case rather than 0. See the documentationRead-onlyv0.0.3 -
Get Heart Rate
actionGet the user's heart rate aggregated into time windows, plus their daily resting heart rate. Each window reports average, minimum, and maximum BPM; pick the window size withgranularity. The range is inclusive and capped at 14 days, because the windows are server-aggregated. Example: startDate="2026-08-24", granularity="900s" → 96 fifteen-minute windows as{ startTime, endTime, avgBpm, minBpm, maxBpm }, plusrestingHeartRate: [{ date, bpm }]and an overallsummary. Use granularity="86400s" for one figure per day. Resting heart rate comes back from this tool too — there is no separate resting-HR tool. For active zone minutes, which are heart-rate derived but reported as activity, use Get Daily Activity Summary. See the documentationRead-onlyv0.0.2 -
Get Identity
actionGet the connected user's Google Health identifiers:healthUserIdandlegacyUserId, the ID the same user had on the legacy Fitbit Web APIs. Use it to correlate records between a system that stored Fitbit IDs and one now on Google Health. Also the cheapest way to confirm the connection works, since it needs no synced data. Example: call with no parameters → returns{ healthUserId: "NGL8Q2...", legacyUserId: "2E4RVC" }.legacyUserIdis 1-63 characters of letters, numbers and hyphens — treat it as an opaque string and do not assume a fixed length or format. It is empty for users who never had a Fitbit account. See the documentationRead-onlyv0.0.2 -
Get Nutrition and Hydration Logs
actionGet the user's logged food and water intake, with aggregate calorie, macro and water totals. Example: startDate="2026-08-24" →entries: [{ time, foodDisplayName: "Greek yogurt", mealType: "BREAKFAST", calories: 180, totalFatG: 4.5, totalCarbohydrateG: 9 }],hydration: [{ time, milliliters: 500, liters: 0.5, flOz: 16.9 }], andtotals.totalsis one object covering the whole requested range, not per-day figures — call a single day at a time if daily breakdowns are wanted. Entries have no date-range limit, buttotalsare server-aggregated and cap the range at 90 days — set includeTotals=false to read entries over a longer span, which makestotalsnull. At most 1000 food entries and 1000 hydration entries come back per call (five pages of 200);truncated: truemeans there were more, so check it before treating the entry list as complete and narrow the range if it is set. Only food the user logged manually appears here; nothing is inferred from activity, so an empty result means nothing was logged, not that nothing was eaten. See the documentationRead-onlyv0.0.3 -
Get Sleep Data
actionGet the user's sleep sessions with per-stage totals, time asleep and awake, and a derived efficiency figure. A session is attributed to the date the user woke up, matching Fitbit — asking for 2026-08-24 returns the night of the 23rd into the 24th. Example: startDate="2026-08-24" →sessions: [{ startTime, endTime, type: "STAGES", isMainSleep: true, minutesAsleep: 431, minutesAwake: 48, efficiency: 0.9, stageTotals: { LIGHT: 240, DEEP: 71, REM: 120, AWAKE: 48 } }], plusmainSleepandtotalMinutesAsleep. Three things to tell the user rather than invent: this API has no sleep score, so none is returned, andefficiencyis computed here as time asleep over time in bed — not the figure Fitbit showed. Stage names depend ontype, so readstageTotalsrather than assuming a fixed set:STAGESsessions report LIGHT/DEEP/REM/AWAKE, olderCLASSICones only ASLEEP/AWAKE/RESTLESS. Naps are separate sessions withisNap: true. At most 125 sessions per call;truncated: truemeans narrow the range. See the documentationRead-onlyv0.0.2 -
List Data Points
actionRead raw data points for any Google Health data type the dedicated tools do not cover — blood oxygen (oxygen-saturation), heart rate variability, respiratory rate, VO2 max, body temperature, exercise sessions, sedentary periods, altitude, swim lengths and more; see thedataTypeoptions for the full list. Prefer a dedicated tool where one exists, since those return compact pre-aggregated results while this returns raw records and can be large: Get Daily Step Count (steps), Get Daily Activity Summary (calories, distance, active minutes, floors), Get Heart Rate, Get Sleep Data, Get Body Measurements (weight, body fat), Get Nutrition and Hydration Logs (food, water). Example: dataType="oxygen-saturation", startDate="2026-08-24" →dataPointswith each reading's value and timestamp, newest first. Two pages ofpageSizecome back (default 50 → 100 records) andpageSizeis capped at 500, so one call returns at most 1000 records;truncated: truemeans there were more — narrow the date range or raisepageSizeup to that cap.foodandfood-measurement-unitare reference catalogues, not time series — the date range does not apply, the response setsdateFilterApplied: false, and you must not describe those results as belonging to a particular day. Not available here:total-calories,floors, andcalories-in-heart-rate-zoneare aggregate-only (use Get Daily Activity Summary); ECG and irregular-rhythm data need OAuth scopes this app does not request. See the documentationRead-onlyv0.0.2
EVENTS
Google Health triggers
Event sources your backend can deploy for users and receive through a webhook.
No Google Health triggers are available yet.
- App slug
- google_health
- Authentication
- OAuth
- Categories
- Productivity
- Actions
- 8
- Triggers
- 0
- API proxy
- Available
OAuth scopes
These are the scopes Pipedream's managed Google Health OAuth client requests when one of your users connects an account. Supply your own OAuth client to request a different set.
- https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
- https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
- https://www.googleapis.com/auth/googlehealth.sleep.readonly
- https://www.googleapis.com/auth/googlehealth.nutrition.readonly