@flomentumsolutions/capacitor-health-extended
v0.8.2
Published
Capacitor plugin for Apple HealthKit and Google Health Connect Platform
Maintainers
Readme
@flomentumsolutions/capacitor-health-extended
Cross‑platform Capacitor plugin for reading data from Apple HealthKit and
Google Health Connect. The plugin requires Node.js 22+ and is compatible
with Capacitor 8. For iOS the plugin ships a Swift Package Manager
distribution (Capacitor 8 default), while the CocoaPods spec
FlomentumsolutionsCapacitorHealthExtended remains for legacy projects.
Thanks and attribution
Forked from capacitor-health and as such...
- Some parts, concepts and ideas are borrowed from cordova-plugin-health.
- Big thanks to @dariosalvi78 for the support.
Thanks @mley for the ground work. The goal of this fork is to extend functionality and datapoints and keep up with the ever-changing brand-new Android Health Connect Platform. I'm hoping to create platform parity for capacitor API-based health data access.
Requirements (Plugin & Consuming Apps)
- Node.js 22+ (Latest LTS version is recommended)
- Capacitor 8
- iOS 15+ (Xcode 26 + HealthKit + SwiftPM toolchain)
- Android 16+ (Android Studio Otter 2025.2.1 + Health Connect 1.2.0-alpha02 + Gradle 8.13.0 + Kotlin 2.2.20)
Features
- Check if health functionality is available on the device
- Request and verify health permissions
- Query aggregated data like steps or calories
- Retrieve workout sessions with optional route and heart rate data
- Create workout sessions (e.g., rock climbing) with totals, optional routes, and heart-rate samples (write APIs)
- Save manual metrics (weight, height, body fat %, resting heart rate) to HealthKit/Health Connect (write APIs)
- Fetch the latest samples for steps, distance (incl. cycling), calories (active/total/basal), heart‑rate, resting HR, HRV, respiratory rate, blood pressure, oxygen saturation, blood glucose, body temperature (basal + core), body fat, height, weight, flights climbed, sleep (incl. REM duration), and exercise time.
- Read profile characteristics on iOS: biological sex, blood type, date of birth, Fitzpatrick skin type, wheelchair use.
Supported data types (parity iOS + Android)
- Activity: steps, distance, distance‑cycling, exercise time (Apple Exercise Time), workouts (with routes/steps/calories), flights climbed
- Energy: active calories, total calories, basal calories
- Vitals: heart rate, resting heart rate, HRV, respiratory rate, blood pressure, oxygen saturation, blood glucose, body temperature, basal body temperature
- Body: weight, height, body fat
- Characteristics (iOS): biological sex, blood type, date of birth, Fitzpatrick skin type, wheelchair use
- Sessions: mindfulness, sleep, sleep REM (latest sample only)
Install
npm install @flomentumsolutions/capacitor-health-extended
npx cap syncSetup Consuming Apps
iOS
Capacitor 8 resolves iOS plugins via SwiftPM. Running npx cap sync ios will
add the FlomentumSolutionsCapacitorHealthExtended package (backed by
capacitor-swift-pm) to your Xcode project. If you are pinned to Capacitor 7,
you can keep using the CocoaPods spec FlomentumSolutionsCapacitorHealthExtended.
- Make sure your app id has the 'HealthKit' entitlement when this plugin is installed (see iOS dev center).
- Also, make sure your app and App Store description comply with the Apple review guidelines.
- There are two keys to be added to the info.plist file: NSHealthShareUsageDescription and NSHealthUpdateUsageDescription.
- Request WRITE_* permissions with
requestHealthPermissionsto enable saving workouts/energy/distance/routes/heart-rate samples and manual metrics (weight/height/body fat/resting HR) to HealthKit.
Android
The plugin namespace/package is com.flomentumsolutions.capacitorhealthextended.capacitor (hyphen removed from older com.flomentumsolutions.capacitor-health-extended references); use this when wiring activities, manifest entries, or ProGuard rules.
- Android Manifest in root tag right after opening manifest tag
<!-- Make Health Connect visible to detect installation -->
<queries>
<package android:name="com.google.android.apps.healthdata" />
</queries>
<!-- Declare permissions you’ll request -->
<!-- READ permissions -->
<uses-permission android:name="android.permission.health.READ_STEPS" />
<uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.READ_TOTAL_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.READ_DISTANCE" />
<uses-permission android:name="android.permission.health.READ_EXERCISE" />
<uses-permission android:name="android.permission.health.READ_EXERCISE_ROUTE" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE" />
<uses-permission android:name="android.permission.health.READ_WEIGHT" />
<uses-permission android:name="android.permission.health.READ_HEIGHT" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE_VARIABILITY" />
<uses-permission android:name="android.permission.health.READ_BLOOD_PRESSURE" />
<uses-permission android:name="android.permission.health.READ_MINDFULNESS" />
<uses-permission android:name="android.permission.health.READ_RESTING_HEART_RATE" />
<uses-permission android:name="android.permission.health.READ_RESPIRATORY_RATE" />
<uses-permission android:name="android.permission.health.READ_OXYGEN_SATURATION" />
<uses-permission android:name="android.permission.health.READ_BLOOD_GLUCOSE" />
<uses-permission android:name="android.permission.health.READ_BODY_TEMPERATURE" />
<uses-permission android:name="android.permission.health.READ_BASAL_BODY_TEMPERATURE" />
<uses-permission android:name="android.permission.health.READ_BODY_FAT" />
<uses-permission android:name="android.permission.health.READ_FLOORS_CLIMBED" />
<uses-permission android:name="android.permission.health.READ_BASAL_METABOLIC_RATE" />
<uses-permission android:name="android.permission.health.READ_SLEEP" />
<!-- WRITE permissions -->
<uses-permission android:name="android.permission.health.WRITE_EXERCISE" />
<uses-permission android:name="android.permission.health.WRITE_ACTIVE_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.WRITE_TOTAL_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.WRITE_DISTANCE" />
<uses-permission android:name="android.permission.health.WRITE_HEART_RATE" />
<uses-permission android:name="android.permission.health.WRITE_EXERCISE_ROUTE" />
<uses-permission android:name="android.permission.health.WRITE_WEIGHT" />
<uses-permission android:name="android.permission.health.WRITE_HEIGHT" />
<uses-permission android:name="android.permission.health.WRITE_BODY_FAT" />
<uses-permission android:name="android.permission.health.WRITE_RESTING_HEART_RATE" />Include the WRITE_* entries when you call saveWorkout to insert exercise sessions, energy, distance, routes, or heart rate samples, and add the metric write permissions when using saveMetrics.
- Android Manifest in application tag
<!-- Handle Health Connect rationale (Android 13-) -->
<!-- REPLACE com.my.app with your details -->
<activity
android:name="com.my.app.PermissionsRationaleActivity"
android:exported="true">
<intent-filter>
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE"/>
<category android:name="android.intent.category.HEALTH_PERMISSIONS"/>
</intent-filter>
</activity>
<!-- Handle Android 14+ alias -->
<!-- REPLACE com.my.app with your details -->
<activity-alias
android:name="ViewPermissionUsageActivity"
android:exported="true"
android:targetActivity="com.my.app.PermissionsRationaleActivity"
android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
<intent-filter>
<action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/>
<category android:name="android.intent.category.HEALTH_PERMISSIONS"/>
</intent-filter>
</activity-alias>- Android Manifest in application tag for secure WebView content
<!-- Configure secure WebView and allow HTTPS loading -->
<application
android:usesCleartextTraffic="false"
android:networkSecurityConfig="@xml/network_security_config">
...
</application>- Create
com.my.app.PermissionsRationaleActivity.ktwith (REPLACE com.my.app with your details):
<!-- REPLACE com.my.app with your details -->
package com.my.app
import android.os.Bundle
import android.util.Log
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.addCallback
import androidx.appcompat.app.AppCompatActivity
class PermissionsRationaleActivity : AppCompatActivity() {
private lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar?.apply {
title = "Privacy Policy"
setDisplayHomeAsUpEnabled(true)
}
webView = WebView(this).apply {
settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
useWideViewPort = true
loadWithOverviewMode = true
}
webChromeClient = WebChromeClient()
webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, request: android.webkit.WebResourceRequest) = false
override fun onReceivedError(
view: WebView,
request: android.webkit.WebResourceRequest,
error: android.webkit.WebResourceError
) {
Log.e("WebView", "Failed to load: ${error.description}")
}
override fun onPageFinished(view: WebView, url: String) {
Log.d("WebView", "Loaded: $url")
}
}
loadUrl("https://mywebsite.com/privacy-policy")
}
setContentView(webView)
// Device back button behavior
onBackPressedDispatcher.addCallback(this) {
finish()
}
}
// Toolbar Up button behavior
override fun onSupportNavigateUp(): Boolean {
finish()
return true
}
}- Create
res/xml/network_security_config.xmlwith:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>This setup ensures your WebView will load HTTPS content securely and complies with Android's default network security policy.
iOS read-permission UX hint
On iOS, checkHealthPermissions is optimistic for read sample permissions because HealthKit does not distinguish
denied access from empty data. If a query returns no results, prompt the user to verify Apple Health settings.
import { Health, type HealthPermission } from '@flomentumsolutions/capacitor-health-extended';
const NO_DATA_HINT =
'No data found. If you believe this is an error, please verify your settings in Apple Health.';
export async function queryWithHealthEmptyHint<T>(
permission: HealthPermission,
query: () => Promise<T>,
isEmpty: (result: T) => boolean,
showHint: (message: string) => void
): Promise<T | null> {
const { permissions } = await Health.checkHealthPermissions({ permissions: [permission] });
if (!permissions[permission]) {
return null;
}
const result = await query();
if (isEmpty(result)) {
showHint(NO_DATA_HINT);
}
return result;
}API
<docgen-index>
* [`isHealthAvailable()`](#ishealthavailable)
* [`checkHealthPermissions(...)`](#checkhealthpermissions)
* [`requestHealthPermissions(...)`](#requesthealthpermissions)
* [`openAppleHealthSettings()`](#openapplehealthsettings)
* [`openHealthConnectSettings()`](#openhealthconnectsettings)
* [`showHealthConnectInPlayStore()`](#showhealthconnectinplaystore)
* [`getCharacteristics(...)`](#getcharacteristics)
* [`queryAggregated(...)`](#queryaggregated)
* [`queryWorkouts(...)`](#queryworkouts)
* [`queryLatestSample(...)`](#querylatestsample)
* [`queryWeight()`](#queryweight)
* [`queryHeight()`](#queryheight)
* [`queryHeartRate()`](#queryheartrate)
* [`querySteps()`](#querysteps)
* [`saveWorkout(...)`](#saveworkout)
* [`saveMetrics(...)`](#savemetrics)
* [Interfaces](#interfaces)
* [Type Aliases](#type-aliases)
</docgen-index>isHealthAvailable()
isHealthAvailable() => Promise<{ available: boolean; }>Checks if health API is available. Android: If false is returned, the Google Health Connect app is probably not installed. See showHealthConnectInPlayStore()
Returns: Promise<{ available: boolean; }>
checkHealthPermissions(...)
checkHealthPermissions(permissions: PermissionsRequest) => Promise<PermissionResponse>Returns whether each permission is granted. Android: Uses Health Connect grant state. iOS: Write permissions are strict. Read permissions for sample types are optimistic because HealthKit does not distinguish denied vs no data; this returns false only when the read permission is not determined. For characteristics, this probes access and returns false when denied. UX tip: If this returns true but a query yields no results, show a hint to check Apple Health settings.
| Param | Type | Description |
| ----------------- | ----------------------------------------------------------------- | -------------------- |
| permissions | PermissionsRequest | permissions to query |
Returns: Promise<PermissionResponse>
requestHealthPermissions(...)
requestHealthPermissions(permissions: PermissionsRequest) => Promise<PermissionResponse>Requests the permissions from the user.
Android: Apps can ask only a few times for permissions, after that the user has to grant them manually in the Health Connect app. See openHealthConnectSettings()
iOS: If the permissions are already granted or denied, this method will just return without asking the user. In iOS we can't really detect if a user granted or denied a permission. The return value reflects the assumption that all permissions were granted.
| Param | Type | Description |
| ----------------- | ----------------------------------------------------------------- | ---------------------- |
| permissions | PermissionsRequest | permissions to request |
Returns: Promise<PermissionResponse>
openAppleHealthSettings()
openAppleHealthSettings() => Promise<void>Opens the apps settings, which is kind of wrong, because health permissions are configured under: Settings > Apps > (Apple) Health > Access and Devices > [app-name] But we can't go there directly.
openHealthConnectSettings()
openHealthConnectSettings() => Promise<void>Opens the Google Health Connect app iOS: Aliases openAppleHealthSettings().
showHealthConnectInPlayStore()
showHealthConnectInPlayStore() => Promise<void>Opens the Google Health Connect app in PlayStore iOS: Resolves without action.
getCharacteristics(...)
getCharacteristics(request?: CharacteristicsRequest | undefined) => Promise<CharacteristicsResponse>iOS only: Reads user characteristics such as biological sex, blood type, date of birth, Fitzpatrick skin type, and wheelchair use.
Values are null when unavailable or permission was not granted. Android does not expose these characteristics; it returns platformSupported: false and a platformMessage for UI hints without emitting null values.
Passing fields lets you request only specific characteristics (e.g., date of birth) to keep permissions scoped narrowly. Defaults to all characteristics when omitted.
| Param | Type |
| ------------- | ------------------------------------------------------------------------- |
| request | CharacteristicsRequest |
Returns: Promise<CharacteristicsResponse>
queryAggregated(...)
queryAggregated(request: QueryAggregatedRequest) => Promise<QueryAggregatedResponse>Query aggregated data
- Blood-pressure aggregates return the systolic average in
valueplussystolic,diastolic, andunit. total-caloriesis derived as active + basal energy on both iOS and Android for latest samples, aggregated queries, and workouts. We fall back to the platform's total‑calories metric (or active calories) when basal data isn't available or permission is missing. Request bothREAD_ACTIVE_CALORIESandREAD_BASAL_CALORIESfor full totals.- Weight/height aggregation returns the latest sample per day (no averaging).
- Android aggregation currently supports daily buckets; unsupported buckets will be rejected.
- Android
distance-cyclingaggregates distance recorded during biking exercise sessions (requires distance + workouts permissions). - Daily
bucket: "day"queries use calendar-day boundaries in the device time zone (start-of-day through the next start-of-day) instead of a trailing 24-hour window. For “today,” sendstartDateat today’s start-of-day andendDateat now or tomorrow’s start-of-day.
| Param | Type |
| ------------- | ------------------------------------------------------------------------- |
| request | QueryAggregatedRequest |
Returns: Promise<QueryAggregatedResponse>
queryWorkouts(...)
queryWorkouts(request: QueryWorkoutRequest) => Promise<QueryWorkoutResponse>Query workouts
| Param | Type |
| ------------- | ------------------------------------------------------------------- |
| request | QueryWorkoutRequest |
Returns: Promise<QueryWorkoutResponse>
queryLatestSample(...)
queryLatestSample(request: { dataType: LatestDataType; }) => Promise<QueryLatestSampleResponse>Query latest sample for a specific data type
- Latest sleep sample returns the most recent complete sleep session (asleep states only) from the last ~36 hours; if a longer overnight session exists, shorter naps are ignored.
sleep-remreturns REM duration (minutes) for the latest sleep session; requires iOS 16+ sleep stages and Health Connect REM data on Android.
| Param | Type |
| ------------- | ------------------------------------------------------------------------ |
| request | { dataType: LatestDataType; } |
Returns: Promise<QueryLatestSampleResponse>
queryWeight()
queryWeight() => Promise<QueryLatestSampleResponse>Query latest weight sample Convenience wrapper around queryLatestSample({ dataType: 'weight' }).
Returns: Promise<QueryLatestSampleResponse>
queryHeight()
queryHeight() => Promise<QueryLatestSampleResponse>Query latest height sample Convenience wrapper around queryLatestSample({ dataType: 'height' }).
Returns: Promise<QueryLatestSampleResponse>
queryHeartRate()
queryHeartRate() => Promise<QueryLatestSampleResponse>Query latest heart rate sample Convenience wrapper around queryLatestSample({ dataType: 'heart-rate' }).
Returns: Promise<QueryLatestSampleResponse>
querySteps()
querySteps() => Promise<QueryLatestSampleResponse>Query latest steps sample Convenience wrapper around queryLatestSample({ dataType: 'steps' }).
Returns: Promise<QueryLatestSampleResponse>
saveWorkout(...)
saveWorkout(request: SaveWorkoutRequest) => Promise<SaveWorkoutResponse>Create a workout session with optional totals and route/heart-rate samples.
- iOS stores an
HKWorkout(activityType mapped fromactivityType) with total energy/distance and optional metadata/route/heart-rate samples. - Android stores an
ExerciseSessionRecordplusActiveCaloriesBurnedRecord,DistanceRecord, andHeartRateRecordwhen provided. Routes are attached viaExerciseRoute. - Requires matching WRITE_* permissions for the values you include (e.g., WRITE_WORKOUTS + WRITE_ACTIVE_CALORIES + WRITE_DISTANCE + WRITE_HEART_RATE + WRITE_ROUTE).
| Param | Type |
| ------------- | ----------------------------------------------------------------- |
| request | SaveWorkoutRequest |
Returns: Promise<SaveWorkoutResponse>
saveMetrics(...)
saveMetrics(request: SaveMetricsRequest) => Promise<SaveMetricsResponse>Save user-provided body metrics to the health platform. iOS: Requests read access for the same metric types when writing to preserve read permissions.
| Param | Type |
| ------------- | ----------------------------------------------------------------- |
| request | SaveMetricsRequest |
Returns: Promise<SaveMetricsResponse>
Interfaces
PermissionResponse
| Prop | Type |
| ----------------- | ---------------------------------------------------------------------------------------------------------- |
| permissions | Record<HealthPermission, boolean> |
PermissionsRequest
| Prop | Type |
| ----------------- | ------------------------------- |
| permissions | HealthPermission[] |
CharacteristicsResponse
| Prop | Type | Description |
| ------------------------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| biologicalSex | HealthBiologicalSex | null | |
| bloodType | HealthBloodType | null | |
| dateOfBirth | string | null | |
| fitzpatrickSkinType | HealthFitzpatrickSkinType | null | |
| wheelchairUse | HealthWheelchairUse | null | |
| platformSupported | boolean | Indicates whether the platform exposes these characteristics via the plugin (true on iOS, false on Android). |
| platformMessage | string | Optional platform-specific message; on Android we return a user-facing note explaining that values remain empty unless synced from iOS. |
CharacteristicsRequest
| Prop | Type | Description |
| ------------ | ---------------------------------- | ----------------------------------------------------------------------- |
| fields | CharacteristicField[] | Characteristics to query. Defaults to all characteristics when omitted. |
QueryAggregatedResponse
| Prop | Type |
| -------------------- | ------------------------------- |
| aggregatedData | AggregatedSample[] |
AggregatedSample
| Prop | Type |
| --------------- | ------------------- |
| startDate | string |
| endDate | string |
| value | number |
| systolic | number |
| diastolic | number |
| unit | string |
QueryAggregatedRequest
| Prop | Type |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| startDate | string |
| endDate | string |
| dataType | 'steps' | 'active-calories' | 'total-calories' | 'basal-calories' | 'distance' | 'weight' | 'height' | 'heart-rate' | 'resting-heart-rate' | 'respiratory-rate' | 'oxygen-saturation' | 'blood-glucose' | 'body-temperature' | 'basal-body-temperature' | 'body-fat' | 'flights-climbed' | 'exercise-time' | 'distance-cycling' | 'mindfulness' | 'sleep' | 'hrv' | 'blood-pressure' |
| bucket | string |
QueryWorkoutResponse
| Prop | Type |
| -------------- | ---------------------- |
| workouts | Workout[] |
Workout
| Prop | Type |
| -------------------- | ------------------------------ |
| startDate | string |
| endDate | string |
| workoutType | string |
| sourceName | string |
| id | string |
| duration | number |
| distance | number |
| steps | number |
| calories | number |
| sourceBundleId | string |
| route | RouteSample[] |
| heartRate | HeartRateSample[] |
RouteSample
| Prop | Type |
| --------------- | ------------------- |
| timestamp | string |
| lat | number |
| lng | number |
| alt | number |
HeartRateSample
| Prop | Type |
| --------------- | ------------------- |
| timestamp | string |
| bpm | number |
QueryWorkoutRequest
| Prop | Type |
| ---------------------- | -------------------- |
| startDate | string |
| endDate | string |
| includeHeartRate | boolean |
| includeRoute | boolean |
| includeSteps | boolean |
QueryLatestSampleResponse
| Prop | Type |
| ------------------ | ---------------------------------------------------------------- |
| value | number |
| systolic | number |
| diastolic | number |
| timestamp | number |
| endTimestamp | number |
| unit | string |
| metadata | Record<string, unknown> |
SaveWorkoutResponse
| Prop | Type |
| ------------- | -------------------- |
| success | boolean |
| id | string |
SaveWorkoutRequest
| Prop | Type |
| ---------------------- | ------------------------------------------------------------------- |
| activityType | WorkoutActivityType |
| startDate | string |
| endDate | string |
| calories | number |
| distance | number |
| metadata | Record<string, any> |
| route | RouteSample[] |
| heartRateSamples | HeartRateSample[] |
SaveMetricsResponse
| Prop | Type |
| -------------- | -------------------- |
| success | boolean |
| inserted | number |
SaveMetricsRequest
| Prop | Type |
| ---------------------- | ------------------- |
| weightKg | number |
| heightCm | number |
| bodyFatPercent | number |
| restingHeartRate | number |
Type Aliases
Record
Construct a type with a set of properties K of type T
{ [P in K]: T; }
HealthPermission
'READ_STEPS' | 'READ_WORKOUTS' | 'WRITE_WORKOUTS' | 'READ_ACTIVE_CALORIES' | 'WRITE_ACTIVE_CALORIES' | 'READ_TOTAL_CALORIES' | 'WRITE_TOTAL_CALORIES' | 'READ_DISTANCE' | 'WRITE_DISTANCE' | 'READ_WEIGHT' | 'WRITE_WEIGHT' | 'READ_HEIGHT' | 'WRITE_HEIGHT' | 'READ_HEART_RATE' | 'WRITE_HEART_RATE' | 'READ_RESTING_HEART_RATE' | 'WRITE_RESTING_HEART_RATE' | 'READ_ROUTE' | 'WRITE_ROUTE' | 'READ_MINDFULNESS' | 'READ_HRV' | 'READ_BLOOD_PRESSURE' | 'READ_BASAL_CALORIES' | 'READ_RESPIRATORY_RATE' | 'READ_OXYGEN_SATURATION' | 'READ_BLOOD_GLUCOSE' | 'READ_BODY_TEMPERATURE' | 'READ_BASAL_BODY_TEMPERATURE' | 'READ_BODY_FAT' | 'WRITE_BODY_FAT' | 'READ_FLOORS_CLIMBED' | 'READ_SLEEP' | 'READ_EXERCISE_TIME' | 'READ_BIOLOGICAL_SEX' | 'READ_BLOOD_TYPE' | 'READ_DATE_OF_BIRTH' | 'READ_FITZPATRICK_SKIN_TYPE' | 'READ_WHEELCHAIR_USE'
HealthBiologicalSex
'female' | 'male' | 'other' | 'not_set' | 'unknown'
HealthBloodType
'a-positive' | 'a-negative' | 'b-positive' | 'b-negative' | 'ab-positive' | 'ab-negative' | 'o-positive' | 'o-negative' | 'not_set' | 'unknown'
HealthFitzpatrickSkinType
'type1' | 'type2' | 'type3' | 'type4' | 'type5' | 'type6' | 'not_set' | 'unknown'
HealthWheelchairUse
'wheelchair_user' | 'not_wheelchair_user' | 'not_set' | 'unknown'
CharacteristicField
'biologicalSex' | 'bloodType' | 'dateOfBirth' | 'fitzpatrickSkinType' | 'wheelchairUse'
LatestDataType
'steps' | 'active-calories' | 'total-calories' | 'basal-calories' | 'distance' | 'weight' | 'height' | 'heart-rate' | 'resting-heart-rate' | 'respiratory-rate' | 'oxygen-saturation' | 'blood-glucose' | 'body-temperature' | 'basal-body-temperature' | 'body-fat' | 'flights-climbed' | 'exercise-time' | 'distance-cycling' | 'mindfulness' | 'sleep' | 'sleep-rem' | 'hrv' | 'blood-pressure'
WorkoutActivityType
'rock-climbing' | 'climbing' | 'hiking' | 'running' | 'walking' | 'cycling' | 'biking' | 'strength-training' | 'yoga' | 'other'
