---
title: "Update Deepalert Threshold"
method: PUT
path: "/cameras/{camera_id}/deepalert-threshold"
tags: ["cameras"]
---

# Update Deepalert Threshold

`PUT /cameras/{camera_id}/deepalert-threshold`

## Request

- Base URL: `https://api.verdun.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.verdun.ai/cameras/{camera_id}/deepalert-threshold`
- Auth: HTTP bearer

## Path parameters

- `camera_id` string, required

## Request body

- UpdateDeepalertThresholdRequest: PUT /cameras/{id}/deepalert-threshold (owner only). Required; null clears.
  - `confidence_threshold` union, required: DeepAlert confidence floor, 0 < v <= 100 (lower = more sensitive); null = default.
    - number
    - integer

## Response `200`

Successful Response

- EditCameraResponse
  - `id` string, uuid, required: The camera ID.
  - `camera_label` string, required: The label of the camera.
  - `camera_id` string, required: The camera ID.
  - `kvs_stream_name` string, required: The KVS stream name.
  - `ip_address` string, required: The IP address of the camera.
  - `port` string, required: The port of the camera.
  - `username` string, required: Camera account username (the password is never returned).
  - `integration` 'RTSP' | 'Network Optix' | 'Axis' | 'Avigilon' | 'Milestone' | 'Verkada' | 'Turing' | 'Hikvision' | 'AvertX', required
  - `adapter` 'generic_onvif' | 'hanwha_onvif'
  - `brand` 'hanwha' | 'dahua'
  - `model` 'ANV-L7012R'
  - `metadata_format` 'onvif'
  - `rtsp_url` string, nullable: The camera's RTSP URL with its password redacted. Never the working credentialed URL. See EditCameraRequest.rtsp_url for the write contract (blank or a REDACTED-bearing echo means keep).
  - `rag_context` string, nullable: Free-form scene context passed to the AI pipeline for this camera.
  - `ingest_mode` 'continuous' | 'motion_clip'
  - `motion_config` object, nullable: Extensible motion settings with bounded known keys (timings, thresholds, detector geometry/rate and RTSP buffer mode); see app/services/motion_config_validation.py. Unknown keys are preserved.
  - `analytics_provider` 'none' | 'deepalert'
  - `analytics_config` object, nullable: Opaque per-vendor analytics settings interpreted by the ingestor.
  - `ii_enabled` boolean: Incident intelligence on/off; when false motion events still record and alert, but skip AI classification.
  - `fire_watch` boolean: Fire-screen gate; when true, analytics-rejected motion is still screened for smoke/flame before being discarded.
  - `monitoring_profile` 'security' | 'safety'
  - `live_view_only` boolean: Live View only: the camera is connected for Live View with no AI and no alarms (its monitoring state is always off). The site-level flag on the camera's site has the same effect.
  - `display_rotation` integer: Degrees counter-clockwise the recorded frame is turned for display (0 or 180). Set by an owner for an upside-down camera; clips are then stamped with a display-matrix tag and the camera's zones are stored in the rotated (upright) space.
  - `agent_mode` boolean: Agent mode on/off; when true the backend acts on AI recommendations (auto-dismiss / voice-down / escalate-upgrade) instead of holding every clip for human review.
  - `agent_observation_minutes` integer: Post-voice-down observation window in minutes before an alert auto-dismisses (agent mode).
  - `agent_incident_types` string[], nullable: Incident types the agent may process at all on this camera; unselected types go to the human queue. Auto-dismiss is additionally bounded by the global safety allowlist.
  - `incident_routing` object, nullable: Per-camera incident routing: incident type -> 'ignore' (dropped and auto-dismissed as not monitored) | 'humans' (operator queue) | 'agent'. A type absent from the map routes to 'humans'; UNKNOWN is never present. Supersedes agent_incident_types, which is now derived from this and kept for one release. Typed as plain strings on the RESPONSE side, deliberately: the read path fails closed (a mode outside the enum reads as 'humans'), and response validation must not undo that by 500-ing on a stored value this build does not know - a hand edit, or a newer task's mode during a rolling deploy. The enum is enforced on the REQUEST model only.
  - `detection_mode` string, nullable: DeepAlert Phase B routing mode (owner-only, written via PUT /cameras/{id}/detection-mode): 'legacy' | 'ii_gated'; null means legacy. Only meaningful when analytics_provider == 'deepalert'.
  - `ptz` boolean: Whether this camera is pan/tilt/zoom; when true the 'camera moved' health issue is suppressed.
  - `integration_id` string, uuid, nullable: The cloud-VMS connection (site_integrations.id) this camera was onboarded from; null for NVR and direct-RTSP cameras.
  - `external_device_id` string, nullable: The VENDOR's own camera id within that connection; null unless integration_id is set.
  - `integration_device_info` object, nullable: Snapshot of what the vendor reported about the device at import (name, model, site, codec); null unless integration_id is set.
  - `live_view_until` string, date-time, nullable: On-demand live view is active while now() < this timestamp (motion_clip cameras).
  - `healthy` boolean, nullable: The healthy status of the camera.
  - `last_healthcheck_at` string, date-time, nullable: The last healthcheck at of the camera.
  - `map_x` number, nullable: Normalized floor-plan x position (0..1) on the site map.
  - `map_y` number, nullable: Normalized floor-plan y position (0..1) on the site map.
  - `map_lat` number, nullable: Geographic latitude on the site map.
  - `map_lng` number, nullable: Geographic longitude on the site map.
  - `map_location_label` string, nullable: Operator-facing location prose shown on queue rows and mini-maps.
  - `map_heading` number, nullable: Direction the device faces, degrees clockwise from map-up; null = not aimed.
  - `deepalert_threshold` DeepAlertThresholdModel: The READ-ONLY, server-resolved DeepAlert sensitivity a camera runs at, built by the same resolver create-event uses, so the console shows exactly what api forwards to incident-intelligence (ii). It is a top-level key on a camera read and NEVER part of `analytics_config`, which stays the raw stored blob the form round-trips (a console must never serialize this block back into analytics_config). A missing block means UNKNOWN (an older backend), not 'inherits the fleet default'.
    - `path` 'ii' | 'ingestion' | 'none', required: 'ii' = the camera is ii_gated (incident intelligence owns the DeepAlert gate); 'ingestion' = a DeepAlert camera on the legacy / II-off path, served by the ingestion server's own validator; 'none' = no DeepAlert.
    - `effective` number, nullable: The number api forwards. ii path: the valid override, else the fleet default, so always a number. ingestion path: the valid override, else null (api does not know the ingestion default). none: null.
    - `source` 'camera' | 'fleet_default' | 'invalid_override' | 'ingestion_default', nullable: 'camera' = a valid per-camera override; 'fleet_default' = no override, the fleet default applies (ii path); 'invalid_override' = the stored value is unusable and the fleet default applies (ii path; saving the camera form needs a deliberate repair); 'ingestion_default' = no valid override on the ingestion path, the ingestion server's own default applies (not reported). Null when path is 'none'.
    - `fleet_revision` integer, nullable: The fleet-default revision in force (ii path only), else null.
    - `override` number, nullable: The stored per-camera override when it is a VALID number, else null.
    - `override_valid` boolean: True iff a valid per-camera override is stored.
    - `invalid_override` string, nullable: A short repr of a stored but unusable override, so the console can say 'stored value X is invalid'; null otherwise. Never forwarded to the vendor.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/verdun/apis/verdun-api.md) - [All operations](https://skmtc.dev/verdun/apis/verdun-api/llms.txt) - [OpenAPI document](https://skmtc.dev/verdun/apis/verdun-api/revisions/35a2a6ebedda?raw)
