Skip to Content
Scopes

Scopes

The API uses a least-privilege scope taxonomy: each scope authorizes a single data domain, and no scope maps to more than one domain. v1 is read-only — there are no write scopes. Health data is split further, scope-wise, into one scope per metric category so an app can read (say) heart metrics without ever touching glucose or sleep.

Each scope authorizes a single domain and limits responses to a fixed field projection. The same field set is returned across single-record, list, and aggregation responses. Fields outside the projection — and all internal fields such as userId and credential hashes — are never returned.

The scope taxonomy

Health data is scope-wise: rather than a single read:health-data scope that exposes every metric, the health-data domain is split into independent metric categories. Each category has its own scope read:health-data:<category> and its own endpoint /api/v1/health-data/<category>. A category scope can only ever read its own metric types — for example read:health-data:heart never returns glucose or sleep readings.

All health-data category scopes share the same fixed projection: id, type, value, unit, timestamp, source.

Health-data category scopes

ScopeCategoryCanonical metric types
read:health-data:heartHeart & cardiacHeart Rate, Resting HR, Walking HR, HRV, ECG
read:health-data:blood-pressureBlood pressureBlood Pressure, BP Diastolic
read:health-data:oxygenBlood oxygenSPO2
read:health-data:respiratoryRespiratoryRespiratory Rate, Respiratory
read:health-data:glucoseBlood glucoseGlucose
read:health-data:temperatureBody temperatureTemperature
read:health-data:activityActivity & movementSteps, Distance, Calories, Basal Calories, Exercise, Flights
read:health-data:sleepSleepSleep, Sleep Deep, Sleep Core, Sleep REM, Sleep Awake, Time in Bed
read:health-data:body-compositionBody compositionWeight, Height, BMI, Body Fat
read:health-data:mindfulnessMindfulnessMindfulness

Other domain scopes

ScopeData domainProjected fields
read:aggregationsaggregations / summariessummary shape only (derived)
read:trendstrendsbucketized trend points only (derived)
read:symptomssymptomsid, description, severity, timestamp
read:medicationsmedications & adherenceid, name, dosage, frequency, condition, pattern
read:conditionsconditionsid, name, severity, sinceDate
read:allergiesallergiesid, name, severity, sinceDate
read:appointmentsappointmentsid, title, dateTime, specialty, location
read:weightweightid, weightKg, date
read:moodmoodid, mood, note, timestamp
read:reportsreportsid, generatedAt, dateRange, summary
read:profileprofile (demographics)name, gender, dateOfBirth, bloodType
read:ehrEHR-derived dataid, resourceType, summary, timestamp

How scopes are enforced

On every authenticated /api/v1 request, the platform:

  1. Resolves the single scope the endpoint requires.
  2. Rejects with INSUFFICIENT_SCOPE (HTTP 403) if the token lacks that scope, or presents a scope not in this taxonomy. The error names the missing scope.
  3. Rejects with CONSENT_REQUIRED (HTTP 403) if no active consent grant covers that scope for the requesting client and target user.

A scope can never reach data outside its own domain.

Requesting scopes

Request only the scopes your app needs. Users can approve a subset, so design your app to degrade gracefully when some requested scopes are not granted.