{
 "$comment": "Generated by scripts/build-unified-schema.mjs. Mappings for https://aifitnessapi.com/schema/v1/unified-health-data.schema.json. CC BY 4.0 (attribution: aifitnessapi.com); vendor sentences quoted as evidence remain their publishers'.",
 "version": "1.0.0",
 "schema": "https://aifitnessapi.com/schema/v1/unified-health-data.schema.json",
 "readOn": "2026-11-05",
 "platforms": [
  "healthkit",
  "health-connect",
  "google-health-api",
  "wear-os"
 ],
 "sources": {
  "healthkit": {
   "name": "Apple HealthKit",
   "dataset": "src/data/healthkitIdentifiers.ts",
   "readOn": "2026-10-02"
  },
  "health-connect": {
   "name": "Android Health Connect",
   "dataset": "src/data/healthConnectRecords.ts",
   "readOn": "2026-10-03"
  },
  "google-health-api": {
   "name": "Google Health API",
   "dataset": "src/data/googleHealthApi.ts",
   "readOn": "2026-10-31"
  },
  "wear-os": {
   "name": "Wear OS Health Services",
   "dataset": "src/data/healthServicesDataTypes.ts",
   "readOn": "2026-10-04"
  },
  "workouts": {
   "name": "Workout activity-type crosswalk",
   "dataset": "src/data/workoutTypes.ts",
   "readOn": "2026-10-18"
  }
 },
 "pageReads": [
  {
   "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateRecord.Sample",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord.Stage",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkcategoryvaluesleepanalysis.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkcategoryvaluesleepanalysis/asleep.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkunit/percent().json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hksample/startdate.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hksample/enddate.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkquantitysample/quantity.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkcategorysample/value.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkworkout/workoutactivitytype.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkworkout/totalenergyburned.json",
   "readOn": "2026-11-05"
  },
  {
   "url": "https://developer.apple.com/tutorials/data/documentation/healthkit/hkworkout/totaldistance.json",
   "readOn": "2026-11-05"
  }
 ],
 "stages": [
  "awake",
  "awakeInBed",
  "outOfBed",
  "inBed",
  "asleep",
  "light",
  "deep",
  "rem",
  "restless",
  "unknown"
 ],
 "records": [
  {
   "id": "heartRate",
   "title": "Heart rate sample",
   "shape": "sample",
   "description": "One heart-rate reading at one instant, in beats per minute.",
   "valueFields": [
    {
     "name": "beatsPerMinute",
     "type": "number",
     "unit": "count/min",
     "minimum": 0,
     "required": true,
     "description": "Heart beats per minute."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKQuantityTypeIdentifier.heartRate",
      "field": null,
      "platformType": "HKQuantityTypeIdentifierHeartRate",
      "evidence": {
       "quote": "A quantity sample type that measures the user’s heart rate.",
       "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/heartrate"
      },
      "href": "/healthkit-identifiers/heart-rate"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": "a sample at one moment has startDate equal to endDate",
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "beatsPerMinute": {
       "status": "mapped",
       "conversion": "read with doubleValue(for:) in count/min",
       "factor": null,
       "type": "HKQuantityTypeIdentifier.heartRate",
       "field": "quantity",
       "platformType": "HKQuantity (count/time unit family)",
       "evidence": {
        "quote": "These samples use count/time units (described in ) and measure discrete values (described in ).",
        "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/heartrate"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": "one record holds a series: each element of samples becomes one unified sample",
      "factor": null,
      "type": "HeartRateRecord",
      "field": null,
      "platformType": "Series",
      "evidence": {
       "quote": "Captures the user's heart rate. Each record represents a series of measurements.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateRecord"
      },
      "href": "/health-connect/heart-rate-record"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HeartRateRecord.Sample",
       "field": "samples[].time",
       "platformType": "Instant",
       "evidence": {
        "quote": "The point in time when the measurement was taken.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateRecord.Sample"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "the record's startZoneOffset, applied to every sample (a Sample has no offset of its own)",
       "factor": null,
       "type": "HeartRateRecord",
       "field": "startZoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at startTime, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateRecord"
       }
      },
      "beatsPerMinute": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HeartRateRecord.Sample",
       "field": "samples[].beatsPerMinute",
       "platformType": "@IntRange (from = 1, to = 300) Long",
       "evidence": {
        "quote": "Heart beats per minute. Validation range: 1-300.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateRecord.Sample"
       }
      }
     },
     "container": {
      "field": "samples",
      "platformType": "List<HeartRateRecord.Sample>"
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "heart-rate",
      "field": "heartRate",
      "platformType": "Sample",
      "evidence": {
       "quote": "A heart rate measurement.",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartrate"
      },
      "href": "/google-health-api/heart-rate"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "heart-rate",
       "field": "heartRate.sampleTime.physicalTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The time of the observation.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartrate"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "heart-rate",
       "field": "heartRate.sampleTime.utcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time during the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartrate"
       }
      },
      "beatsPerMinute": {
       "status": "mapped",
       "conversion": "int64 arrives as a JSON string: parse to a number",
       "factor": null,
       "type": "heart-rate",
       "field": "heartRate.beatsPerMinute",
       "platformType": "string/int64",
       "evidence": {
        "quote": "Required. The heart rate value in beats per minute. Must be in the range `[1, 300]`.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartrate"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "DataType.HEART_RATE_BPM",
      "field": null,
      "platformType": "DeltaDataType<Double, SampleDataPoint<Double>>",
      "evidence": {
       "quote": "Current heart rate, in beats per minute.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/services/client/data/DataType#HEART_RATE_BPM()"
      },
      "href": "/wear-os-data-types/heart-rate-bpm"
     },
     "fields": {
      "time": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "beatsPerMinute": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "DataType.HEART_RATE_BPM",
       "field": "SampleDataPoint.value",
       "platformType": "Double",
       "evidence": {
        "quote": "Current heart rate, in beats per minute.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/services/client/data/DataType#HEART_RATE_BPM()"
       }
      }
     }
    }
   },
   "notes": []
  },
  {
   "id": "steps",
   "title": "Step count over an interval",
   "shape": "interval",
   "description": "The number of steps taken between two instants.",
   "valueFields": [
    {
     "name": "count",
     "type": "integer",
     "unit": "count",
     "minimum": 0,
     "required": true,
     "description": "Steps in the interval."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKQuantityTypeIdentifier.stepCount",
      "field": null,
      "platformType": "HKQuantityTypeIdentifierStepCount",
      "evidence": {
       "quote": "A quantity sample type that measures the number of steps the user has taken.",
       "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/stepcount"
      },
      "href": "/healthkit-identifiers/step-count"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HKSample",
       "field": "endDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s end date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/enddate"
       }
      },
      "startUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "endUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "count": {
       "status": "mapped",
       "conversion": "read with doubleValue(for:) in count",
       "factor": null,
       "type": "HKQuantityTypeIdentifier.stepCount",
       "field": "quantity",
       "platformType": "HKQuantity (count unit family)",
       "evidence": {
        "quote": "These samples use count units (described in ) and measure cumulative values (described in ).",
        "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/stepcount"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "StepsRecord",
      "field": null,
      "platformType": "Interval",
      "evidence": {
       "quote": "Captures the number of steps taken since the last reading. Each step is only reported once so records shouldn't have overlapping time. The start time of each record should represent the start of the interval in which steps were taken.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/StepsRecord"
      },
      "href": "/health-connect/steps-record"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "StepsRecord",
       "field": "startTime",
       "platformType": "Instant",
       "evidence": {
        "quote": "Start time of the record.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/StepsRecord"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "StepsRecord",
       "field": "endTime",
       "platformType": "Instant",
       "evidence": {
        "quote": "End time of the record.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/StepsRecord"
       }
      },
      "startUtcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "StepsRecord",
       "field": "startZoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at startTime, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/StepsRecord"
       }
      },
      "endUtcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "StepsRecord",
       "field": "endZoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at endTime, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/StepsRecord"
       }
      },
      "count": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "StepsRecord",
       "field": "count",
       "platformType": "Long",
       "evidence": {
        "quote": "Count. Required field. Valid range: 1-1000000.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/StepsRecord"
       }
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "steps",
      "field": "steps",
      "platformType": "Interval",
      "evidence": {
       "quote": "Step count over the time interval.",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#steps"
      },
      "href": "/google-health-api/steps"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "steps",
       "field": "steps.interval.startTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. Observed interval start time.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#steps"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "steps",
       "field": "steps.interval.endTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. Observed interval end time.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#steps"
       }
      },
      "startUtcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "steps",
       "field": "steps.interval.startUtcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time at the start of the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#steps"
       }
      },
      "endUtcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "steps",
       "field": "steps.interval.endUtcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time at the end of the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#steps"
       }
      },
      "count": {
       "status": "mapped",
       "conversion": "int64 arrives as a JSON string: parse to an integer",
       "factor": null,
       "type": "steps",
       "field": "steps.count",
       "platformType": "string/int64",
       "evidence": {
        "quote": "Required. Number of steps in the recorded interval. Must be in the range `[0, 1000000]`.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#steps"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "DataType.STEPS",
      "field": null,
      "platformType": "DeltaDataType<Long, IntervalDataPoint<Long>>",
      "evidence": {
       "quote": "Number of steps taken since the last update.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/services/client/data/DataType#STEPS()"
      },
      "href": "/wear-os-data-types/steps"
     },
     "fields": {
      "startTime": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "endTime": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "startUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "endUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "count": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "DataType.STEPS",
       "field": "IntervalDataPoint.value",
       "platformType": "Long",
       "evidence": {
        "quote": "Number of steps taken since the last update.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/services/client/data/DataType#STEPS()"
       }
      }
     }
    }
   },
   "notes": [
    "Google prints different lower bounds: Health Connect's count is “Valid range: 1-1000000.”, the Google Health API's “Required. Number of steps in the recorded interval. Must be in the range `[0, 1000000]`.” A zero-step interval converts to the unified shape, but cannot be written back to Health Connect."
   ]
  },
  {
   "id": "sleepSession",
   "title": "Sleep session with stages",
   "shape": "session",
   "description": "One sleep period and the stages inside it, each stage an interval with one value from the unified stage vocabulary.",
   "valueFields": [
    {
     "name": "stages",
     "type": "array",
     "required": true,
     "description": "Non-overlapping stage intervals inside the session; empty when the source has none.",
     "items": {
      "startTime": {
       "type": "string",
       "format": "date-time"
      },
      "endTime": {
       "type": "string",
       "format": "date-time"
      },
      "stage": {
       "type": "string",
       "enum": [
        "awake",
        "awakeInBed",
        "outOfBed",
        "inBed",
        "asleep",
        "light",
        "deep",
        "rem",
        "restless",
        "unknown"
       ]
      }
     }
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": "HealthKit writes one category sample per stage: the converter groups the samples you paste into one session, from the earliest start to the latest end",
      "factor": null,
      "type": "HKCategoryTypeIdentifier.sleepAnalysis",
      "field": null,
      "platformType": "HKCategoryTypeIdentifierSleepAnalysis",
      "evidence": {
       "quote": "A category sample type for sleep analysis information.",
       "url": "https://developer.apple.com/documentation/healthkit/hkcategorytypeidentifier/sleepanalysis"
      },
      "href": "/healthkit-identifiers/sleep-analysis"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HKSample",
       "field": "endDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s end date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/enddate"
       }
      },
      "startUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "endUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "stages": {
       "status": "mapped",
       "conversion": "each sample's startDate, endDate and value become one stage",
       "factor": null,
       "type": "HKCategorySample",
       "field": "value (HKCategoryValueSleepAnalysis)",
       "platformType": "Int",
       "evidence": {
        "quote": "The category value for this sample.",
        "url": "https://developer.apple.com/documentation/healthkit/hkcategorysample/value"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "SleepSessionRecord",
      "field": null,
      "platformType": "Interval",
      "evidence": {
       "quote": "Captures the user's sleep length and its stages. Each record represents a time interval for a full sleep session.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord"
      },
      "href": "/health-connect/sleep-session-record"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "SleepSessionRecord",
       "field": "startTime",
       "platformType": "Instant",
       "evidence": {
        "quote": "Start time of the record.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "SleepSessionRecord",
       "field": "endTime",
       "platformType": "Instant",
       "evidence": {
        "quote": "End time of the record.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord"
       }
      },
      "startUtcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "SleepSessionRecord",
       "field": "startZoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at startTime, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord"
       }
      },
      "endUtcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "SleepSessionRecord",
       "field": "endZoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at endTime, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord"
       }
      },
      "stages": {
       "status": "mapped",
       "conversion": "stage Int → the unified vocabulary (table below)",
       "factor": null,
       "type": "SleepSessionRecord.Stage",
       "field": "stages[].startTime, stages[].endTime, stages[].stage",
       "platformType": "List<SleepSessionRecord.Stage>; stage: Int",
       "evidence": {
        "quote": "startTime: Instant, endTime: Instant, stage: Int",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord.Stage"
       }
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "sleep",
      "field": "sleep",
      "platformType": "Session",
      "evidence": {
       "quote": "A sleep session possibly including stages.",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep"
      },
      "href": "/google-health-api/sleep"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "sleep",
       "field": "sleep.interval.startTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The start time of the observed session.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "sleep",
       "field": "sleep.interval.endTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The end time of the observed session.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep"
       }
      },
      "startUtcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "sleep",
       "field": "sleep.interval.startUtcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time at the start of the session relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep"
       }
      },
      "endUtcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "sleep",
       "field": "sleep.interval.endUtcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time at the end of the session relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep"
       }
      },
      "stages": {
       "status": "mapped",
       "conversion": "type string → the unified vocabulary (table below); outOfBedSegments are not read",
       "factor": null,
       "type": "sleep",
       "field": "sleep.stages[] (startTime, endTime, type)",
       "platformType": "array<SleepStage>",
       "evidence": {
        "quote": "Optional. List of non-overlapping contiguous sleep stage segments that cover the sleep period.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "not-mapped",
      "type": null,
      "field": null,
      "platformType": null,
      "conversion": null,
      "factor": null,
      "evidence": null,
      "reason": "None of the 65 Health Services DataType constants (Jetpack reference, read 2026-10-04) has a name or description mentioning “sleep”: no sleep type to map."
     },
     "fields": {
      "startTime": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "endTime": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "startUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "endUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "stages": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "No sleep type in Health Services."
      }
     }
    }
   },
   "notes": [
    "Stage vocabularies differ: Health Connect separates awake from awake-in-bed and out-of-bed, the Google Health API adds restless, and Apple's core stage is “light or intermediate”. The unified vocabulary keeps every distinction any source makes, so a conversion never merges two source values — except Apple's core into light, stated in the table."
   ]
  },
  {
   "id": "workout",
   "title": "Workout session",
   "shape": "session",
   "description": "One exercise session: when it ran, what it was, and the totals where the source states them.",
   "valueFields": [
    {
     "name": "activityType",
     "type": [
      "string",
      "null"
     ],
     "required": true,
     "description": "The activity as this site's workout crosswalk key (Two constants share a crosswalk row only when their names are identical after removing a leading EXERCISE_TYPE_ (Health Connect's prefix, which the Google Health API also uses on EXERCISE_TYPE_UNSPECIFIED), lowercasing, and removing every character that is not a letter or a digit). null when the source value is not in the crosswalk data."
    },
    {
     "name": "nativeActivityType",
     "type": "string",
     "required": true,
     "description": "The source's own activity value, unchanged (an Objective-C constant, an Int as text, or an enum string)."
    },
    {
     "name": "energyKcal",
     "type": [
      "number",
      "null"
     ],
     "unit": "kcal",
     "minimum": 0,
     "required": false,
     "description": "Total energy for the session in kilocalories; null when the source carries none."
    },
    {
     "name": "distanceMeters",
     "type": [
      "number",
      "null"
     ],
     "unit": "m",
     "minimum": 0,
     "required": false,
     "description": "Total distance in meters; null when the source carries none."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKWorkout",
      "field": null,
      "platformType": "HKWorkout",
      "evidence": {
       "quote": "The type of activity performed during the workout.",
       "url": "https://developer.apple.com/documentation/healthkit/hkworkout/workoutactivitytype"
      },
      "href": "/workout-types"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HKSample",
       "field": "endDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s end date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/enddate"
       }
      },
      "startUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "endUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "activityType": {
       "status": "mapped",
       "conversion": "Objective-C constant → crosswalk key",
       "factor": null,
       "type": "HKWorkout",
       "field": "workoutActivityType",
       "platformType": "HKWorkoutActivityType",
       "evidence": {
        "quote": "The type of activity performed during the workout.",
        "url": "https://developer.apple.com/documentation/healthkit/hkworkout/workoutactivitytype"
       }
      },
      "nativeActivityType": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HKWorkout",
       "field": "workoutActivityType",
       "platformType": "HKWorkoutActivityType",
       "evidence": {
        "quote": "The type of activity performed during the workout.",
        "url": "https://developer.apple.com/documentation/healthkit/hkworkout/workoutactivitytype"
       }
      },
      "energyKcal": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HKWorkout.totalEnergyBurned is deprecated as of iOS 18.0 (Apple: “Use statisticsForType: passing the HKQuantityType for HKQuantityTypeIdentifierActiveEnergyBurned”); per-type statistics are not in this site's datasets, so the converter does not read energy from HealthKit."
      },
      "distanceMeters": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HKWorkout.totalDistance is deprecated as of iOS 27.3 (Apple: “Use statisticsForType: passing the HKQuantityType for the desired distance type”); not read."
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "ExerciseSessionRecord",
      "field": null,
      "platformType": "Interval",
      "evidence": {
       "quote": "Captures any exercise a user does. This can be common fitness exercise like running or different sports.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/ExerciseSessionRecord"
      },
      "href": "/health-connect/exercise-session-record"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "ExerciseSessionRecord",
       "field": "startTime",
       "platformType": "Instant",
       "evidence": {
        "quote": "Start time of the record.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/ExerciseSessionRecord"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "ExerciseSessionRecord",
       "field": "endTime",
       "platformType": "Instant",
       "evidence": {
        "quote": "End time of the record.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/ExerciseSessionRecord"
       }
      },
      "startUtcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "ExerciseSessionRecord",
       "field": "startZoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at startTime, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/ExerciseSessionRecord"
       }
      },
      "endUtcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "ExerciseSessionRecord",
       "field": "endZoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at endTime, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/ExerciseSessionRecord"
       }
      },
      "activityType": {
       "status": "mapped",
       "conversion": "Int value → EXERCISE_TYPE_ constant → crosswalk key",
       "factor": null,
       "type": "ExerciseSessionRecord",
       "field": "exerciseType",
       "platformType": "Int",
       "evidence": {
        "quote": "Type of exercise (e.g. walking, swimming). Required field.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/ExerciseSessionRecord"
       }
      },
      "nativeActivityType": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "ExerciseSessionRecord",
       "field": "exerciseType",
       "platformType": "Int",
       "evidence": {
        "quote": "Type of exercise (e.g. walking, swimming). Required field.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/ExerciseSessionRecord"
       }
      },
      "energyKcal": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "ExerciseSessionRecord has no energy property: Health Connect stores it as separate calories records over the same interval."
      },
      "distanceMeters": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "ExerciseSessionRecord has no distance property: Health Connect stores it as separate DistanceRecord records."
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "exercise",
      "field": "exercise",
      "platformType": "Session",
      "evidence": {
       "quote": "An exercise that stores information about a physical activity.",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
      },
      "href": "/google-health-api/exercise"
     },
     "fields": {
      "startTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "exercise",
       "field": "exercise.interval.startTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The start time of the observed session.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      },
      "endTime": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "exercise",
       "field": "exercise.interval.endTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The end time of the observed session.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      },
      "startUtcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "exercise",
       "field": "exercise.interval.startUtcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time at the start of the session relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      },
      "endUtcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "exercise",
       "field": "exercise.interval.endUtcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time at the end of the session relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      },
      "activityType": {
       "status": "mapped",
       "conversion": "enum string → crosswalk key",
       "factor": null,
       "type": "exercise",
       "field": "exercise.exerciseType",
       "platformType": "string",
       "evidence": {
        "quote": "Required. The type of activity performed during an exercise.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      },
      "nativeActivityType": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "exercise",
       "field": "exercise.exerciseType",
       "platformType": "string",
       "evidence": {
        "quote": "Required. The type of activity performed during an exercise.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      },
      "energyKcal": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "exercise",
       "field": "exercise.metricsSummary.caloriesKcal",
       "platformType": "number/double",
       "evidence": {
        "quote": "Optional. Total calories burned by the user during the exercise.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      },
      "distanceMeters": {
       "status": "mapped",
       "conversion": "÷ 1,000 (the field name states millimeters)",
       "factor": 0.001,
       "type": "exercise",
       "field": "exercise.metricsSummary.distanceMillimeters",
       "platformType": "number/double",
       "evidence": {
        "quote": "Optional. Total distance covered by the user during the exercise.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#exercise"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "ExerciseType",
      "field": null,
      "platformType": "ExerciseType",
      "evidence": {
       "quote": "ExerciseType objects, each with an int id and a name, on the Jetpack ExerciseType class",
       "url": "https://developer.android.com/reference/androidx/health/services/client/data/ExerciseType"
      },
      "href": "/workout-types"
     },
     "fields": {
      "startTime": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "endTime": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "startUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "endUtcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "activityType": {
       "status": "mapped",
       "conversion": "constant name → crosswalk key",
       "factor": null,
       "type": "ExerciseType",
       "field": "name",
       "platformType": "String",
       "evidence": {
        "quote": "85 ExerciseType constants read from the androidx source on 2026-10-18",
        "url": "https://developer.android.com/reference/androidx/health/services/client/data/ExerciseType"
       }
      },
      "nativeActivityType": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "ExerciseType",
       "field": "name",
       "platformType": "String",
       "evidence": null
      },
      "energyKcal": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Exercise totals in Health Services arrive as DataType values during the exercise (CALORIES_TOTAL and similar), not on a session object; not mapped here."
      },
      "distanceMeters": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "As for energy: DISTANCE_TOTAL-style values arrive during the exercise; not mapped here."
      }
     }
    }
   },
   "notes": [
    "activityType uses the workout crosswalk's key (87 keys are shared by two or more platforms). A key shared by name is not a claim that two platforms mean the same activity; /workout-types shows each platform's own description."
   ]
  },
  {
   "id": "bodyMass",
   "title": "Body mass (weight)",
   "shape": "sample",
   "description": "The user's weight at one instant, in kilograms.",
   "valueFields": [
    {
     "name": "kilograms",
     "type": "number",
     "unit": "kg",
     "minimum": 0,
     "required": true,
     "description": "Body mass in kilograms."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKQuantityTypeIdentifier.bodyMass",
      "field": null,
      "platformType": "HKQuantityTypeIdentifierBodyMass",
      "evidence": {
       "quote": "A quantity sample type that measures the user’s weight.",
       "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/bodymass"
      },
      "href": "/healthkit-identifiers/body-mass"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": "a sample at one moment has startDate equal to endDate",
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "kilograms": {
       "status": "mapped",
       "conversion": "read with doubleValue(for:) in kg",
       "factor": null,
       "type": "HKQuantityTypeIdentifier.bodyMass",
       "field": "quantity",
       "platformType": "HKQuantity (mass unit family)",
       "evidence": {
        "quote": "These samples use mass units (described in ) and measure discrete values (described in ).",
        "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/bodymass"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "WeightRecord",
      "field": null,
      "platformType": "Instantaneous",
      "evidence": {
       "quote": "Captures the user's weight.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/WeightRecord"
      },
      "href": "/health-connect/weight-record"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "WeightRecord",
       "field": "time",
       "platformType": "Instant",
       "evidence": {
        "quote": "Time the record happened.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/WeightRecord"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "WeightRecord",
       "field": "zoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at time, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/WeightRecord"
       }
      },
      "kilograms": {
       "status": "mapped",
       "conversion": "Mass → kilograms (inKilograms)",
       "factor": null,
       "type": "WeightRecord",
       "field": "weight",
       "platformType": "Mass",
       "evidence": {
        "quote": "User's weight in kilograms. Required field. Valid range: 0-1000 kilograms.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/WeightRecord"
       }
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "weight",
      "field": "weight",
      "platformType": "Sample",
      "evidence": {
       "quote": "Body weight measurement.",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#weight"
      },
      "href": "/google-health-api/weight"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "weight",
       "field": "weight.sampleTime.physicalTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The time of the observation.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#weight"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "weight",
       "field": "weight.sampleTime.utcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time during the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#weight"
       }
      },
      "kilograms": {
       "status": "mapped",
       "conversion": "÷ 1,000",
       "factor": 0.001,
       "type": "weight",
       "field": "weight.weightGrams",
       "platformType": "number/double",
       "evidence": {
        "quote": "Retrieve the user's weight in grams from the `weightGrams` field in the Weight data type. Convert this to kilograms (divide by 1,000) or pounds (divide by 453.59237).",
        "url": "https://developers.google.com/health/migration/api-specifications"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "not-mapped",
      "type": null,
      "field": null,
      "platformType": null,
      "conversion": null,
      "factor": null,
      "evidence": null,
      "reason": "None of the 65 Health Services DataType constants (Jetpack reference, read 2026-10-04) has a name or description mentioning “weight” or “body mass”: no body-mass type to map."
     },
     "fields": {
      "time": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "kilograms": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "No body-mass type in Health Services."
      }
     }
    }
   },
   "notes": [
    "Pounds: Google's migration guide divides grams by 453.59237 (“Retrieve the user's weight in grams from the `weightGrams` field in the Weight data type. Convert this to kilograms (divide by 1,000) or pounds (divide by 453.59237).”), and elsewhere says “Retrieve the user's weight in grams from the `weightGrams` field in the Weight data type and convert to kilograms (divide by 1,000). To convert pounds to kilograms, divide by 2.2.” The converter uses 453.59237 g per pound."
   ]
  },
  {
   "id": "bodyFat",
   "title": "Body fat percentage",
   "shape": "sample",
   "description": "Body fat as a percentage from 0 to 100.",
   "valueFields": [
    {
     "name": "percent",
     "type": "number",
     "unit": "%",
     "minimum": 0,
     "maximum": 100,
     "required": true,
     "description": "Body fat, 0–100."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKQuantityTypeIdentifier.bodyFatPercentage",
      "field": null,
      "platformType": "HKQuantityTypeIdentifierBodyFatPercentage",
      "evidence": {
       "quote": "A quantity sample type that measures the user’s body fat percentage.",
       "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/bodyfatpercentage"
      },
      "href": "/healthkit-identifiers/body-fat-percentage"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": "a sample at one moment has startDate equal to endDate",
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "percent": {
       "status": "mapped",
       "conversion": "× 100 (Apple: “Percent measures a value between 0.0 and 1.0.”)",
       "factor": 100,
       "type": "HKQuantityTypeIdentifier.bodyFatPercentage",
       "field": "quantity",
       "platformType": "HKQuantity (percent unit family)",
       "evidence": {
        "quote": "Percent measures a value between 0.0 and 1.0.",
        "url": "https://developer.apple.com/documentation/healthkit/hkunit/percent()"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "BodyFatRecord",
      "field": null,
      "platformType": "Instantaneous",
      "evidence": {
       "quote": "Captures the body fat percentage of a user. Each record represents a person's total body fat as a percentage of their total body mass.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/BodyFatRecord"
      },
      "href": "/health-connect/body-fat-record"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "BodyFatRecord",
       "field": "time",
       "platformType": "Instant",
       "evidence": {
        "quote": "Time the record happened.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/BodyFatRecord"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "BodyFatRecord",
       "field": "zoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at time, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/BodyFatRecord"
       }
      },
      "percent": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "BodyFatRecord",
       "field": "percentage",
       "platformType": "Percentage",
       "evidence": {
        "quote": "Percentage. Required field. Valid range: 0-100.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/BodyFatRecord"
       }
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "body-fat",
      "field": "bodyFat",
      "platformType": "Sample",
      "evidence": {
       "quote": "Body fat measurement.",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#bodyfat"
      },
      "href": "/google-health-api/body-fat"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "body-fat",
       "field": "bodyFat.sampleTime.physicalTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The time of the observation.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#bodyfat"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "body-fat",
       "field": "bodyFat.sampleTime.utcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time during the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#bodyfat"
       }
      },
      "percent": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "body-fat",
       "field": "bodyFat.percentage",
       "platformType": "number/double",
       "evidence": {
        "quote": "Required. Body fat percentage. Must be in the range `[0, 100]`.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#bodyfat"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "not-mapped",
      "type": null,
      "field": null,
      "platformType": null,
      "conversion": null,
      "factor": null,
      "evidence": null,
      "reason": "None of the 65 Health Services DataType constants (Jetpack reference, read 2026-10-04) has a name or description mentioning “fat”: no body-fat type to map."
     },
     "fields": {
      "time": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "percent": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "No body-fat type in Health Services."
      }
     }
    }
   },
   "notes": [
    "HealthKit's percent unit is a fraction (0.0–1.0); Health Connect and the Google Health API state 0–100. Mixing them is the classic 0.23-percent body-fat bug."
   ]
  },
  {
   "id": "height",
   "title": "Height",
   "shape": "sample",
   "description": "The user's height at one instant, in meters.",
   "valueFields": [
    {
     "name": "meters",
     "type": "number",
     "unit": "m",
     "minimum": 0,
     "required": true,
     "description": "Height in meters."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKQuantityTypeIdentifier.height",
      "field": null,
      "platformType": "HKQuantityTypeIdentifierHeight",
      "evidence": {
       "quote": "A quantity sample type that measures the user’s height.",
       "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/height"
      },
      "href": "/healthkit-identifiers/height"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": "a sample at one moment has startDate equal to endDate",
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "meters": {
       "status": "mapped",
       "conversion": "read with doubleValue(for:) in m",
       "factor": null,
       "type": "HKQuantityTypeIdentifier.height",
       "field": "quantity",
       "platformType": "HKQuantity (length unit family)",
       "evidence": {
        "quote": "These samples use length units (described in ) and measure discrete values (described in ).",
        "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/height"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HeightRecord",
      "field": null,
      "platformType": "Instantaneous",
      "evidence": {
       "quote": "Captures the user's height.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeightRecord"
      },
      "href": "/health-connect/height-record"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HeightRecord",
       "field": "time",
       "platformType": "Instant",
       "evidence": {
        "quote": "Time the record happened.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeightRecord"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "HeightRecord",
       "field": "zoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at time, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeightRecord"
       }
      },
      "meters": {
       "status": "mapped",
       "conversion": "Length → meters (inMeters)",
       "factor": null,
       "type": "HeightRecord",
       "field": "height",
       "platformType": "Length",
       "evidence": {
        "quote": "Height in Length unit. Required field. Valid range: 0-3 meters.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeightRecord"
       }
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "height",
      "field": "height",
      "platformType": "Sample",
      "evidence": {
       "quote": "Body height measurement.",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#height"
      },
      "href": "/google-health-api/height"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "height",
       "field": "height.sampleTime.physicalTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The time of the observation.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#height"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "height",
       "field": "height.sampleTime.utcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time during the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#height"
       }
      },
      "meters": {
       "status": "mapped",
       "conversion": "÷ 1,000 (int64 arrives as a JSON string)",
       "factor": 0.001,
       "type": "height",
       "field": "height.heightMillimeters",
       "platformType": "string/int64",
       "evidence": {
        "quote": "Retrieve the user's height in millimeters from the `heightMillimeters` field in the Height data type. Convert this to meters (divide by 1,000) or inches (divide by 25.4).",
        "url": "https://developers.google.com/health/migration/api-specifications"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "not-mapped",
      "type": null,
      "field": null,
      "platformType": null,
      "conversion": null,
      "factor": null,
      "evidence": null,
      "reason": "None of the 65 Health Services DataType constants (Jetpack reference, read 2026-10-04) has a name or description mentioning “height”: no height type to map."
     },
     "fields": {
      "time": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "meters": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "No height type in Health Services."
      }
     }
    }
   },
   "notes": []
  },
  {
   "id": "heartRateVariability",
   "title": "Heart rate variability",
   "shape": "sample",
   "description": "One HRV reading in milliseconds, tagged with the statistic it is. SDNN and RMSSD are different measures and never convert into each other.",
   "valueFields": [
    {
     "name": "metric",
     "type": "string",
     "enum": [
      "sdnn",
      "rmssd"
     ],
     "required": true,
     "description": "sdnn: standard deviation of heartbeat intervals. rmssd: root mean square of successive differences."
    },
    {
     "name": "milliseconds",
     "type": "number",
     "unit": "ms",
     "minimum": 0,
     "required": true,
     "description": "The value in milliseconds."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKQuantityTypeIdentifier.heartRateVariabilitySDNN",
      "field": null,
      "platformType": "HKQuantityTypeIdentifierHeartRateVariabilitySDNN",
      "evidence": {
       "quote": "A quantity sample type that measures the standard deviation of heartbeat intervals.",
       "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/heartratevariabilitysdnn"
      },
      "href": "/healthkit-identifiers/heart-rate-variability-sdnn"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": "a sample at one moment has startDate equal to endDate",
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "metric": {
       "status": "mapped",
       "conversion": "always sdnn",
       "factor": null,
       "type": "HKQuantityTypeIdentifier.heartRateVariabilitySDNN",
       "field": "(the type)",
       "platformType": "sdnn",
       "evidence": {
        "quote": "A quantity sample type that measures the standard deviation of heartbeat intervals.",
        "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/heartratevariabilitysdnn"
       }
      },
      "milliseconds": {
       "status": "mapped",
       "conversion": "read with doubleValue(for:) in ms",
       "factor": null,
       "type": "HKQuantityTypeIdentifier.heartRateVariabilitySDNN",
       "field": "quantity",
       "platformType": "HKQuantity (time unit family)",
       "evidence": {
        "quote": "These samples use time units (described in ) and measure discrete values (described in ).",
        "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/heartratevariabilitysdnn"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HeartRateVariabilityRmssdRecord",
      "field": null,
      "platformType": "Instantaneous",
      "evidence": {
       "quote": "Captures user's heart rate variability (HRV) as measured by the root mean square of successive differences (RMSSD) between normal heartbeats.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateVariabilityRmssdRecord"
      },
      "href": "/health-connect/heart-rate-variability-rmssd-record"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HeartRateVariabilityRmssdRecord",
       "field": "time",
       "platformType": "Instant",
       "evidence": {
        "quote": "Time the record happened.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateVariabilityRmssdRecord"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "HeartRateVariabilityRmssdRecord",
       "field": "zoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at time, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateVariabilityRmssdRecord"
       }
      },
      "metric": {
       "status": "mapped",
       "conversion": "always rmssd",
       "factor": null,
       "type": "HeartRateVariabilityRmssdRecord",
       "field": "(the record class)",
       "platformType": "rmssd",
       "evidence": {
        "quote": "Captures user's heart rate variability (HRV) as measured by the root mean square of successive differences (RMSSD) between normal heartbeats.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateVariabilityRmssdRecord"
       }
      },
      "milliseconds": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "HeartRateVariabilityRmssdRecord",
       "field": "heartRateVariabilityMillis",
       "platformType": "Double",
       "evidence": {
        "quote": "Heart rate variability in milliseconds. Required field. Valid Range: 1-200.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/HeartRateVariabilityRmssdRecord"
       }
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "heart-rate-variability",
      "field": "heartRateVariability",
      "platformType": "Sample",
      "evidence": {
       "quote": "Captures user's heart rate variability (HRV) as measured by the root mean square of successive differences (RMSSD) between normal heartbeats or by standard deviation of the inter-beat intervals (SDNN).",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartratevariability"
      },
      "href": "/google-health-api/heart-rate-variability"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "heart-rate-variability",
       "field": "heartRateVariability.sampleTime.physicalTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The time of the observation.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartratevariability"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "heart-rate-variability",
       "field": "heartRateVariability.sampleTime.utcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time during the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartratevariability"
       }
      },
      "metric": {
       "status": "mapped",
       "conversion": "rmssd when this field is present",
       "factor": null,
       "type": "heart-rate-variability",
       "field": "heartRateVariability.rootMeanSquareOfSuccessiveDifferencesMilliseconds",
       "platformType": "rmssd",
       "evidence": {
        "quote": "Optional. The root mean square of successive differences between normal heartbeats. This is a measure of heart rate variability used by Google Health. Must be in the range `[1, 200]`.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartratevariability"
       }
      },
      "milliseconds": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "heart-rate-variability",
       "field": "heartRateVariability.rootMeanSquareOfSuccessiveDifferencesMilliseconds",
       "platformType": "number/double",
       "evidence": {
        "quote": "Optional. The root mean square of successive differences between normal heartbeats. This is a measure of heart rate variability used by Google Health. Must be in the range `[1, 200]`.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#heartratevariability"
       }
      }
     },
     "unmappedFields": [
      {
       "field": "heartRateVariability.standardDeviationMilliseconds",
       "reason": "Not mapped to sdnn. Google describes it as “Optional. The standard deviation of the heart rate variability measurement.” — the deviation of the measurement, not of the heartbeat intervals — so calling it SDNN would be a guess."
      }
     ]
    },
    "wear-os": {
     "type": {
      "status": "not-mapped",
      "type": null,
      "field": null,
      "platformType": null,
      "conversion": null,
      "factor": null,
      "evidence": null,
      "reason": "None of the 65 Health Services DataType constants (Jetpack reference, read 2026-10-04) has a name or description mentioning “variability”: no heart-rate-variability type to map."
     },
     "fields": {
      "time": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "metric": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "No HRV type in Health Services."
      },
      "milliseconds": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "No HRV type in Health Services."
      }
     }
    }
   },
   "notes": [
    "HealthKit publishes SDNN; Health Connect and the Google Health API publish RMSSD. A pipeline that stores both in one column without the metric tag mixes two different numbers."
   ]
  },
  {
   "id": "oxygenSaturation",
   "title": "Blood oxygen saturation (SpO2)",
   "shape": "sample",
   "description": "One SpO2 reading as a percentage from 0 to 100.",
   "valueFields": [
    {
     "name": "percent",
     "type": "number",
     "unit": "%",
     "minimum": 0,
     "maximum": 100,
     "required": true,
     "description": "Oxygen saturation, 0–100."
    }
   ],
   "platforms": {
    "healthkit": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "HKQuantityTypeIdentifier.oxygenSaturation",
      "field": null,
      "platformType": "HKQuantityTypeIdentifierOxygenSaturation",
      "evidence": {
       "quote": "A quantity sample type that measures the user’s oxygen saturation.",
       "url": "https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/oxygensaturation"
      },
      "href": "/healthkit-identifiers/oxygen-saturation"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": "a sample at one moment has startDate equal to endDate",
       "factor": null,
       "type": "HKSample",
       "field": "startDate",
       "platformType": "Date",
       "evidence": {
        "quote": "The sample’s start date.",
        "url": "https://developer.apple.com/documentation/healthkit/hksample/startdate"
       }
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "HealthKit samples carry no UTC offset field. An export.xml date includes the offset (the converter reads it); in the API, the optional HKMetadataKeyTimeZone metadata is a zone name, not an offset."
      },
      "percent": {
       "status": "mapped",
       "conversion": "× 100 (Apple: “Percent measures a value between 0.0 and 1.0.”)",
       "factor": 100,
       "type": "HKQuantityTypeIdentifier.oxygenSaturation",
       "field": "quantity",
       "platformType": "HKQuantity (percent unit family)",
       "evidence": {
        "quote": "Percent measures a value between 0.0 and 1.0.",
        "url": "https://developer.apple.com/documentation/healthkit/hkunit/percent()"
       }
      }
     }
    },
    "health-connect": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "OxygenSaturationRecord",
      "field": null,
      "platformType": "Instantaneous",
      "evidence": {
       "quote": "Captures the amount of oxygen circulating in the blood, measured as a percentage of oxygen-saturated hemoglobin. Each record represents a single blood oxygen saturation reading at the time of measurement.",
       "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/OxygenSaturationRecord"
      },
      "href": "/health-connect/oxygen-saturation-record"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "OxygenSaturationRecord",
       "field": "time",
       "platformType": "Instant",
       "evidence": {
        "quote": "Time the record happened.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/OxygenSaturationRecord"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "ZoneOffset → ±HH:MM; null stays null",
       "factor": null,
       "type": "OxygenSaturationRecord",
       "field": "zoneOffset",
       "platformType": "ZoneOffset?",
       "evidence": {
        "quote": "User experienced zone offset at time, or null if unknown. Providing these will help history aggregations results stay consistent should user travel. Queries with user experienced time filters will assume system current zone offset if the information is absent.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/OxygenSaturationRecord"
       }
      },
      "percent": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "OxygenSaturationRecord",
       "field": "percentage",
       "platformType": "Percentage",
       "evidence": {
        "quote": "Percentage. Required field. Valid range: 0-100.",
        "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/OxygenSaturationRecord"
       }
      }
     }
    },
    "google-health-api": {
     "type": {
      "status": "mapped",
      "conversion": null,
      "factor": null,
      "type": "oxygen-saturation",
      "field": "oxygenSaturation",
      "platformType": "Sample",
      "evidence": {
       "quote": "Captures the user's instantaneous oxygen saturation percentage (SpO2).",
       "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#oxygensaturation"
      },
      "href": "/google-health-api/oxygen-saturation"
     },
     "fields": {
      "time": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "oxygen-saturation",
       "field": "oxygenSaturation.sampleTime.physicalTime",
       "platformType": "string/google-datetime",
       "evidence": {
        "quote": "Required. The time of the observation.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#oxygensaturation"
       }
      },
      "utcOffset": {
       "status": "mapped",
       "conversion": "google-duration seconds (\"3600s\") → ±HH:MM",
       "factor": null,
       "type": "oxygen-saturation",
       "field": "oxygenSaturation.sampleTime.utcOffset",
       "platformType": "string/google-duration",
       "evidence": {
        "quote": "Required. The offset of the user's local time during the observation relative to the Coordinated Universal Time (UTC).",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#oxygensaturation"
       }
      },
      "percent": {
       "status": "mapped",
       "conversion": null,
       "factor": null,
       "type": "oxygen-saturation",
       "field": "oxygenSaturation.percentage",
       "platformType": "number/double",
       "evidence": {
        "quote": "Required. The oxygen saturation percentage. Must be in the range `[0, 100]`.",
        "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#oxygensaturation"
       }
      }
     }
    },
    "wear-os": {
     "type": {
      "status": "not-mapped",
      "type": null,
      "field": null,
      "platformType": null,
      "conversion": null,
      "factor": null,
      "evidence": null,
      "reason": "None of the 65 Health Services DataType constants (Jetpack reference, read 2026-10-04) has a name or description mentioning “spo2” or “saturation”: no oxygen-saturation type to map."
     },
     "fields": {
      "time": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "utcOffset": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "Health Services DataPoint time fields are not in this site's Health Services dataset, and Health Services has no JSON form to convert."
      },
      "percent": {
       "status": "not-mapped",
       "type": null,
       "field": null,
       "platformType": null,
       "conversion": null,
       "factor": null,
       "evidence": null,
       "reason": "No SpO2 type in Health Services."
      }
     }
    }
   },
   "notes": []
  }
 ],
 "sleepStageMaps": {
  "healthkit": [
   {
    "unified": "inBed",
    "value": "HKCategoryValueSleepAnalysisInBed",
    "evidence": "The user is in bed.",
    "url": "https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis/inbed",
    "note": null
   },
   {
    "unified": "awake",
    "value": "HKCategoryValueSleepAnalysisAwake",
    "evidence": "The user is awake.",
    "url": "https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis/awake",
    "note": null
   },
   {
    "unified": "light",
    "value": "HKCategoryValueSleepAnalysisAsleepCore",
    "evidence": "The user is in light or intermediate sleep.",
    "url": "https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis/asleepcore",
    "note": "Apple's core stage is “light or intermediate”; the unified vocabulary has no intermediate stage, so it lands on light."
   },
   {
    "unified": "deep",
    "value": "HKCategoryValueSleepAnalysisAsleepDeep",
    "evidence": "The user is in deep sleep.",
    "url": "https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis/asleepdeep",
    "note": null
   },
   {
    "unified": "rem",
    "value": "HKCategoryValueSleepAnalysisAsleepREM",
    "evidence": "The user is in REM sleep.",
    "url": "https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis/asleeprem",
    "note": null
   },
   {
    "unified": "asleep",
    "value": "HKCategoryValueSleepAnalysisAsleepUnspecified",
    "evidence": "The user is asleep, but the specific stage isn’t known.",
    "url": "https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis/asleepunspecified",
    "note": null
   },
   {
    "unified": "asleep",
    "value": "HKCategoryValueSleepAnalysisAsleep",
    "evidence": "The user is sleeping.",
    "url": "https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis/asleep",
    "note": "Deprecated in iOS 16.0; Apple's availability data names HKCategoryValueSleepAnalysis.asleepUnspecified as its new name."
   }
  ],
  "health-connect": [
   {
    "unified": "unknown",
    "value": 0,
    "evidence": "Use this type if the stage of sleep is unknown.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_UNKNOWN"
   },
   {
    "unified": "awake",
    "value": 1,
    "evidence": "The user is awake and either known to be in bed, or it is unknown whether they are in bed or not.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_AWAKE"
   },
   {
    "unified": "asleep",
    "value": 2,
    "evidence": "The user is asleep but the particular stage of sleep (light, deep or REM) is unknown.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_SLEEPING"
   },
   {
    "unified": "outOfBed",
    "value": 3,
    "evidence": "The user is out of bed and assumed to be awake.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_OUT_OF_BED"
   },
   {
    "unified": "light",
    "value": 4,
    "evidence": "The user is in a light sleep stage.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_LIGHT"
   },
   {
    "unified": "deep",
    "value": 5,
    "evidence": "The user is in a deep sleep stage.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_DEEP"
   },
   {
    "unified": "rem",
    "value": 6,
    "evidence": "The user is in a REM sleep stage.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_REM"
   },
   {
    "unified": "awakeInBed",
    "value": 7,
    "evidence": "The user is awake and in bed.",
    "url": "https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/SleepSessionRecord",
    "note": null,
    "name": "STAGE_TYPE_AWAKE_IN_BED"
   }
  ],
  "google-health-api": [
   {
    "unified": "unknown",
    "value": "SLEEP_STAGE_TYPE_UNSPECIFIED",
    "evidence": "The default unset value.",
    "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep",
    "note": null
   },
   {
    "unified": "awake",
    "value": "AWAKE",
    "evidence": "Sleep stage AWAKE.",
    "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep",
    "note": null
   },
   {
    "unified": "light",
    "value": "LIGHT",
    "evidence": "Sleep stage LIGHT.",
    "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep",
    "note": null
   },
   {
    "unified": "deep",
    "value": "DEEP",
    "evidence": "Sleep stage DEEP.",
    "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep",
    "note": null
   },
   {
    "unified": "rem",
    "value": "REM",
    "evidence": "Sleep stage REM.",
    "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep",
    "note": null
   },
   {
    "unified": "asleep",
    "value": "ASLEEP",
    "evidence": "Sleep stage ASLEEP.",
    "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep",
    "note": null
   },
   {
    "unified": "restless",
    "value": "RESTLESS",
    "evidence": "Sleep stage RESTLESS.",
    "url": "https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints#sleep",
    "note": null
   }
  ]
 },
 "converter": {
  "healthkitTypes": {
   "HKQuantityTypeIdentifierHeartRate": "heartRate",
   "HKQuantityTypeIdentifierStepCount": "steps",
   "HKQuantityTypeIdentifierBodyMass": "bodyMass",
   "HKQuantityTypeIdentifierBodyFatPercentage": "bodyFat",
   "HKQuantityTypeIdentifierHeight": "height",
   "HKQuantityTypeIdentifierHeartRateVariabilitySDNN": "heartRateVariability",
   "HKQuantityTypeIdentifierOxygenSaturation": "oxygenSaturation",
   "HKCategoryTypeIdentifierSleepAnalysis": "sleepSession"
  },
  "healthConnectClasses": {
   "HeartRateRecord": "heartRate",
   "StepsRecord": "steps",
   "SleepSessionRecord": "sleepSession",
   "ExerciseSessionRecord": "workout",
   "WeightRecord": "bodyMass",
   "BodyFatRecord": "bodyFat",
   "HeightRecord": "height",
   "HeartRateVariabilityRmssdRecord": "heartRateVariability",
   "OxygenSaturationRecord": "oxygenSaturation"
  },
  "googleProperties": {
   "heartRate": "heartRate",
   "steps": "steps",
   "sleep": "sleepSession",
   "exercise": "workout",
   "weight": "bodyMass",
   "bodyFat": "bodyFat",
   "height": "height",
   "heartRateVariability": "heartRateVariability",
   "oxygenSaturation": "oxygenSaturation"
  },
  "workouts": {
   "normalisation": "Two constants share a crosswalk row only when their names are identical after removing a leading EXERCISE_TYPE_ (Health Connect's prefix, which the Google Health API also uses on EXERCISE_TYPE_UNSPECIFIED), lowercasing, and removing every character that is not a letter or a digit.",
   "healthkit": {
    "HKWorkoutActivityTypeAmericanFootball": "americanfootball",
    "HKWorkoutActivityTypeArchery": "archery",
    "HKWorkoutActivityTypeAustralianFootball": "australianfootball",
    "HKWorkoutActivityTypeBadminton": "badminton",
    "HKWorkoutActivityTypeBarre": "barre",
    "HKWorkoutActivityTypeBaseball": "baseball",
    "HKWorkoutActivityTypeBasketball": "basketball",
    "HKWorkoutActivityTypeBowling": "bowling",
    "HKWorkoutActivityTypeBoxing": "boxing",
    "HKWorkoutActivityTypeCardioDance": "cardiodance",
    "HKWorkoutActivityTypeClimbing": "climbing",
    "HKWorkoutActivityTypeCooldown": "cooldown",
    "HKWorkoutActivityTypeCoreTraining": "coretraining",
    "HKWorkoutActivityTypeCricket": "cricket",
    "HKWorkoutActivityTypeCrossCountrySkiing": "crosscountryskiing",
    "HKWorkoutActivityTypeCrossTraining": "crosstraining",
    "HKWorkoutActivityTypeCurling": "curling",
    "HKWorkoutActivityTypeCycling": "cycling",
    "HKWorkoutActivityTypeDance": "dance",
    "HKWorkoutActivityTypeDanceInspiredTraining": "danceinspiredtraining",
    "HKWorkoutActivityTypeDiscSports": "discsports",
    "HKWorkoutActivityTypeDownhillSkiing": "downhillskiing",
    "HKWorkoutActivityTypeElliptical": "elliptical",
    "HKWorkoutActivityTypeEquestrianSports": "equestriansports",
    "HKWorkoutActivityTypeFencing": "fencing",
    "HKWorkoutActivityTypeFishing": "fishing",
    "HKWorkoutActivityTypeFitnessGaming": "fitnessgaming",
    "HKWorkoutActivityTypeFlexibility": "flexibility",
    "HKWorkoutActivityTypeFunctionalStrengthTraining": "functionalstrengthtraining",
    "HKWorkoutActivityTypeGolf": "golf",
    "HKWorkoutActivityTypeGymnastics": "gymnastics",
    "HKWorkoutActivityTypeHandball": "handball",
    "HKWorkoutActivityTypeHandCycling": "handcycling",
    "HKWorkoutActivityTypeHighIntensityIntervalTraining": "highintensityintervaltraining",
    "HKWorkoutActivityTypeHiking": "hiking",
    "HKWorkoutActivityTypeHockey": "hockey",
    "HKWorkoutActivityTypeHunting": "hunting",
    "HKWorkoutActivityTypeJumpRope": "jumprope",
    "HKWorkoutActivityTypeKickboxing": "kickboxing",
    "HKWorkoutActivityTypeLacrosse": "lacrosse",
    "HKWorkoutActivityTypeMartialArts": "martialarts",
    "HKWorkoutActivityTypeMindAndBody": "mindandbody",
    "HKWorkoutActivityTypeMixedCardio": "mixedcardio",
    "HKWorkoutActivityTypeMixedMetabolicCardioTraining": "mixedmetaboliccardiotraining",
    "HKWorkoutActivityTypeOther": "other",
    "HKWorkoutActivityTypePaddleSports": "paddlesports",
    "HKWorkoutActivityTypePickleball": "pickleball",
    "HKWorkoutActivityTypePilates": "pilates",
    "HKWorkoutActivityTypePlay": "play",
    "HKWorkoutActivityTypePreparationAndRecovery": "preparationandrecovery",
    "HKWorkoutActivityTypeRacquetball": "racquetball",
    "HKWorkoutActivityTypeRowing": "rowing",
    "HKWorkoutActivityTypeRugby": "rugby",
    "HKWorkoutActivityTypeRunning": "running",
    "HKWorkoutActivityTypeSailing": "sailing",
    "HKWorkoutActivityTypeSkatingSports": "skatingsports",
    "HKWorkoutActivityTypeSnowboarding": "snowboarding",
    "HKWorkoutActivityTypeSnowSports": "snowsports",
    "HKWorkoutActivityTypeSoccer": "soccer",
    "HKWorkoutActivityTypeSocialDance": "socialdance",
    "HKWorkoutActivityTypeSoftball": "softball",
    "HKWorkoutActivityTypeSquash": "squash",
    "HKWorkoutActivityTypeStairClimbing": "stairclimbing",
    "HKWorkoutActivityTypeStairs": "stairs",
    "HKWorkoutActivityTypeStepTraining": "steptraining",
    "HKWorkoutActivityTypeSurfingSports": "surfingsports",
    "HKWorkoutActivityTypeSwimBikeRun": "swimbikerun",
    "HKWorkoutActivityTypeSwimming": "swimming",
    "HKWorkoutActivityTypeTableTennis": "tabletennis",
    "HKWorkoutActivityTypeTaiChi": "taichi",
    "HKWorkoutActivityTypeTennis": "tennis",
    "HKWorkoutActivityTypeTrackAndField": "trackandfield",
    "HKWorkoutActivityTypeTraditionalStrengthTraining": "traditionalstrengthtraining",
    "HKWorkoutActivityTypeTransition": "transition",
    "HKWorkoutActivityTypeUnderwaterDiving": "underwaterdiving",
    "HKWorkoutActivityTypeVolleyball": "volleyball",
    "HKWorkoutActivityTypeWalking": "walking",
    "HKWorkoutActivityTypeWaterFitness": "waterfitness",
    "HKWorkoutActivityTypeWaterPolo": "waterpolo",
    "HKWorkoutActivityTypeWaterSports": "watersports",
    "HKWorkoutActivityTypeWheelchairRunPace": "wheelchairrunpace",
    "HKWorkoutActivityTypeWheelchairWalkPace": "wheelchairwalkpace",
    "HKWorkoutActivityTypeWrestling": "wrestling",
    "HKWorkoutActivityTypeYoga": "yoga"
   },
   "health-connect": {
    "0": {
     "name": "EXERCISE_TYPE_OTHER_WORKOUT",
     "key": "otherworkout"
    },
    "2": {
     "name": "EXERCISE_TYPE_BADMINTON",
     "key": "badminton"
    },
    "4": {
     "name": "EXERCISE_TYPE_BASEBALL",
     "key": "baseball"
    },
    "5": {
     "name": "EXERCISE_TYPE_BASKETBALL",
     "key": "basketball"
    },
    "8": {
     "name": "EXERCISE_TYPE_BIKING",
     "key": "biking"
    },
    "9": {
     "name": "EXERCISE_TYPE_BIKING_STATIONARY",
     "key": "bikingstationary"
    },
    "10": {
     "name": "EXERCISE_TYPE_BOOT_CAMP",
     "key": "bootcamp"
    },
    "11": {
     "name": "EXERCISE_TYPE_BOXING",
     "key": "boxing"
    },
    "13": {
     "name": "EXERCISE_TYPE_CALISTHENICS",
     "key": "calisthenics"
    },
    "14": {
     "name": "EXERCISE_TYPE_CRICKET",
     "key": "cricket"
    },
    "16": {
     "name": "EXERCISE_TYPE_DANCING",
     "key": "dancing"
    },
    "25": {
     "name": "EXERCISE_TYPE_ELLIPTICAL",
     "key": "elliptical"
    },
    "26": {
     "name": "EXERCISE_TYPE_EXERCISE_CLASS",
     "key": "exerciseclass"
    },
    "27": {
     "name": "EXERCISE_TYPE_FENCING",
     "key": "fencing"
    },
    "28": {
     "name": "EXERCISE_TYPE_FOOTBALL_AMERICAN",
     "key": "footballamerican"
    },
    "29": {
     "name": "EXERCISE_TYPE_FOOTBALL_AUSTRALIAN",
     "key": "footballaustralian"
    },
    "31": {
     "name": "EXERCISE_TYPE_FRISBEE_DISC",
     "key": "frisbeedisc"
    },
    "32": {
     "name": "EXERCISE_TYPE_GOLF",
     "key": "golf"
    },
    "33": {
     "name": "EXERCISE_TYPE_GUIDED_BREATHING",
     "key": "guidedbreathing"
    },
    "34": {
     "name": "EXERCISE_TYPE_GYMNASTICS",
     "key": "gymnastics"
    },
    "35": {
     "name": "EXERCISE_TYPE_HANDBALL",
     "key": "handball"
    },
    "36": {
     "name": "EXERCISE_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING",
     "key": "highintensityintervaltraining"
    },
    "37": {
     "name": "EXERCISE_TYPE_HIKING",
     "key": "hiking"
    },
    "38": {
     "name": "EXERCISE_TYPE_ICE_HOCKEY",
     "key": "icehockey"
    },
    "39": {
     "name": "EXERCISE_TYPE_ICE_SKATING",
     "key": "iceskating"
    },
    "44": {
     "name": "EXERCISE_TYPE_MARTIAL_ARTS",
     "key": "martialarts"
    },
    "46": {
     "name": "EXERCISE_TYPE_PADDLING",
     "key": "paddling"
    },
    "47": {
     "name": "EXERCISE_TYPE_PARAGLIDING",
     "key": "paragliding"
    },
    "48": {
     "name": "EXERCISE_TYPE_PILATES",
     "key": "pilates"
    },
    "50": {
     "name": "EXERCISE_TYPE_RACQUETBALL",
     "key": "racquetball"
    },
    "51": {
     "name": "EXERCISE_TYPE_ROCK_CLIMBING",
     "key": "rockclimbing"
    },
    "52": {
     "name": "EXERCISE_TYPE_ROLLER_HOCKEY",
     "key": "rollerhockey"
    },
    "53": {
     "name": "EXERCISE_TYPE_ROWING",
     "key": "rowing"
    },
    "54": {
     "name": "EXERCISE_TYPE_ROWING_MACHINE",
     "key": "rowingmachine"
    },
    "55": {
     "name": "EXERCISE_TYPE_RUGBY",
     "key": "rugby"
    },
    "56": {
     "name": "EXERCISE_TYPE_RUNNING",
     "key": "running"
    },
    "57": {
     "name": "EXERCISE_TYPE_RUNNING_TREADMILL",
     "key": "runningtreadmill"
    },
    "58": {
     "name": "EXERCISE_TYPE_SAILING",
     "key": "sailing"
    },
    "59": {
     "name": "EXERCISE_TYPE_SCUBA_DIVING",
     "key": "scubadiving"
    },
    "60": {
     "name": "EXERCISE_TYPE_SKATING",
     "key": "skating"
    },
    "61": {
     "name": "EXERCISE_TYPE_SKIING",
     "key": "skiing"
    },
    "62": {
     "name": "EXERCISE_TYPE_SNOWBOARDING",
     "key": "snowboarding"
    },
    "63": {
     "name": "EXERCISE_TYPE_SNOWSHOEING",
     "key": "snowshoeing"
    },
    "64": {
     "name": "EXERCISE_TYPE_SOCCER",
     "key": "soccer"
    },
    "65": {
     "name": "EXERCISE_TYPE_SOFTBALL",
     "key": "softball"
    },
    "66": {
     "name": "EXERCISE_TYPE_SQUASH",
     "key": "squash"
    },
    "68": {
     "name": "EXERCISE_TYPE_STAIR_CLIMBING",
     "key": "stairclimbing"
    },
    "69": {
     "name": "EXERCISE_TYPE_STAIR_CLIMBING_MACHINE",
     "key": "stairclimbingmachine"
    },
    "70": {
     "name": "EXERCISE_TYPE_STRENGTH_TRAINING",
     "key": "strengthtraining"
    },
    "71": {
     "name": "EXERCISE_TYPE_STRETCHING",
     "key": "stretching"
    },
    "72": {
     "name": "EXERCISE_TYPE_SURFING",
     "key": "surfing"
    },
    "73": {
     "name": "EXERCISE_TYPE_SWIMMING_OPEN_WATER",
     "key": "swimmingopenwater"
    },
    "74": {
     "name": "EXERCISE_TYPE_SWIMMING_POOL",
     "key": "swimmingpool"
    },
    "75": {
     "name": "EXERCISE_TYPE_TABLE_TENNIS",
     "key": "tabletennis"
    },
    "76": {
     "name": "EXERCISE_TYPE_TENNIS",
     "key": "tennis"
    },
    "78": {
     "name": "EXERCISE_TYPE_VOLLEYBALL",
     "key": "volleyball"
    },
    "79": {
     "name": "EXERCISE_TYPE_WALKING",
     "key": "walking"
    },
    "80": {
     "name": "EXERCISE_TYPE_WATER_POLO",
     "key": "waterpolo"
    },
    "81": {
     "name": "EXERCISE_TYPE_WEIGHTLIFTING",
     "key": "weightlifting"
    },
    "82": {
     "name": "EXERCISE_TYPE_WHEELCHAIR",
     "key": "wheelchair"
    },
    "83": {
     "name": "EXERCISE_TYPE_YOGA",
     "key": "yoga"
    }
   },
   "google-health-api": {
    "EXERCISE_TYPE_UNSPECIFIED": "unspecified",
    "AEROBIC_WORKOUT": "aerobicworkout",
    "ARCHERY": "archery",
    "ASSAULT_BIKE": "assaultbike",
    "BACKPACKING": "backpacking",
    "BADMINTON": "badminton",
    "BALLET": "ballet",
    "BALLROOM_DANCE": "ballroomdance",
    "BARRE_CLASS": "barreclass",
    "BASEBALL": "baseball",
    "BASKETBALL": "basketball",
    "BIKING": "biking",
    "BILLIARDS": "billiards",
    "BODY_WEIGHT": "bodyweight",
    "BOOTCAMP": "bootcamp",
    "BOWLING": "bowling",
    "BOXING": "boxing",
    "BREAKDANCING": "breakdancing",
    "CALISTHENICS": "calisthenics",
    "CANOEING": "canoeing",
    "CARDIO_SCULPT": "cardiosculpt",
    "CARDIO_WORKOUT": "cardioworkout",
    "CARPENTRY": "carpentry",
    "CHEERLEADING": "cheerleading",
    "CIRCUIT_TRAINING": "circuittraining",
    "CLEANING": "cleaning",
    "CLIMBING": "climbing",
    "CORE_TRAINING": "coretraining",
    "CRICKET": "cricket",
    "CROQUET": "croquet",
    "CROSS_COUNTRY_SKI": "crosscountryski",
    "CROSS_TRAINING": "crosstraining",
    "CROSSFIT": "crossfit",
    "CURLING": "curling",
    "DANCING": "dancing",
    "DIVING": "diving",
    "ELECTRIC_BIKE": "electricbike",
    "ELECTRIC_SCOOTER": "electricscooter",
    "ELLIPTICAL": "elliptical",
    "EQUESTRIAN_SPORTS": "equestriansports",
    "EXERCISE_CLASS": "exerciseclass",
    "FENCING": "fencing",
    "FIELD_HOCKEY": "fieldhockey",
    "FISHING": "fishing",
    "FITNESS_GAMING": "fitnessgaming",
    "FOILING": "foiling",
    "FOOTBALL_AMERICAN": "footballamerican",
    "FOOTBALL_AUSTRALIAN": "footballaustralian",
    "FREE_WEIGHTS": "freeweights",
    "FRISBEE_PLAYING_GENERAL": "frisbeeplayinggeneral",
    "FUNCTIONAL_STRENGTH_TRAINING": "functionalstrengthtraining",
    "GARDENING": "gardening",
    "GOLF": "golf",
    "GYMNASTICS": "gymnastics",
    "HANDBALL": "handball",
    "HAND_CYCLING": "handcycling",
    "HIIT": "hiit",
    "HIKING": "hiking",
    "HIP_HOP": "hiphop",
    "HOCKEY": "hockey",
    "HOEING": "hoeing",
    "HOUSEHOLD_CHORES": "householdchores",
    "HUNTING": "hunting",
    "ICE_SKATING": "iceskating",
    "INCLINE_RUN": "inclinerun",
    "INCLINE_WALK": "inclinewalk",
    "INDOOR_CLIMBING": "indoorclimbing",
    "INTERVAL_WORKOUT": "intervalworkout",
    "JAZZ_DANCE": "jazzdance",
    "JIU_JITSU": "jiujitsu",
    "JUMPING_ROPE": "jumpingrope",
    "KARATE": "karate",
    "KAYAKING": "kayaking",
    "KICKBOXING": "kickboxing",
    "KITESURFING": "kitesurfing",
    "LACROSSE": "lacrosse",
    "MARTIAL_ARTS": "martialarts",
    "MEDITATE": "meditate",
    "MODERN_DANCE": "moderndance",
    "MOTOCROSS": "motocross",
    "MOTORCYCLE": "motorcycle",
    "MOUNTAIN_BIKE": "mountainbike",
    "MOWING_LAWN": "mowinglawn",
    "MUAY_THAI": "muaythai",
    "MULTISPORT": "multisport",
    "MUSICAL_PERFORMANCE": "musicalperformance",
    "NORDIC_WALKING": "nordicwalking",
    "ORIENTEERING": "orienteering",
    "OTHER": "other",
    "OUTDOOR_BIKE": "outdoorbike",
    "OUTDOOR_WORKOUT": "outdoorworkout",
    "PADDLEBOARDING": "paddleboarding",
    "PADEL": "padel",
    "PAINTING": "painting",
    "PARAGLIDING": "paragliding",
    "PARKOUR": "parkour",
    "PICKELBALL": "pickelball",
    "PILATES": "pilates",
    "POLO": "polo",
    "POWERLIFTING": "powerlifting",
    "POWER_WALKING": "powerwalking",
    "RACKET_SPORTS": "racketsports",
    "RACQUETBALL": "racquetball",
    "RESISTANCE_BANDS": "resistancebands",
    "ROCK_CLIMBING": "rockclimbing",
    "ROLLERBLADING": "rollerblading",
    "ROLLER_SKATING": "rollerskating",
    "ROWING": "rowing",
    "ROWING_MACHINE": "rowingmachine",
    "RUCKING": "rucking",
    "RUGBY": "rugby",
    "RUNNING": "running",
    "SAILING": "sailing",
    "SCOOTERING": "scootering",
    "SCUBA_DIVING": "scubadiving",
    "SHOOTING": "shooting",
    "SHOVELING": "shoveling",
    "SKATEBOARDING": "skateboarding",
    "SKATING": "skating",
    "SKIING": "skiing",
    "SKYDIVING": "skydiving",
    "SNORKELING": "snorkeling",
    "SNOWBOARDING": "snowboarding",
    "SNOWMOBILING": "snowmobiling",
    "SNOWSHOEING": "snowshoeing",
    "SNOW_SPORT": "snowsport",
    "SOCCER": "soccer",
    "SOFTBALL": "softball",
    "SPEED_SKATING": "speedskating",
    "SPINNING": "spinning",
    "SPORT": "sport",
    "SQUASH": "squash",
    "STAIRCLIMBER": "stairclimber",
    "STATIONARY_BIKE": "stationarybike",
    "STEP_TRAINING": "steptraining",
    "STRENGTH_TRAINING": "strengthtraining",
    "STRETCHING": "stretching",
    "STROLLER_WALK": "strollerwalk",
    "SURFING": "surfing",
    "SWIMMING": "swimming",
    "SWIMMING_OPEN_WATER": "swimmingopenwater",
    "SWIMMING_POOL": "swimmingpool",
    "SYNCHRONIZED_SWIMMING": "synchronizedswimming",
    "TABATA_WORKOUT": "tabataworkout",
    "TABLE_TENNIS": "tabletennis",
    "TAEKWONDO": "taekwondo",
    "TAI_CHI": "taichi",
    "TANGO": "tango",
    "TENNIS": "tennis",
    "TRACK_AND_FIELD": "trackandfield",
    "TRAIL_RUN": "trailrun",
    "TRAMPOLINE": "trampoline",
    "TREADMILL": "treadmill",
    "TREADMILL_WALK": "treadmillwalk",
    "TRX": "trx",
    "ULTIMATE_FRISBEE": "ultimatefrisbee",
    "UNICYCLING": "unicycling",
    "VOLLEYBALL": "volleyball",
    "VOLLEYBALL_BEACH": "volleyballbeach",
    "WAKEBOARDING": "wakeboarding",
    "WALKING": "walking",
    "WALK_WITH_WEIGHTS": "walkwithweights",
    "WATER_AEROBICS": "wateraerobics",
    "WATER_JOGGING": "waterjogging",
    "WATER_POLO": "waterpolo",
    "WATER_SKIING": "waterskiing",
    "WATER_SPORT": "watersport",
    "WATER_VOLLEYBALL": "watervolleyball",
    "WEEDING": "weeding",
    "WEIGHTLIFTING": "weightlifting",
    "WEIGHT_MACHINES": "weightmachines",
    "WEIGHTS": "weights",
    "WHEELCHAIR": "wheelchair",
    "WINDSURFING": "windsurfing",
    "WORKOUT": "workout",
    "WRESTLING": "wrestling",
    "YOGA": "yoga",
    "YOGA_BIKRAM": "yogabikram",
    "YOGA_HATHA": "yogahatha",
    "YOGA_POWER": "yogapower",
    "YOGA_VINYASA": "yogavinyasa",
    "ZUMBA": "zumba"
   },
   "wear-os": {
    "ALPINE_SKIING": "alpineskiing",
    "BACKPACKING": "backpacking",
    "BACK_EXTENSION": "backextension",
    "BADMINTON": "badminton",
    "BARBELL_SHOULDER_PRESS": "barbellshoulderpress",
    "BASEBALL": "baseball",
    "BASKETBALL": "basketball",
    "BENCH_PRESS": "benchpress",
    "BIKING": "biking",
    "BIKING_STATIONARY": "bikingstationary",
    "BOOT_CAMP": "bootcamp",
    "BOXING": "boxing",
    "BURPEE": "burpee",
    "CALISTHENICS": "calisthenics",
    "CRICKET": "cricket",
    "CROSS_COUNTRY_SKIING": "crosscountryskiing",
    "CRUNCH": "crunch",
    "DANCING": "dancing",
    "DEADLIFT": "deadlift",
    "ELLIPTICAL": "elliptical",
    "EXERCISE_CLASS": "exerciseclass",
    "FENCING": "fencing",
    "FOOTBALL_AMERICAN": "footballamerican",
    "FOOTBALL_AUSTRALIAN": "footballaustralian",
    "FORWARD_TWIST": "forwardtwist",
    "FRISBEE_DISC": "frisbeedisc",
    "GOLF": "golf",
    "GUIDED_BREATHING": "guidedbreathing",
    "GYMNASTICS": "gymnastics",
    "HANDBALL": "handball",
    "HIGH_INTENSITY_INTERVAL_TRAINING": "highintensityintervaltraining",
    "HIKING": "hiking",
    "HORSE_RIDING": "horseriding",
    "ICE_HOCKEY": "icehockey",
    "ICE_SKATING": "iceskating",
    "INLINE_SKATING": "inlineskating",
    "JUMPING_JACK": "jumpingjack",
    "JUMP_ROPE": "jumprope",
    "LAT_PULL_DOWN": "latpulldown",
    "LUNGE": "lunge",
    "MARTIAL_ARTS": "martialarts",
    "MEDITATION": "meditation",
    "MOUNTAIN_BIKING": "mountainbiking",
    "ORIENTEERING": "orienteering",
    "PADDLING": "paddling",
    "PARA_GLIDING": "paragliding",
    "PILATES": "pilates",
    "PLANK": "plank",
    "RACQUETBALL": "racquetball",
    "ROCK_CLIMBING": "rockclimbing",
    "ROLLER_HOCKEY": "rollerhockey",
    "ROLLER_SKATING": "rollerskating",
    "ROWING": "rowing",
    "ROWING_MACHINE": "rowingmachine",
    "RUGBY": "rugby",
    "RUNNING": "running",
    "RUNNING_TREADMILL": "runningtreadmill",
    "SAILING": "sailing",
    "SCUBA_DIVING": "scubadiving",
    "SKATING": "skating",
    "SKIING": "skiing",
    "SNOWBOARDING": "snowboarding",
    "SNOWSHOEING": "snowshoeing",
    "SOCCER": "soccer",
    "SOFTBALL": "softball",
    "SQUASH": "squash",
    "SQUAT": "squat",
    "STAIR_CLIMBING": "stairclimbing",
    "STAIR_CLIMBING_MACHINE": "stairclimbingmachine",
    "STRENGTH_TRAINING": "strengthtraining",
    "STRETCHING": "stretching",
    "SURFING": "surfing",
    "SWIMMING_OPEN_WATER": "swimmingopenwater",
    "SWIMMING_POOL": "swimmingpool",
    "TABLE_TENNIS": "tabletennis",
    "TENNIS": "tennis",
    "UNKNOWN": "unknown",
    "UPPER_TWIST": "uppertwist",
    "VOLLEYBALL": "volleyball",
    "WALKING": "walking",
    "WATER_POLO": "waterpolo",
    "WEIGHTLIFTING": "weightlifting",
    "WORKOUT": "workout",
    "YACHTING": "yachting",
    "YOGA": "yoga"
   },
   "shared": [
    "archery",
    "backpacking",
    "badminton",
    "baseball",
    "basketball",
    "biking",
    "bikingstationary",
    "bootcamp",
    "bowling",
    "boxing",
    "calisthenics",
    "climbing",
    "coretraining",
    "cricket",
    "crosscountryskiing",
    "crosstraining",
    "curling",
    "dancing",
    "elliptical",
    "equestriansports",
    "exerciseclass",
    "fencing",
    "fishing",
    "fitnessgaming",
    "footballamerican",
    "footballaustralian",
    "frisbeedisc",
    "functionalstrengthtraining",
    "golf",
    "guidedbreathing",
    "gymnastics",
    "handball",
    "handcycling",
    "highintensityintervaltraining",
    "hiking",
    "hockey",
    "hunting",
    "icehockey",
    "iceskating",
    "jumprope",
    "kickboxing",
    "lacrosse",
    "martialarts",
    "orienteering",
    "other",
    "paddling",
    "paragliding",
    "pilates",
    "racquetball",
    "rockclimbing",
    "rollerhockey",
    "rollerskating",
    "rowing",
    "rowingmachine",
    "rugby",
    "running",
    "runningtreadmill",
    "sailing",
    "scubadiving",
    "skating",
    "skiing",
    "snowboarding",
    "snowshoeing",
    "soccer",
    "softball",
    "squash",
    "stairclimbing",
    "stairclimbingmachine",
    "steptraining",
    "strengthtraining",
    "stretching",
    "surfing",
    "swimming",
    "swimmingopenwater",
    "swimmingpool",
    "tabletennis",
    "taichi",
    "tennis",
    "trackandfield",
    "volleyball",
    "walking",
    "waterpolo",
    "weightlifting",
    "wheelchair",
    "workout",
    "wrestling",
    "yoga"
   ]
  },
  "units": {
   "mass": {
    "kg": 1,
    "g": 0.001,
    "mg": 0.000001,
    "lb": 0.45359237,
    "kilograms": 1,
    "grams": 0.001,
    "pounds": 0.45359237
   },
   "length": {
    "m": 1,
    "cm": 0.01,
    "mm": 0.001,
    "km": 1000,
    "in": 0.0254,
    "meters": 1,
    "centimeters": 0.01,
    "millimeters": 0.001,
    "inches": 0.0254
   },
   "time": {
    "ms": 1,
    "s": 1000
   },
   "rate": {
    "count/min": 1
   },
   "count": {
    "count": 1
   },
   "percent": {
    "%": 100
   },
   "unitEvidence": {
    "lb": {
     "quote": "Retrieve the user's weight in grams from the `weightGrams` field in the Weight data type. Convert this to kilograms (divide by 1,000) or pounds (divide by 453.59237).",
     "url": "https://developers.google.com/health/migration/api-specifications"
    },
    "in": {
     "quote": "Retrieve the user's height in millimeters from the `heightMillimeters` field in the Height data type. Convert this to meters (divide by 1,000) or inches (divide by 25.4).",
     "url": "https://developers.google.com/health/migration/api-specifications"
    },
    "percent": {
     "quote": "Percent measures a value between 0.0 and 1.0.",
     "url": "https://developer.apple.com/documentation/healthkit/hkunit/percent()"
    }
   }
  },
  "healthkitExportNote": "Apple does not publish export.xml's element and attribute names; the converter reads the attribute names the file itself carries (startDate, endDate, value, unit), whose dates include the device's UTC offset."
 }
}
