# Update org threshold (v2)

Canonical page: https://docs.ovok.com/api/slim/threshold/v2/update-org-threshold-v2

`PUT /v2/slim/threshold`

Saves the home's threshold configuration in the v2 shape. `mode` is required on every settings field; `patient` is not a valid mode here.

**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 `PlanDefinition:update` (an admin or super admin who holds no access policy skips this check).
**Scope:** The caller's project (from the token).

## Behaviour

- `settings.heartRate` and `settings.respiratoryRate`: `mode: 'organization'` with `enabled`, `min` and `max`. The home's band is absolute; `mode: 'baseline'` answers 422, because a resident without a baseline of their own would get no alarm from it. Set baseline limits per resident with `PUT /v2/slim/threshold/patient/{patientId}`.
- `settings.outOfBed`: `mode: 'organization'` with `enabled` and `maxDurationSeconds` (a multiple of 60, from 0 to 86400), plus an optional `deviationPercent` (an integer from 5 to 300, or `null` to switch it off). With it, every resident on the home's out-of-bed setting alerts once an exit runs that far past their own usual exit, if that is sooner than `maxDurationSeconds`. Omit it to keep the stored value.
- `settings.bedTimePeriod`: `mode: 'organization'` with `start` and `end` (`HH:MM:SS`). `end` equal to `start` means 24 hours; `end` before `start` crosses midnight.
- `settings.oxygenSaturation`, `pulseRate`, `perfusionIndex`, `bodyTemperature` (each optional): `{ mode: 'organization', enabled, min, max }`, the home's default for every resident. Either bound may be `null` for a one-sided limit. An enabled vital needs at least one bound, and `min` must be below `max`. Omitting one, or sending `null`, keeps what is stored. Disabling one removes its rules in Signals.
- `ranges` (optional): the range each vital's limits may take, for the home and every resident. Per vital, `{ min, max }` with `min < max`, inside heart rate 20–300, respiratory rate 4–150, SpO₂ 50–100, pulse 20–300, perfusion index 0–20 and body temperature 30–45. A vital left out keeps its stored range, or the default: heart rate 40–120, respiratory rate 4–60, SpO₂ 70–100, pulse 40–120, perfusion index 0–20, body temperature 34–42. A range for SpO₂, pulse, perfusion index or temperature is kept with that vital's setting, so the home must have set the vital (it may be disabled); otherwise the PUT answers 422 on `ranges.<vital>`.
- Every enabled limit must sit inside its range, counting `ranges` in the same request. One outside answers 422 naming the field (for example `settings.heartRate.max`) and nothing is saved. A disabled band is not checked.
- Narrowing a range does not rewrite residents whose limits fall outside it. A resident's next change to such a limit must fit; their other edits still save.
- Medical limits (heart rate, respiratory rate, the optional vitals, the out-of-bed limit and the bed-time window) are evaluated by Signals. Every save is all or nothing, one that changes nothing included: it writes the home's settings to Signals and answers only once Signals holds them, and nothing writes them later. Residents following the home follow it at once, the out-of-bed band included (Signals applies it to each resident's usual exit); a resident with limits of their own keeps them.
- Homes with many residents take longer: the save gives up after about 25 seconds and puts back what it wrote. Putting back can take longer than the gateway allows, so the caller may get a 504 while it finishes. Read the limits (`GET /v2/slim/threshold`) before sending the save again: until the undo is done, another save answers 409.
- If any of that fails, everything the save changed is put back and it answers an error with `saved: false`. Nothing is stored; send the save again:
  - 409: another save of this home's limits is running, the home is moving to another Signals tenant, or the home's limits were saved while this one ran.
  - 502: the save ran out of time, or Signals did not take the limits.
  - 500: putting the previous limits back failed too. The message says which side kept the new limits; save the home's limits again.
- If the stored thresholds cannot be read, the PUT answers 502 and nothing is saved.
- Unknown keys are stripped, so a GET response can be sent back as a PUT body, with two exceptions: a heart-rate or respiratory-rate field still stored on baseline (see above), and a range the GET reports for an optional vital the home has never set.
- A change-history entry is written for a save that stands. The response is the saved configuration, with `signalsSync: { status: 'ok' }`.
- The v1 route `PUT /v1/slim/threshold` is deprecated in favour of this one.

## Example

```bash
curl -X PUT 'https://api.sandbox.ovok.com/v2/slim/threshold' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' \
  -H 'Content-Type: application/json' \
  -d '{
    "settings": {
      "heartRate": { "mode": "organization", "enabled": true, "min": 40, "max": 120 },
      "respiratoryRate": { "mode": "organization", "enabled": true, "min": 8, "max": 25 },
      "outOfBed": { "mode": "organization", "enabled": true, "maxDurationSeconds": 900 },
      "bedTimePeriod": { "mode": "organization", "start": "19:00:00", "end": "09:00:00" }
    }
  }'
```
