Skip to main content

Measurements and health data

Use this guide to choose a measurement category, understand its data shape, and read or save values through @ovok/core. Each declared category has a separate page with field details and an app-level example.

The SDK maps supported measurements to FHIR Observation resources. A category key selects the measurement shape; it does not by itself guarantee that the SDK can read or save that category.

Measurement support​

The SDK declares 22 measurement category keys. Eighteen currently have a typed observation read mapping and save service. Four are declared keys without a working measurement workflow.

CategoryKeyReadSave
Blood glucosebloodGlucoseYesYes
Blood pressurebloodPressureYesYes
ECGecgYesYes
Blood oxygen and pulse ratebloodOxygenPulseRateYesYes
Body weightbodyWeightYesYes
Body temperaturetemperatureYesYes
Urine analysisurineAnalysisYesYes
Uric acid legacy keyuricAcidYes, deprecated aliasYes, deprecated alias
Heart rateheartRateYesYes
Heart-rate variabilityheartRateVariabilityYesYes
Respiratory raterespiratoryRateYesYes
VO₂ maxvo2MaxYesYes
Step countstepCountYesYes
Resting heart raterestingHeartRateYesYes
Walking heart-rate averagewalkingHeartRateAverageYesYes
Symptom questionnairesymptomQuestionnaireNoNo
COSINUSS multiparametercosinussMultiParamNoNo
Photo uploadphotoUploadNoNo
Spirometry panelspirometryPanelNoNo
Lipid panellipidPanelYesYes
Respiratory therapyrespiratoryTherapyYesYes
Baby sleepbabySleepYesYes

The four unsupported keys are present in the enum only, except that spirometry also has a data shape declaration. None has a complete typed observation read and save workflow. Do not pass them to the measurement hooks or save method and expect the SDK to handle them.

Measurement types​

Each linked page documents the category key, public fields, units, read mapping, save behavior, limitations, and an example:

Read measurements in React​

Render the component below OvokProvider and call useObservations() from a client-side component. Pass one or more supported category keys. Use patientId and period to scope the search.

import { MeasurementTypeKey, useObservations } from '@ovok/core';

const types = [
MeasurementTypeKey.bloodGlucose,
MeasurementTypeKey.heartRate,
] as const;

export function HealthReadings({ patientId }: { patientId?: string }) {
const { measurements, observations, loading, error } = useObservations({
types,
patientId,
period: { start: new Date('2026-10-01T00:00:00Z') },
});

if (loading) return <p>Loading readings…</p>;
if (error) return <p role="alert">{error.message}</p>;

return (
<section>
<p>{measurements.length} mapped measurement groups</p>
<p>{observations.length} matching Observation resources</p>
</section>
);
}

The hook returns mapped measurements, the original read-only observations, a loading flag, and an optional error. A single measurement can map to multiple Observations, and one ECG recording or urine strip can contain multiple related resources. Keep the original resources when the interface needs source metadata or effective times not represented in the typed measurement.

If patientId is omitted, the hook does not add a patient filter. Use an explicit patient ID when the screen must be scoped to one patient. See the useObservations reference for the full query options and state behavior.

Save measurements​

Use useSaveMeasurement() in React, or call saveMeasurement() on a configured OvokClient from non-component code. Every request needs a typed measurement.

Request fieldRequiredPurpose
measurementYesCategory key and category-specific values.
patientIdNoWhen supplied, targets Patient/{id}. When omitted, the SDK uses the signed-in profile reference, which can be a Patient or Practitioner.
effectiveDateTimeNoEffective time for categories that use a single observation time. Some categories, such as step count, use measurement-specific interval fields.
deviceNoDevice details associated with the observations.

The shared device shape accepts name, localName, manufacturerData, manufacturerName, model, sn, id, and optional batteryPercentage from 0 to 100.

import { MeasurementTypeKey, OvokClient } from '@ovok/core';

const client = new OvokClient({
baseUrl: 'https://api.sandbox.ovok.com',
fhirUrlPath: '/fhir/R4/',
});

async function saveReading() {
return client.saveMeasurement({
measurement: {
measurementTypeKey: MeasurementTypeKey.heartRate,
heartRate: 72,
},
effectiveDateTime: new Date(),
});
}

Without offline queueing, a completed request returns a saved result or rejects with an error. When the opt-in offline queue is enabled, the result can instead have status: 'queued' and a queue ID. Treat that result as pending until a later queue flush confirms the save. See useSaveMeasurement and offline measurement saves.

Units, precision, and dates​

Use the units stated on each category page. Direct SDK saves do not generally convert user-entered units. Some services round values to a documented precision before saving; the page for each category lists that behavior.

Use JavaScript Date values for date fields. The request-level effectiveDateTime applies to categories that store a single effective time. Step counts can specify a start and end interval, ECG uses its recordedAt field for recording time, and urine analysis uses recordedAt for the strip time. See the individual type page for category-specific timing behavior.

Data sources and interpretation​

The SDK maps and transports values. It does not establish which devices or platform integrations produce data for a project, interpret a measurement clinically, or diagnose a condition. Data availability depends on the app’s permissions, device source, and project configuration. Check the data ingestion guide for platform-side ingestion behavior.

For the resource format and coded observation representation, see the FHIR Observation reference. Questionnaire answers use a separate QuestionnaireResponse workflow; see the QuestionnaireResponse reference and the symptom questionnaire category page.