Garmin API Push Notifications: How Callback Sync Works
Key Takeaways
- Garmin's push notification system delivers data to your registered callback URLs when users sync their devices, not when you request it
- Each Garmin data type has a separate callback URL: activities, daily summaries, sleep, HRV, stress, body composition and more
- Your handlers must respond with HTTP 200 within a few seconds; all processing must be asynchronous
- Garmin retries failed deliveries, so idempotent processing is essential at every level
- Open Wearables pre-builds all Garmin callback infrastructure and delivers normalized data through a query API
Introduction
Most API integrations follow the same pattern: your code makes a request, the API returns data. You control the timing, the scope and the frequency. Garmin's Health API inverts this entirely.
When a Garmin user syncs their device, Garmin processes the data on their backend and pushes it to callback URLs that you have registered in advance. You do not request the data. Garmin delivers it. Your job is to be ready to receive it at any time, process it correctly, and return a 200 response fast enough that Garmin does not mark the delivery as failed.
This architecture is efficient once it is running. You only process data when it actually exists, which means no polling and no wasted API calls. But the operational requirements are more demanding than a traditional pull API: always-on public HTTPS endpoints, asynchronous processing infrastructure, idempotent database operations, and monitoring to detect delivery failures quickly.
How the Push System Works
The data flow from a Garmin device sync to your database has several steps. Understanding each step is necessary for building a reliable integration.
When a user syncs their Garmin device via the Connect mobile app or a USB/WiFi connection to Garmin Connect on desktop, Garmin's backend processes the raw data from the device. This processing extracts structured data: activities, daily health summaries, sleep records, HRV measurements and so on. Garmin then looks up which third-party applications the user has authorized and sends the relevant data to each application's registered callback URL.
Your server receives a POST request with a JSON payload. The payload may contain multiple records of the same type if the user has not synced in several days. You process the data, store it, and return HTTP 200. Garmin marks the delivery as successful. If you return a non-200 response or fail to respond within the timeout window, Garmin marks the delivery as failed and will retry.
The retry behavior means your processing must be idempotent. If Garmin sends the same activity twice (once initially and once as a retry after a transient failure on your end), processing it twice should produce the same result as processing it once. Use upsert operations keyed on Garmin's unique identifiers rather than inserts that could create duplicates.
Callback Types and What They Carry
Garmin supports separate callback URLs for each data category. You register only the ones you need. Each callback receives a different payload structure.
Activities are the most data-rich payload. Each activity includes sport type, start time, duration, distance, calories, average and maximum heart rate, and summary statistics specific to the sport type. Running activities include pace, cadence and elevation. Cycling activities include power and cadence. The payload also contains a URL to fetch the full activity details including per-second data streams if needed. Activity payloads identify the user by their OAuth access token, which you must map to your internal user ID.
Daily summaries consolidate health data for a calendar day: steps, floors climbed, active and BMR calories, distance, intensity minutes, resting heart rate, average stress level, Body Battery high and low values, average respiration rate, average SpO2 where available, and sleep duration.
Sleep records contain sleep start and end times, sleep duration, time in each stage (deep, light, REM, awake), average respiration rate during sleep, average SpO2 during sleep where available, and an overall sleep score.
HRV summaries include the weekly average, the last-night average, the last-night 5-minute high, and a status classification (balanced, unbalanced, low or poor) based on Garmin's proprietary interpretation of HRV relative to the user's baseline.
Implementing the Callbacks
The most important rule for webhook handlers is: do not do heavy work in the handler. Return 200 immediately and queue the processing.
@app.route('/garmin/activities', methods=['POST'])
def receive_activities():
process_garmin_activities.delay(request.json)
return '', 200
This pattern is critical. If your database is slow, your normalization logic is complex, or your infrastructure is under load, inline processing risks timing out and causing Garmin to retry. Queuing with Celery, RQ or any task queue keeps handler response time in milliseconds regardless of downstream conditions.
For user identification, Garmin includes the OAuth access token in each payload record as userAccessToken. You must store this token at OAuth connection time mapped to your internal user ID. Every callback handler needs to look up the user from this token before processing. If the lookup fails (the user has disconnected or the token has been revoked), discard the payload and return 200 to prevent Garmin from retrying.
For idempotency, key your database upserts on Garmin's IDs. Activities have a unique activityId. Daily summaries have calendarDate plus userId as a natural composite key. Sleep records have their own IDs. Design your data layer to treat repeated processing of the same record as a safe no-op.
Monitoring and Failure Detection
Push-based integrations have a failure mode that pull integrations do not: silent data gaps. If your callback endpoint goes down, Garmin retries for a period and then stops. When your endpoint comes back up, Garmin does not automatically resend data from the outage window. That data is gone unless you implement a backfill mechanism.
Monitor your callback endpoints with uptime checks and alert on downtime quickly. Monitor incoming delivery volume per data type and alert when it drops to zero unexpectedly. Users who sync their Garmin devices daily should generate daily callbacks. If you see no deliveries for a given user over 48 hours, something is likely wrong.
Open Wearables and Garmin Push
Open Wearables pre-builds the complete Garmin callback infrastructure. It handles OAuth 1.0a authentication, callback URL registration for all data types, asynchronous processing of push payloads, user token mapping, idempotent storage, and normalization of Garmin's data schema into a consistent format shared with other providers.
You configure Open Wearables with your Garmin Health API credentials, register your Open Wearables instance's callback URLs with Garmin, and receive normalized data through a simple query interface. The push complexity is abstracted away.
FAQ
What happens if my server is down when Garmin sends data?
Garmin retries failed deliveries on a schedule. The retry window and frequency are controlled by Garmin. Data delivered after the retry window closes is lost unless you implement historical backfill. Monitor your endpoints and minimize downtime.
Can I request specific Garmin data on demand rather than waiting for push?
Garmin's Health API is push-first. Some pull endpoints exist for initial historical backfill when a user connects, but real-time data delivery relies on push. Do not design your architecture around on-demand Garmin API calls.
How do I test Garmin callbacks in local development?
Use a tunneling service like ngrok to expose your local server with a public HTTPS URL and register that URL temporarily with Garmin during development. The Garmin sandbox environment generates synthetic push events that let you test your handlers without a physical device.
Are Garmin activity payloads always complete?
Activity payloads contain summary data. To access per-second data streams (GPS points, heart rate by second, power by second), you make a separate request to the activity detail URL included in the payload. This additional request consumes Garmin API quota.
How does user identification work in push payloads?
Each data record in a push payload includes userAccessToken, which is the OAuth access token issued to that user when they connected your application. Store this token in your database at connection time keyed to your internal user ID, and use it as the lookup key in every callback handler.
Garmin Integration
View the full Garmin integration documentation on Open Wearables.
See Related Articles
Garmin Connect API: Developer Guide for Activities and Health Metrics