Skip to main content

Get patient effective threshold (v2)

MethodPath
GET/v2/slim/threshold/patient/:patientId

Authentication · Access policies

Returns the thresholds in effect for one resident in the v2 shape: their own limits where they have them, and the home's limits everywhere else.

This route supersedes GET /v1/slim/threshold/patient/{patientId}. It adds baseline limits, ranges, the optional vitals and a signalsSync health verdict, and it checks that the resident exists.

Auth: Bearer token. The caller must be a practitioner, an admin, a super admin, or hold the "System Owner" access policy. The access policy must grant Goal:read (admins and super admins skip this check). Scope: The resident must be in the caller's project (from the token). A resident in another project (a sub-project included) answers 404, the same as an unknown id.

Request​

Path parameters​

NameTypeRequiredDescription
patientIdstring (uuid)YesThe resident's Patient id.

Behaviour​

  • Read-only; no threshold is created. The one side effect is the "limits not confirmed" flag described below.
  • Every settings field carries a mode: patient (the resident's own limit), organization (follows the home) or, for heart and respiratory rate, baseline (alerts relative to the resident's own baseline). A field in organization mode carries the home's concrete values, so clients never compute the fallback themselves.
  • settings.heartRate and settings.respiratoryRate are either the absolute shape (min and max) or the baseline shape (deviationPercent, baselineAverage, effectiveBand). baselineAverage is the resident's baseline average (the device's latest 7-day mean, rounded to one decimal), null when none is on record. effectiveBand is the band Signals is given: the average moved by deviationPercent either way, null without an average.
  • settings.outOfBed and settings.bedTimePeriod individualise independently: a resident can have their own bed-time window on the home's out-of-bed limit, or the other way round.
  • settings.outOfBed.deviationPercent (or null) is the relative band: alert once an exit runs that many percent past the resident's usual one. baselineAverage is that usual exit length in seconds: the median exit inside the resident's bed-time period over the last 14 nights of presence data, null with the band off or fewer than 7 nights in bed and 5 exits. effectiveMaxDurationSeconds is the limit the evaluator applies: maxDurationSeconds, or the usual exit plus the percentage when that is shorter, floored to the minute; null when out-of-bed alerting is off.
  • settings.bedTimePeriod.timezone is server-resolved: the zone the out-of-bed check reads the window in, which is the home's (Europe/Berlin unless the home set one). start and end are wall-clock times in it. A window nobody stored reads as 19:00 to 09:00, and that is also the window the out-of-bed check applies. A stored end equal to start is a deliberate 24-hour window.
  • settings.oxygenSaturation, pulseRate, perfusionIndex and bodyTemperature are null when neither the home nor the resident watches the vital, else { mode, enabled, min, max }. They are read from Signals first, since Signals evaluates them; Ovok's copy is only the fallback when Signals cannot answer, and signalsSync says so.
  • ranges is the home's range for each vital's limits, the same as on Get current org threshold (v2), so an editor can bound a resident's inputs.
  • id is null: a resident's own limits are not one stored document. updatedAt is when the home's thresholds were last saved, not when the resident's own limits last changed.
  • signalsSync says whether Signals holds the limits Ovok last sent. null means the status could not be read. Otherwise status is one of:
    • ok: a comparison against what Signals holds ran and agreed.
    • pending: a fault was found, and reason names it: limits-not-confirmed, not-found-in-signals, never-pushed, stale-config-push, signals-rule-missing, or a reason with the affected codes after a colon (metric-disarmed:, trigger-mismatch:, trigger-content-mismatch:, evaluator-band-mismatch:).
    • unverified: the check could not run, and reason names the missing evidence (no-pushed-record, no-pushed-fingerprints, no-signals-fingerprints, signals-read-stale). It is not a fault report, and it is not a claim of health.
  • When signalsSync is pending with trigger-mismatch or trigger-content-mismatch (Signals holds something other than the last push), this read also flags the resident as "limits not confirmed". It then appears on GET /signals/config/unconfirmed, where POST /signals/config/unconfirmed/repush can send their limits again, and the next confirmed push clears the flag.
  • A failed read of the home's stored thresholds answers 502, never the home's empty template.

Example​

curl -X GET 'https://api.sandbox.ovok.com/v2/slim/threshold/patient/3f1c2b7e-8d4a-4c1e-9b2f-6a7d5e4c3b21' \
-H "Authorization: Bearer ${OVOK_TOKEN}"

Successful response​

200 — Patient v2 threshold retrieved successfully.

{
"id": null,
"patientId": "3f1c2b7e-8d4a-4c1e-9b2f-6a7d5e4c3b21",
"projectId": "3f1c2b7e-8d4a-4c1e-9b2f-6a7d5e4c3b11",
"updatedAt": "2026-10-09T08:30:00.000Z",
"settings": {
"heartRate": { "mode": "patient", "enabled": true, "min": 50, "max": 100 },
"respiratoryRate": {
"mode": "baseline",
"enabled": true,
"deviationPercent": 25,
"baselineAverage": 16,
"effectiveBand": { "min": 12, "max": 20 }
},
"outOfBed": {
"mode": "patient",
"enabled": true,
"maxDurationSeconds": 900,
"deviationPercent": 50,
"baselineAverage": 312,
"effectiveMaxDurationSeconds": 420
},
"bedTimePeriod": { "mode": "organization", "start": "19:00:00", "end": "09:00:00", "timezone": "Europe/Berlin" },
"oxygenSaturation": { "mode": "organization", "enabled": true, "min": 92, "max": null },
"pulseRate": null,
"perfusionIndex": null,
"bodyTemperature": null
},
"ranges": {
"heartRate": { "min": 40, "max": 120 },
"respiratoryRate": { "min": 4, "max": 60 },
"oxygenSaturation": { "min": 70, "max": 100 },
"pulseRate": { "min": 40, "max": 120 },
"perfusionIndex": { "min": 0, "max": 20 },
"bodyTemperature": { "min": 34, "max": 42 }
},
"signalsSync": { "status": "ok" }
}
FieldTypeDescription
idstring | nullAlways null today.
patientIdstring (uuid)The resident.
projectIdstringThe caller's project.
updatedAtstring (ISO 8601 date-time) | nullWhen the home's thresholds were last saved.
settingsobjectThe limits in effect for the resident.
settings.heartRateobjectHeart-rate limit. Either the absolute shape or the baseline shape below.
settings.heartRate.mode"organization" | "patient" | "baseline"organization follows the home (absolute or, for a home that still holds one, baseline). patient is the resident's own absolute band. baseline is the resident's own baseline band.
settings.heartRate.enabledbooleanWhether the limit alerts.
settings.heartRate.minnumberLower bound in beats per minute. Absolute shape only.
settings.heartRate.maxnumberUpper bound in beats per minute. Absolute shape only.
settings.heartRate.deviationPercentnumberBaseline shape only: the symmetric deviation from the resident's baseline, in percent.
settings.heartRate.baselineAveragenumber | nullBaseline shape only: the resident's baseline average, or null when none is on record.
settings.heartRate.effectiveBandobject | nullBaseline shape only: the band in effect, or null without an average.
settings.heartRate.effectiveBand.minnumberLower bound of the band in effect.
settings.heartRate.effectiveBand.maxnumberUpper bound of the band in effect.
settings.respiratoryRateobjectRespiratory-rate limit. Same fields as settings.heartRate, in breaths per minute.
settings.outOfBedobjectOut-of-bed limit.
settings.outOfBed.mode"organization" | "patient"Whether the limit follows the home or is the resident's own.
settings.outOfBed.enabledbooleanWhether out-of-bed alerting is on.
settings.outOfBed.maxDurationSecondsintegerThe longest exit allowed, in seconds.
settings.outOfBed.deviationPercentinteger | nullThe relative band, in percent. null when off.
settings.outOfBed.baselineAveragenumber | nullThe resident's usual exit length in seconds. null with the band off, on too little data, or when it could not be read.
settings.outOfBed.effectiveMaxDurationSecondsnumber | nullThe limit the evaluator applies to this resident, in seconds. null when out-of-bed alerting is off.
settings.bedTimePeriodobjectThe window in which out-of-bed is checked.
settings.bedTimePeriod.mode"organization" | "patient"Whether the window is the home's or the resident's own.
settings.bedTimePeriod.startstring (HH:MM:SS)Window start, wall-clock time in timezone.
settings.bedTimePeriod.endstring (HH:MM:SS)Window end. Equal to start means 24 hours; before start crosses midnight.
settings.bedTimePeriod.timezonestring | nullIANA time zone the window is read in, resolved by the server.
settings.oxygenSaturationobject | nullSpO₂ limit. null when neither the home nor the resident watches the vital.
settings.oxygenSaturation.mode"organization" | "patient"Whether the limit follows the home or is the resident's own.
settings.oxygenSaturation.enabledbooleanWhether the limit alerts.
settings.oxygenSaturation.minnumber | nullLower bound, or null for none.
settings.oxygenSaturation.maxnumber | nullUpper bound, or null for none.
settings.pulseRateobject | nullPulse-rate limit. Same fields as settings.oxygenSaturation.
settings.perfusionIndexobject | nullPerfusion-index limit. Same fields as settings.oxygenSaturation.
settings.bodyTemperatureobject | nullBody-temperature limit. Same fields as settings.oxygenSaturation.
rangesobjectThe home's range for each vital's limits. Always present.
ranges.heartRateobject{ min, max }, both number. Same shape for ranges.respiratoryRate, ranges.oxygenSaturation, ranges.pulseRate, ranges.perfusionIndex and ranges.bodyTemperature.
signalsSyncobject | nullWhether Signals holds the limits Ovok last sent. null when the status could not be read.
signalsSync.status"ok" | "pending" | "unverified"The verdict. See Behaviour.
signalsSync.reasonstringPresent when status is pending or unverified. Names the fault or the missing evidence.

Errors​

StatusMeaning
400Your session has no project.
401Bearer token is missing, invalid or expired.
403You are not a practitioner, admin or System Owner, or you lack Goal:read.
404No patient with this id exists, or the patient is in another project.
502The home's stored thresholds could not be read.
503The access policy could not be read right now. Retry.