HealthKit has no server API, so the direction flips: your iOS app reads the watch with our Swift package and pushes to us. What reaches your webhook is the same event as from Garmin, under provider: "apple".
From 32.50 € a month billed annually, 30 days to change your mind.
in your iOS app — configure at launch, connect on a tap
import StrideeHealth
// Every launch, so iOS's background wake-ups land.
HealthSync.configure(HealthSync.Configuration(
tokenProvider: {
// Your route from device-token.js, with your own session.
let minted = try await MyAPI.strideeDeviceToken()
return HealthSync.DeviceToken(
token: minted.token, expiresAt: minted.expiresAt)
}
))
// When they tap "Connect Apple Health": iOS's sheet,
// then their history, then every new workout and night.
try await HealthSync.shared.connect()A signed POST /v1/device-tokens, behind your own sign-in, for the one user your server has already identified. The token lasts an hour, pushes for that user only and reads none of their data — a stolen one could add workouts to one history for the rest of its hour, and nothing else. Your signing key never ships in the app.
StrideeHealth is a Swift package for iOS 17 and later. Configured at launch, it registers the observers iOS wakes your app for, asks for the token when it needs one, and uploads each new workout and night — history first, then live. Uploads queue on disk and retry, so an outage of ours or of your token route loses nothing.
account.connected when they first connect, activity.created with a FIT file, wellness.created with the same metrics as Garmin’s — sealed to your public key and signed, with provider: "apple". The handler you already run does not branch. And a workout you POST /v1/workouts is scheduled on their Apple Watch by the same package.
HealthKit lives on the phone and is readable only by an app the user has granted. No server of yours or ours can ask Apple for a workout. Whatever you build runs inside your app — anchored queries so you never re-read what you have, observers for what is new, and a store of where you got to that survives reinstalls badly.
iOS will wake your app when a workout lands, but only with the entitlement ticked, the usage string present and the observers registered on every launch — not after the user taps something. Miss one and nothing fails loudly: data simply stops arriving whenever the app is closed. The SDK registers at configure() and the guide says where that call has to go.
A HealthKit workout is a row plus thousands of samples in separate stores — heart rate here, power there, the route in a third. There is no recording to download. We take the samples the SDK sends and encode the FIT file ourselves, so every Apple activity reaches you in the shape every other provider’s already does.
An iPhone and an Apple Watch both count steps; summed raw, the day doubles. Garmin Connect and Wahoo write their workouts into HealthKit too, so an athlete connected to both would deliver every run twice. The SDK uses HealthKit’s statistics queries, which merge devices correctly, and skips the bundles whose workouts already arrive natively.
Apple shows its permission sheet once per data type, ever, and never tells your app whether the answer was yes — a denial would itself reveal something about the user’s health. The SDK ships a primer screen to show first, and a lastDataFound signal that is the closest thing to a permission check iOS allows, with a button straight to the right page in Settings.
All of it is one Swift package, a token your server mints with POST /v1/device-tokens, and the webhook handler you write once for every provider.
Add the SDKin your iOS app — configure at launch, connect on a tap
import StrideeHealth
// Every launch, so iOS's background wake-ups land.
HealthSync.configure(HealthSync.Configuration(
tokenProvider: {
// Your route from device-token.js, with your own session.
let minted = try await MyAPI.strideeDeviceToken()
return HealthSync.DeviceToken(
token: minted.token, expiresAt: minted.expiresAt)
}
))
// When they tap "Connect Apple Health": iOS's sheet,
// then their history, then every new workout and night.
try await HealthSync.shared.connect()Checkout is the signup. No waitlist, no sales call.
Cancel any time from the Stripe billing portal, or email [email protected] within 30 days and we refund you.
Plans start at
Or 39 €/month, month to month. Paying annually gets you two months free.
Hacker, Startup, Scale and Enterprise differ on how many of your users may connect a watch. The API is the same on every plan.
See the plans14-day free trial · cancel any time
We create the account on the email you pay with, automatically. Sign in at platform.stridee.com/login. Nothing to wait for.
Not a server one. Apple Watch data lives in HealthKit on the paired iPhone, and HealthKit is readable only by an app running on that phone that the user has granted access to. There is no endpoint at Apple to fetch a workout from, and no OAuth to hold — which is why no unified wearable API can connect an Apple Watch from a web page. What exists is on-device: HealthKit for reading, WorkoutKit for putting a workout on the watch. Our Swift package does both inside your app and pushes to us, and from there everything is the same API as Garmin.
Yes. Only code running in an app the user has granted can read their HealthKit data, so there is no hosted consent page for Apple the way there is for Garmin or Polar — the permission sheet is iOS’s own, shown by your app. If your product has no iOS app, Apple Watch data is not reachable, by us or by anyone. If it has one, the integration is a Swift package, three settings in your Xcode target and one route on your server.
Only the one you already have to ship an iOS app. Your target needs the HealthKit capability with Background Delivery ticked, and an NSHealthShareUsageDescription for the sentence on Apple’s permission sheet. The SDK only reads, so no update description is needed. There is no registration with Apple on our side and nothing of ours in your entitlements — your app talks to HealthKit directly, as Apple requires, and to us with a token your server mints.
Two weeks free, then from 32.50 € a month billed annually — or 39 € a month with no year to commit to — for the whole API, every provider and every endpoint, with no charge for calls. What separates the plans is how many of your users may connect a watch. Hacker is up to 100, for a project and its first users; Startup covers up to 500; Scale includes 1,500 and bills the ones past that at a published per-user rate, with no ceiling; Enterprise is a contract with a better rate again; and none of them charges for calls, activities or endpoints. The usual price for a unified wearable API starts in the hundreds of dollars a month and charges again for each connected user, which is a pricing model that punishes exactly the thing you are trying to do. There is a 30-day money-back guarantee on any charge, and cancelling is a button in the Stripe billing portal; access ends when the period does.
The same events as from any provider, with provider: "apple": account.connected, activity.created with a FIT file, wellness.created and wellness.updated, and account.disconnected. A workout the watch saves reaches HealthKit on the phone within moments and iOS wakes your app to upload it, so a run that ends with the phone unlocked is in your webhook minutes later. Health data is unreadable while the phone is locked, so a run that ends with it in a pocket syncs after the next unlock. Nothing is lost in between: uploads queue on disk and retry.
Yes, and more of it than from any other provider: on the first sync the SDK sends every workout HealthKit holds — on an Apple Watch that is routinely years — and the last 90 days of wellness, or whatever you set wellnessHistoryDays to. It arrives as ordinary deliveries through the same fan-out as a live workout. The phone does the uploading, so history lands while your app is running or woken in the background; a user who connects and never opens your app again still gets there, more slowly. An app replacing its own HealthKit sync can hand the SDK its query anchor so nothing is sent twice.
Yes. Apple has no server API for it either — the only way in is WorkoutKit, inside an iOS app — so with schedulesWorkouts on, the SDK fetches what you created with POST /v1/workouts and schedules it in the Workout app on the athlete’s watch. Nothing changes on your server: the same call, the same pushes array, and Apple’s entry reads pending until the phone syncs, then synced. A workout needs a date, because the Workout app has a calendar and no library; and when the athlete runs it, the activity.created that comes back carries the workout_id you were given.
No. Garmin Connect and Wahoo write their workouts into HealthKit, and if you also connect those providers, their workouts already arrive natively — so the SDK skips workouts those apps wrote, by default. The list is a setting, excludedSourceBundleIDs, if you need to add to it or clear it. Steps and calories are computed with HealthKit’s statistics queries, which merge the iPhone and the watch correctly rather than counting both.
Because it is a different statistic. Apple measures SDNN; Garmin, Zepp and Fitbit report RMSSD. The two have different normal ranges and there is no exact conversion between them, so Apple’s arrives as hrv_sdrr and the others as hrv_avg. A chart that plots hrv_avg shows no Apple line rather than a wrong one, which is the behaviour you want from a field name. The sleep stages, daily totals and the rest of the nine wellness kinds use the same metric names as every other provider.
No, and that is a difference from Garmin worth knowing. Each app has its own HealthKit grant, so the workout your app reads is yours alone: it is never fanned out to another account, the way a Garmin athlete connected to two developers delivers to both. It also means a user who removes your app, or revokes it in Health, stops the data at the source — there is nothing of theirs we could go on fetching.
Not today. Health Connect is the Android counterpart of HealthKit and we do not read it yet; this integration is iOS 17 and later. Fitbit and Pixel Watch are covered through the Google Health API — see the Fitbit page — and Garmin, COROS, Polar, Wahoo, Zepp and Hammerhead connect from any platform, because their link is with the athlete’s account rather than their phone.
The full documentation is public and needs no account. Still have questions? Ask us in Discord