Access Apple HealthKit from your web app through the Despia native bridge. Despia gives you three ways to work with health data: read historical records on demand, write new samples back to HealthKit, and subscribe to live updates via server webhooks. All three work from JavaScript with no native code required.Documentation Index
Fetch the complete documentation index at: https://setup.despia.com/llms.txt
Use this file to discover all available pages before exploring further.
HealthKit is iOS only. Always gate calls behind an
isDespiaIOS check so your app degrades gracefully in a browser or on Android.Installation
- Bundle
- CDN
Apple Developer and Despia setup
HealthKit requires the HealthKit capability on your core app bundle ID before any read or write call works. Configure Apple Developer first, then enable Health Data in the Despia Editor and rebuild.Sign in to Apple Developer
Go to developer.apple.com and sign in with the Apple Developer account that owns your app’s primary bundle ID. Navigate to Certificates, Identifiers & Profiles > Identifiers.
Add HealthKit to your core app bundle ID
Find your core app (e.g.
com.despia.myapp), click into it, and check HealthKit under Capabilities. Click Save. Without this, HealthKit reads will return empty arrays and writes will fail silently, since iOS rejects HealthKit access for any app whose bundle ID does not declare the capability.Enable Health Data in the Despia Editor
Open the Despia Editor and go to App > Addons > Health Data. Toggle the addon on. This signals Despia to compile the HealthKit framework and the matching usage descriptions into your next build.
Choosing the right approach
HealthKit data can be accessed in three ways. Which one to use depends on whether you need data right now, want to save data, or need to react to changes continuously.| Approach | Use when | How it works |
|---|---|---|
| Read | You need historical data at a specific moment, on page load, on a button tap, or when building a report | Call readhealthkit:// or healthkit://workouts and await the result. Returns records for the last N days |
| Write | You want to save a value back to HealthKit, for example logging a weight entry or a step count from your own sensor | Call writehealthkit:// with a value. Adds a new sample without replacing existing data |
| Observer | You need your server to stay in sync with the user’s health data automatically, without requiring the user to open the app | Register a webhook with healthkit://observe. Despia posts new data to your server whenever HealthKit updates, even in the background |
How it works
Define theisDespiaIOS check once at the top of your app and reuse it throughout. Pass one or more identifiers as a comma-separated list on the URL host, Despia routes the request through the native bridge in a single dispatch and returns one response keyed by identifier.
Read
Usereadhealthkit:// to fetch historical data on demand. This is the right approach when your UI needs to display health data at a point in time, on load, after a user action, or when generating a report. You control exactly when the fetch happens and how many days of history to retrieve.
Pass any valid HKQuantityTypeIdentifier, HKCategoryTypeIdentifier, HKWorkoutTypeIdentifier, or HKCharacteristicTypeIdentifier as the URL host, plus an optional days parameter. See Identifier reference for the full list.
Reading multiple identifiers
Most real apps need more than one metric at a time, a dashboard typically wants steps, heart rate, calories, and sleep all at once. Comma-separate the identifiers on the URL host and Despia returns them in a single response, keyed by identifier name.healthkitResponse holds the same array shape that a single-identifier read would return for that type. Quantity types return daily values, sleep returns stage intervals, workouts return session records. The single days parameter applies to every identifier in the call.
You can mix categories freely in one call as long as they all accept a days window:
HKCharacteristicTypeIdentifierDateOfBirth, biological sex, blood type, skin type) are static values and do not accept days, so fetch them with their own dedicated call.
Quantity types
Quantity types cover numeric metrics: steps, heart rate, distance, body mass, calories, and more. Each record represents one day’s value for the requested identifier.Start of day in ISO 8601 format
The health metric value for that day
Unit of measurement, e.g.
count, count/min, kg, m. Determined automatically by the identifier.Sleep data
Sleep analysis usesHKCategoryTypeIdentifierSleepAnalysis. Unlike quantity types, sleep returns individual stage intervals rather than daily aggregates, each record covers a contiguous block of one sleep stage with its own start and end time.
ISO 8601 start time of the sleep stage interval
ISO 8601 end time of the sleep stage interval
Raw integer from
HKCategoryValueSleepAnalysisHuman-readable stage:
inBed, awake, asleep, core, deep, or remWorkouts
Use the dedicatedhealthkit://workouts scheme to fetch workout sessions, optionally enriched with per-workout statistics like average heart rate or summed active energy. The response lands on window.healthkitWorkouts as a flat array, distinct from the multi-type healthkitResponse object used by readhealthkit://.
Number of days back to look. Defaults to
1.Comma-separated list of per-workout quantity statistics. Each entry is a real
HKQuantityTypeIdentifier followed by an aggregation suffix. Omit to skip per-workout stats. See Per-workout statistics.ISO 8601 start time of the workout
Apple’s activity enum name in PascalCase, for example
Running, Cycling, FunctionalStrengthTraining. See HKWorkoutActivityType for the complete list.Duration in seconds
Kilocalories burned.
0 if the source did not record this.Distance in meters.
0 if not applicable, for example strength training.Primary metric, picked dynamically: distance if greater than
0, otherwise calories, otherwise duration in secondsUnit of
value: m, kcal, or sPer-workout quantity statistics, present only when
included= is non-empty. Each entry has key, value, and unit.Per-workout statistics
Passincluded= to compute aggregated quantity values scoped to each workout’s time range. Each entry is an HKQuantityTypeIdentifier plus an aggregation suffix. The native side strips the suffix to request authorization for the underlying type, then runs the aggregation across that workout’s startDate to endDate window. The result is the avg, max, min, or sum of that signal during the workout, not over the whole day.
| Suffix | Aggregation | Example |
|---|---|---|
Average | Discrete average | HKQuantityTypeIdentifierHeartRateAverage |
Max | Discrete maximum | HKQuantityTypeIdentifierHeartRateMax |
Min | Discrete minimum | HKQuantityTypeIdentifierHeartRateMin |
Sum | Cumulative sum | HKQuantityTypeIdentifierActiveEnergyBurnedSum |
| (none) | Discrete average | HKQuantityTypeIdentifierHeartRate |
| Goal | included= value |
|---|---|
| Heart rate range per workout | HKQuantityTypeIdentifierHeartRateAverage,HKQuantityTypeIdentifierHeartRateMax,HKQuantityTypeIdentifierHeartRateMin |
| Total energy per workout | HKQuantityTypeIdentifierActiveEnergyBurnedSum |
| Pace and top speed for runs | HKQuantityTypeIdentifierRunningSpeedAverage,HKQuantityTypeIdentifierRunningSpeedMax |
| Average and peak power for rides | HKQuantityTypeIdentifierCyclingPowerAverage,HKQuantityTypeIdentifierCyclingPowerMax |
Exact identifier you passed in
included=, including the aggregation suffixStringified numeric result. Wrap with
Number() before doing math. A value of "0" means the source did not record that signal during the workout, treat as missing rather than literal zero.HealthKit unit string, for example
count/min, kcal, mAuthorization for every base quantity type referenced in
included= is requested automatically on the first call, the suffix is stripped before the auth request. Invalid identifiers in included= are silently skipped, valid ones in the same call still come through. If the user denies access or the build does not have HealthKit linked, window.healthkitWorkouts resolves to [], so always check Array.isArray() before reading.readhealthkit://HKWorkoutTypeIdentifier endpoint continues to work and is the right choice when you need workouts in the same call as other unrelated identifiers, for example pulling steps, heart rate, and workouts together. Its response shape is slightly different: it lands on healthkitResponse.HKWorkoutTypeIdentifier rather than healthkitWorkouts, returns lowercase activityType values, and does not support included=. Use healthkit://workouts for any workouts-only read or any read that needs per-workout statistics.
Characteristics
Characteristics such as date of birth, biological sex, and blood type are static values that do not change over time. They return a plain string or raw integer and do not accept adays parameter, so they cannot be batched into the same call as quantity, category, or workout reads.
| Identifier | Returns |
|---|---|
HKCharacteristicTypeIdentifierDateOfBirth | ISO 8601 date string |
HKCharacteristicTypeIdentifierBiologicalSex | Raw integer from HKBiologicalSex |
HKCharacteristicTypeIdentifierBloodType | Raw integer from HKBloodType |
HKCharacteristicTypeIdentifierFitzpatrickSkinType | Raw integer from HKFitzpatrickSkinType |
Write
Usewritehealthkit:// to save a value back to HealthKit. This is useful when your app collects health data that should also live in Apple Health, for example a weight logging form, a manual step entry, or a calorie tracker. Writing adds a new sample to HealthKit without removing or replacing any existing records.
The URL format is writehealthkit://IdentifierString//Value. The unit is resolved automatically from the identifier.
Any writable
HKQuantityTypeIdentifier, passed as the URL host (e.g. HKQuantityTypeIdentifierBodyMass)Numeric value to write. The unit is determined automatically from the identifier, see the Identifier reference.
Write is one-directional. It adds samples to HealthKit but does not delete or modify existing ones. If you need to correct a previously written value, write a new sample, HealthKit stores the history and surfaces the most recent reading.
Observer
Use observers when you need your server to stay current with a user’s health data automatically, without requiring the user to open your app. Observers register a background listener on the device that watches one or more HealthKit types. When new data arrives, from Apple Watch, a connected sensor, or another app, Despia posts a webhook to your server with the latest records. This is fundamentally different from read. Read is a point-in-time fetch that your code initiates. An observer is a persistent subscription that fires on Despia’s side whenever HealthKit tells it something changed. The user does not need to be in the app for a webhook to fire. Common uses for observers include: tracking whether a user hit a daily step goal, alerting a coach when a client logs a workout, syncing sleep data nightly to a backend, and triggering push notifications based on health events.Registering an observer
Comma-separated list of HealthKit identifiers to observe
How often Despia delivers batched updates to your server:
immediate, hourly, daily, or weekly. Defaults to immediate. Use hourly or daily for high-volume types like steps to avoid unnecessary webhook traffic.Full URL of the endpoint that receives webhook POSTs. Append your own query parameters here to identify the user on your server.
Identifying users in webhooks
Webhooks include auserId field containing the Despia device ID. If you need to map webhook events to your own user records, append your user identifier as a query parameter on the server URL when registering the observer. Your server receives it as part of the request URL.
POST /webhook?user=user_abc123 and can route the event directly to the right user record without any device ID mapping.
Webhook payload
Despia sends aPOST with Content-Type: application/json each time an observed type updates. The data object contains one key per observed type, each holding an array of the most recent records (last 1 day).
Always
updateDespia device ID, consistent across all events from the same device. For your own user IDs, use a query parameter on the
server URL instead.ISO 8601 timestamp of when the webhook was sent
One key per observed type, each containing an array of records matching the read response shape for that type
Checking active observers
despia.observingHealthKit holds an array of currently active identifier strings. It is undefined before any observe or unobserve call has been made, and [] once all observers have been stopped. Use this to check whether an observer is already registered before calling observe again.
Stopping observers
Passall to stop every active observer, or a comma-separated list of identifiers to stop specific types. The response contains the updated list of remaining active observers.
Identifier reference
Despia supports all four HealthKit identifier categories. Pass any valid identifier string directly toreadhealthkit:// or writehealthkit://, or as part of included= on healthkit://workouts. Despia resolves the type and unit automatically.
Constructing identifiers
Every identifier follows a predictable pattern based on its category:| Type | Prefix | Example |
|---|---|---|
| Quantity | HKQuantityTypeIdentifier | HKQuantityTypeIdentifierStepCount |
| Category | HKCategoryTypeIdentifier | HKCategoryTypeIdentifierSleepAnalysis |
| Workout | HKWorkoutTypeIdentifier | HKWorkoutTypeIdentifier |
| Characteristic | HKCharacteristicTypeIdentifier | HKCharacteristicTypeIdentifierDateOfBirth |
StepCount under HKQuantityTypeIdentifier, the full identifier string is HKQuantityTypeIdentifierStepCount.
When using a quantity identifier inside included= on healthkit://workouts, append one of the aggregation suffixes (Average, Max, Min, Sum) to control how the value is computed across the workout window. Identifiers used as the URL host on readhealthkit:// never take a suffix.
Apple Documentation
HKQuantityTypeIdentifier
Steps, heart rate, distance, body mass, nutrition, and all other numeric types
HKCategoryTypeIdentifier
Sleep analysis, mindfulness, and other category-based types
HKWorkoutActivityType
All workout activity types returned in the
activityType fieldHKCharacteristicTypeIdentifier
Date of birth, biological sex, blood type, and skin type
Resources
NPM Package
despia-native