NeccessoryNeccessory

Measurement Result

The canonical measurement JSON — the shape every SDK emits and the API returns.

There is one measurement result shape. It is what the SDKs deliver on completion, what the REST API stores and returns, and what the console renders. This page documents it field by field.

The envelope

API responses wrap the result in the standard envelope:

{ "ok": true, "data": { /* the measurement, below */ } }

Errors use { "ok": false, "error": { "code", "message" } } — see Errors.

The measurement object

{
  "id": "meas_9c1f4b7ae2d05138b6a37f42",     // string
  "keyId": "nk_live_sRwG9z2hK2hdV4Il83J7Cw", // key that produced this measurement (or null)
  "source": "web",                           // "web" | "ios" | "playground"
  "origin": "cloud",                         // "cloud" | "on_device" — who computed the metrics
  "attested": true,                          // true only when we computed them
  "createdAt": 1751810602000,                // epoch milliseconds, number
  "durationSec": 32.4,                       // capture length in seconds
  "isComplete": true,                        // boolean
  "sdkVersion": "0.1.0",                     // client SDK that produced it, optional
  "modelsVersion": "wv-5",                   // model bundle it ran, optional
  "requestId": "req_9a1c4e77b0d2358fc6e4",   // the API call that stored it, when there was one
  "userRef": "u_42",                         // your own end-user id, when you sent one

  "quality": {                               // REQUIRED, never null
    "level": "good",                         // "good" | "fair" | "poor"
    "score": 0.82,                           // 0..1
    "usable": true                           // boolean
  },

  "cardiac": {
    "heartRate": {
      "value": 72,                        // int | null
      "unit": "bpm",
      "confidence": 0.88                  // 0..1, present when the SDK emits one
    }
  },

  "hrv": {                                // all int | null unless noted
    "sdnnMs": 48,                         // headline
    "rmssdMs": 41,
    "pnn50Pct": 12.5,                     // number | null
    "sd1Ms": 29.1,                        // Poincare, number | null
    "sd2Ms": 61.4,
    "sd1Sd2Ratio": 0.47,
    "csi": 2.11,
    "cvi": 3.25,
    "lfhf": 1.4,                          // frequency domain, number | null
    "lfPower": 812,
    "hfPower": 580,
    "vlfPower": 210,
    "totalPower": 1602
  },

  "respiratory": {
    "breathingRate": { "value": 15, "unit": "brpm" }   // int | null
  },

  "stress": {
    "index": 34,                          // int 0..100 | null
    "level": "low",                       // "low" | "moderate" | "high" | null
    "unit": "index"
  },

  // ── Beta sections. Wellness only; each carries tier and disclaimer. ──
  "bloodPressure": {
    "systolicMmHg": 118,                  // int | null
    "diastolicMmHg": 77,                  // int | null
    "mapMmHg": 90,                        // derived, int | null
    "ppMmHg": 41,                         // derived, int | null
    "unit": "mmHg",
    "confidence": 0.51,
    "tier": "beta",
    "disclaimer": "Estimate for wellness use only. Not a medical device."
  },

  "spo2": {
    "value": 97,                          // int | null
    "unit": "%",
    "confidence": 0.60,
    "tier": "beta",
    "disclaimer": "Estimate for wellness use only. Not a medical device."
  },

  "emotion": {
    "dominant": "Neutral",                // string | null
    "dominantConfidence": 0.64,           // 0..1 | null
    "probabilities": { "Neutral": 0.64 }, // object | null
    "tier": "beta",
    "disclaimer": "Estimate for wellness use only. Not a medical device."
  },

  "behavior": {
    "attentionPercent": 82,               // int | null
    "fatiguePercent": 24,                 // int | null
    "blinkRate": 17,                      // per minute, int | null
    "cardiacOutput": 5.1,                 // number | null
    "gaze": { "yawDeg": -2.4, "pitchDeg": 1.1 },
    "headPose": { "yawDeg": -3.0, "pitchDeg": 2.2, "rollDeg": 0.4 },
    "tier": "beta",
    "disclaimer": "Estimate for wellness use only. Not a medical device."
  },

  "raw": {                                   // OPT-IN ONLY — omitted unless requested
    "rrIntervalsMs": [812, 799, 834],
    "ppgSignal": [0.12, 0.14, 0.11],
    "sampleRateHz": 30
  }
}

Field rules

  • quality is required and never null. See Signal quality.
  • Every section key is always present, but individual metric values may be null. Always handle null — hide or dim, never render a guessed number.
  • When quality.level is "poor", every metric is null. That is "no measurement", not "a bad measurement".
  • bloodPressure, spo2, emotion and behavior are Beta. Each carries tier: "beta" and a disclaimer. Never render them at the same visual authority as the Core sections.
  • raw is absent by default. It appears only when you explicitly opt in — pass ?advanced=true on the query string or { "includeAdvanced": true } in the request body when submitting. It contains RR intervals and the pulse signal for advanced use. It never contains pixels: camera frames are not part of a measurement in either tier.
  • origin and attested are server-owned. The server sets them; a client cannot. They are stripped from anything you submit, exactly like id, keyId and createdAt. attested is true only for cloud measurements, where we computed the metrics ourselves — see Attestation.
  • sdkVersion and modelsVersion say which engine produced the numbers. Both are optional strings of at most 64 characters, matching ^[A-Za-z0-9][A-Za-z0-9._+-]*$; a value outside that shape is rejected with validation_error. Unlike origin and attested they are client-owned: you send them, we store them and hand them back. The web SDK fills both in for you — see Submitting measurements. They are what the console groups by when it shows which versions are live in production, so a fleet that never sends them is invisible there.
  • emotion is a separate, optional module with its own use restrictions, and the physical-state fields in behavior (fatigue, blink rate, head pose) are not emotion inference. See Metrics.
  • test: true appears only on measurements produced by a test key. On real measurements the field is absent, never false. See test keys.
  • cloudJobId appears only on cloud measurements and links back to the job that produced them. Server-owned like origin, absent on on-device measurements.
  • tokensCharged appears only where a charge exists — the tokens this measurement cost, as a number. On-device measurements are not billed and have no such field. See Pricing.
  • requestId names the API call the record came from. It is the value of the X-Request-Id header on the response to POST /sdk/v1/measurements, and the same value appears on that call's row in the usage log — one id ties the call, its log row and the stored record together. Server-owned; absent when no signed call produced the record.
  • userRef is present when you sent one. Your opaque end-user identifier, echoed back — see End users.

Assessment

An optional interpretation block on top of the raw numbers: a wellness score, per-metric norm badges, and machine-readable disclaimers. Console reads always include it; API responses include it only when you ask with ?include=assessment on the query string.

"assessment": {
  "wellnessScore": 74,
  "badges": [
    { "metric": "hr", "state": "in_range", "value": 72, "range": { "low": 55, "high": 100 } },
    { "metric": "bp", "state": "above", "value": { "systolic": 132, "diastolic": 78 }, "range": { "systolic": { "low": 90, "high": 129 }, "diastolic": { "low": 60, "high": 84 } } },
    { "metric": "spo2", "state": "unknown", "value": null, "range": { "low": 95, "high": 100 } },
    { "metric": "breathing", "state": "in_range", "value": 15, "range": { "low": 10, "high": 20 } },
    { "metric": "stress", "state": "in_range", "value": 34, "range": { "low": 0, "high": 60 } }
  ],
  "disclaimers": [
    { "code": "not_medical_device", "text": "Estimate for wellness use only. Not a medical device." },
    { "code": "bp_estimate", "text": "Blood pressure is a beta estimate with a typical error around ±10 mmHg. Ranges are informational, not diagnostic." }
  ]
}
  • state is one of in_range | above | below | unknown. A null metric value maps to unknown — never to a guessed state.
  • wellnessScore is 0..100, and null when quality.level is "poor".
  • A low_quality disclaimer is added when quality.level is fair or poor.
  • The badges are wellness reference ranges, not diagnostics. The disclaimer codes are machine-readable and are there to be shown: render the matching text next to the numbers it qualifies — the BP disclaimer next to the BP values in particular.

Confidence

A per-metric confidence (0..1) is included only where the SDK emits one — today heart rate, blood pressure, and SpO2. HRV, breathing rate, and stress have no per-metric confidence field and inherit trust from the top-level quality. emotion reports its own dominantConfidence.

Metrics reference

For what each value means, its unit, range, and when it works, see Metrics.