Need help with your Google Health integration? Pop into our Discord if you have questions or want to discover how Open Wearables can solve your problems.
Overview
Google Health data reaches Open Wearables through two independent paths that share the singlegoogle provider identity:
- Health Connect (mobile SDK) — data pushed from an Android device via the Sync SDK. See the Android SDK guide.
- Google Health API (cloud OAuth) — this guide. A server-side OAuth 2.0 flow against the Google Health API that lets you connect a user’s Google account and pull their data over REST, plus receive notify-only webhooks.
Supported data types
Data delivery
Data granularity and fetch modes
The Health API exposes the same underlying data through three different operations. Open Wearables picks one per theDEFAULT_DATA_GRANULARITY setting, and — at the finest granularity — the GOOGLE_USE_RECONCILE flag.
GOOGLE_USE_RECONCILE only takes effect at raw granularity. hourly/daily always use windowed rollUp aggregates regardless of the flag.Reconcile vs. list — why it matters
A user commonly has the same activity reported by multiple sources (e.g. the phone’s pedometer and the Fitbit app both counting steps). The two modes handle that overlap differently:reconcile(default) returns one merged stream, deduplicated across all sources at the interval level — exactly what the native Google Health / Fitbit app displays. There is no single device behind a merged value, so reconciled points carry no device attribution (device_modelis empty).listreturns the raw per-source points, each tagged with its originating device. This preserves device attribution but stores overlapping sources separately; Open Wearables then deduplicates on read by source priority (it does not sum them).
Reconcile (2560) matches the app exactly — it keeps intervals that either source captured while removing the overlap. Read-time dedup of the list data would instead pick a single source (1919), which is why reconcile is the default: it produces app-accurate totals.
Choose
list (GOOGLE_USE_RECONCILE=false) only when you specifically need per-device attribution (e.g. to know which watch recorded a reading). For app-matching totals, keep the default.What you need by the end
- A Google Cloud project with the Health API enabled
- OAuth client credentials (Client ID + Secret) with the Google Health scopes
- Redirect URI registered in your OAuth client
- (Webhooks only) A service account for project-level subscriber registration
Prerequisites
- A Google Cloud project
- Access to the Google Health API for that project (
gcloud services enable health.googleapis.com)
Application walkthrough
1
Enable the Health API and create an OAuth client
In the Google Cloud Console, select your project and enable the Health API:Then create an OAuth 2.0 Client ID (Web application) under APIs & Services → Credentials, and add your server-side callback as an Authorized redirect URI:
- Local dev:
http://localhost:8000/api/v1/oauth/google/callback
2
Configure credentials in Open Wearables
Add the following to your Configuration details:
.env file:The redirect URI is derived from
API_BASE_URL — it must match the Authorized redirect URI on your OAuth client ({API_BASE_URL}/api/v1/oauth/google/callback).3
Connect a user via OAuth
With credentials configured and your instance running, initiate the OAuth flow.1. Get the authorization URL:2. Redirect the user to the returned You should see a connection with
authorization_url. They log in to Google and grant consent.3. Google redirects back to {API_BASE_URL}/api/v1/oauth/google/callback; Open Wearables exchanges the code for tokens and stores the connection. It also resolves the user’s stable healthUserId (via the Health API identity endpoint) as the connection’s provider user id — this is what inbound webhooks are matched against.4. Verify the connection:"provider": "google" and "status": "active".4
Sync data
An initial sync runs automatically after a successful OAuth connection. To trigger one manually:
5
Verify the integration
Fetch a synced 24/7 series (e.g. steps):If data is returned, your Google Health API integration is working end-to-end.
Webhooks
Google Health webhooks are notify-only: each notification names the changeddataType, operation (UPSERT/DELETE), and the physical-time intervals that changed — but carries no data. Open Wearables verifies the request, then fetches the changed data over REST for those intervals.
Two distinct secrets are involved:
GOOGLE_WEBHOOK_SECRET— a bearer token you register with Google that it echoes back in theAuthorizationheader of every notification, so Open Wearables can verify the ping is genuine. Defaults toSECRET_KEYif unset.- Service-account credentials — used only to register the subscriber (a project-level admin call). Not involved in receiving notifications.
Receiving and processing webhooks needs only
GOOGLE_WEBHOOK_SECRET. The service account is required only to register the subscriber programmatically — you can also register it manually via gcloud/the API console.Webhook subscriber registration
Subscribers live at the project level (POST /v4/projects/{project}/subscribers), so registration authenticates as the project via a service account, not a user’s OAuth token.
1
Create a service account
2
Provide the credentials
Either mount a JSON key and point to it, or rely on Application Default Credentials (ADC) if running on GCP:Add to
.env:3
Register the subscriber
Switching the provider’s live sync mode to
webhook registers the subscriber automatically. Google then performs an endpoint-verification handshake (POST {"type":"verification"}) against {API_BASE_URL}/api/v1/providers/google/webhooks, which must return 2xx when authenticated. Once verified, notifications begin flowing.Managing subscribers without app credentials (gcloud / console)
If you’d rather not give the app a service account, create and manage the subscriber yourself and leaveGOOGLE_SERVICE_ACCOUNT_FILE/GOOGLE_PROJECT_ID unset. The app then
needs only GOOGLE_WEBHOOK_SECRET to verify inbound notifications — it never calls the
project-level subscriber API.
In this mode the in-app
.../webhooks/subscriptions management endpoints (list / register /
update / delete) won’t work — they require project credentials. Use the commands below instead.subscriberId
(open-wearables) the app uses, so it stays interchangeable.
dataTypes above is an abbreviated example — use the set the app supports for webhooks
(steps, distance, hydration-log, heart-rate, run-vo2-max, daily-resting-heart-rate,
heart-rate-variability, weight, body-fat, blood-glucose, daily-respiratory-rate, sleep,
exercise). Registering a data type the app doesn’t handle just means its notifications are ignored.Next Steps
API Reference
Explore the Open Wearables API endpoints.
Supported Providers
See all supported providers.
Support
Need Help?
- Join our Discord and ask a question.
- Check GitHub Discussions.
- Check the Google Health API Documentation.

