---
title: "Post Camera Connection Test"
method: POST
path: "/analytics/camera-health/connection-test"
tags: ["analytics"]
---

# Post Camera Connection Test

`POST /analytics/camera-health/connection-test`

## 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/analytics/camera-health/connection-test`
- Auth: HTTP bearer

"Reconnect & notify", step 1: try to open each named camera's stream
now, and ask its ingestor for a fresh health sample.

One RTSP DESCRIBE per camera from the API (rtsp_probe, the NVR Test &
Save probe), channels of one recorder account tried serially and stopped
at the first credential that went out without being proven accepted,
with secret reads, DNS and probes sharing an ~11 s budget. The answer separates "the customer's camera is
unreachable" from "reachable, so the outage is ours" - the second must
not turn into an e-mail to the customer.

VERDUN STAFF ONLY (require_central_staff; read_only is then refused by
the global write guardrail). NARROWER than Re-check on purpose: the
customer-side logins can edit a camera's RTSP address, and a probe that
reports reachable vs refused for an address they chose is a port scanner
pointed at our own network. Scope is the Camera Health tab's own; an id
outside it is a 404. Not activity-logged: it changes no configuration.

## Request body

- PostCameraConnectionTestRequest: Which cameras to try to connect to now. The console sends one site's down cameras per call. Bounded so a single request stays inside its write timeout even when every camera hangs.
  - `camera_ids` string[], required: Camera row ids. Any id the caller cannot see on the Camera Health tab makes the whole request a 404 and nothing is probed.

## Response `200`

Successful Response

- PostCameraConnectionTestResponse
  - `tested_at` string, date-time, required: Server time of the test; also the re-check stamp written on the cameras.
  - `recheck_requested` integer, required: motion_clip cameras newly asked for a health sample (same cooldown as Re-check cameras). The ingestor answers within about a minute when it can reach the camera.
  - `results` CameraConnectionResult[], required: One per requested camera, in request order.
    - `camera_id` string, required: Camera row id, as sent.
    - `outcome` 'reachable' | 'auth_failed' | 'unreachable' | 'stream_error' | 'inconclusive' | 'no_stream_url' | 'not_tested', required: reachable: the stream answered DESCRIBE. auth_failed: reached, but the stored credentials were refused. unreachable: no TCP connection (refused, no route, timeout, DNS). stream_error: reached, but the camera or recorder returned an error. inconclusive: answered in a way that proves nothing. no_stream_url: nothing stored to probe. not_tested: skipped (time budget, or another camera on the same recorder already had its credentials refused, so this one was spared a lockout attempt).
    - `detail` string, required: Fixed operator-facing sentence for the outcome. Never the probe's raw error text.
    - `probe_status` string, nullable: The underlying rtsp_probe status, for support. Null when no probe ran.
    - `rtsp_status` integer, nullable: RTSP status code of the final response, when one arrived.
    - `codec` string, nullable: Video codec named in the SDP (h264/h265) when the stream answered.
    - `credentials_unproven` boolean: True when a credential was sent for this camera and not proven accepted (refused, or the exchange was cut short after Authorization). The server stops that recorder account's remaining channels on it; a client splitting one site across several calls should stop too, to avoid feeding the recorder's lockout counter.

## 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)
