---
title: Get patient effective threshold (v2)
sidebar_label: Get patient effective threshold (v2)
description: "Get patient effective threshold (v2) using Ovok’s Slim API."
---

# Get patient effective threshold (v2)


| Method | Path |
| --- | --- |
| `GET` | `/v2/slim/threshold/patient/:patientId` |

[Authentication](/authentication) · [Access policies](/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}`](/slim-apis/threshold/get-patient-effective-threshold). 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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `patientId` | `string (uuid)` | Yes | The 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)](/slim-apis/threshold/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

```bash
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.

```json
{
  "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" }
}
```

| Field | Type | Description |
| --- | --- | --- |
| `id` | `string \| null` | Always `null` today. |
| `patientId` | `string (uuid)` | The resident. |
| `projectId` | `string` | The caller's project. |
| `updatedAt` | `string (ISO 8601 date-time) \| null` | When the home's thresholds were last saved. |
| `settings` | `object` | The limits in effect for the resident. |
| `settings.heartRate` | `object` | Heart-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.enabled` | `boolean` | Whether the limit alerts. |
| `settings.heartRate.min` | `number` | Lower bound in beats per minute. Absolute shape only. |
| `settings.heartRate.max` | `number` | Upper bound in beats per minute. Absolute shape only. |
| `settings.heartRate.deviationPercent` | `number` | Baseline shape only: the symmetric deviation from the resident's baseline, in percent. |
| `settings.heartRate.baselineAverage` | `number \| null` | Baseline shape only: the resident's baseline average, or `null` when none is on record. |
| `settings.heartRate.effectiveBand` | `object \| null` | Baseline shape only: the band in effect, or `null` without an average. |
| `settings.heartRate.effectiveBand.min` | `number` | Lower bound of the band in effect. |
| `settings.heartRate.effectiveBand.max` | `number` | Upper bound of the band in effect. |
| `settings.respiratoryRate` | `object` | Respiratory-rate limit. Same fields as `settings.heartRate`, in breaths per minute. |
| `settings.outOfBed` | `object` | Out-of-bed limit. |
| `settings.outOfBed.mode` | `"organization"` \| `"patient"` | Whether the limit follows the home or is the resident's own. |
| `settings.outOfBed.enabled` | `boolean` | Whether out-of-bed alerting is on. |
| `settings.outOfBed.maxDurationSeconds` | `integer` | The longest exit allowed, in seconds. |
| `settings.outOfBed.deviationPercent` | `integer \| null` | The relative band, in percent. `null` when off. |
| `settings.outOfBed.baselineAverage` | `number \| null` | The 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.effectiveMaxDurationSeconds` | `number \| null` | The limit the evaluator applies to this resident, in seconds. `null` when out-of-bed alerting is off. |
| `settings.bedTimePeriod` | `object` | The 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.start` | `string (HH:MM:SS)` | Window start, wall-clock time in `timezone`. |
| `settings.bedTimePeriod.end` | `string (HH:MM:SS)` | Window end. Equal to `start` means 24 hours; before `start` crosses midnight. |
| `settings.bedTimePeriod.timezone` | `string \| null` | IANA time zone the window is read in, resolved by the server. |
| `settings.oxygenSaturation` | `object \| null` | SpO₂ 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.enabled` | `boolean` | Whether the limit alerts. |
| `settings.oxygenSaturation.min` | `number \| null` | Lower bound, or `null` for none. |
| `settings.oxygenSaturation.max` | `number \| null` | Upper bound, or `null` for none. |
| `settings.pulseRate` | `object \| null` | Pulse-rate limit. Same fields as `settings.oxygenSaturation`. |
| `settings.perfusionIndex` | `object \| null` | Perfusion-index limit. Same fields as `settings.oxygenSaturation`. |
| `settings.bodyTemperature` | `object \| null` | Body-temperature limit. Same fields as `settings.oxygenSaturation`. |
| `ranges` | `object` | The home's range for each vital's limits. Always present. |
| `ranges.heartRate` | `object` | `{ min, max }`, both `number`. Same shape for `ranges.respiratoryRate`, `ranges.oxygenSaturation`, `ranges.pulseRate`, `ranges.perfusionIndex` and `ranges.bodyTemperature`. |
| `signalsSync` | `object \| null` | Whether 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.reason` | `string` | Present when `status` is `pending` or `unverified`. Names the fault or the missing evidence. |

## Errors

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