---
title: "Get System Health"
method: GET
path: "/analytics/system-health"
tags: ["analytics"]
---

# Get System Health

`GET /analytics/system-health`

## 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/system-health`
- Auth: HTTP bearer

Fleet-wide detection-pipeline health — the Analytics → System Health tab.

OWNER + SUPPORT (require_diagnostics_reader; support since the owner ask
of 2026-10-14) and NOT the monitoring manager — note that /summary beside
it was relaxed to require_ops_lead by owner decision 2026-09-15 while this
route deliberately was not (the decision's "Out of scope" list names
GET /analytics/system-health alongside Training and logs/*). The two no
longer share a dependency, and that divergence is the point: every block
here is a cross-tenant fleet
aggregate (fail-open share across the whole fleet, per-camera accept-rate
outliers naming cameras under every parent). There is deliberately no
scoped variant — one would leak fleet facts by construction — so there are
no filter parameters and nothing for ensure_analytics_filter_in_scope to
check. Adding a filter later is therefore a deliberate act, not a default.

No query parameters in v1: the windows are fixed (1h / 24h / 7-day band per
block, each block self-describing), and the service serves the whole
payload from a ~5-minute in-process cache, so polling it is cheap by
construction.

## Response `200`

Successful Response

- GetSystemHealthResponse: Owner-only fleet health for the detection pipeline itself (System Health). Every block self-describes its window; nothing here is tenant-scoped, because these are cross-tenant fleet aggregates with no meaningful per-customer variant.
  - `generated_at` string, date-time, required: When this payload was computed. Served from a ~5-minute per-process cache, so two consecutive polls can land on different API tasks and see slightly different values — key any freshness banner off your own fetch time, not off this alone.
  - `cache_age_seconds` integer, required: How old the served payload is, in seconds. 0 means this request computed it.
  - `fail_open` SystemHealthFailOpen, required: M1 — how many clips the pipeline read blind because the detection vendor could not answer. The brownout metric.
    - `window_1h` SystemHealthRatio, required: A count over a total, with the percentage the server computed — never recompute it client-side, and never render a null pct as 0%.
      - `fail_open` integer, required: Clips read without a usable detector verdict in the window.
      - `total` integer, required: Clips in the window this ratio is over.
      - `pct` number, nullable: fail_open as a percentage of total. Null when the window is empty (an empty window is normal, not zero percent).
    - `window_24h` SystemHealthRatio, required: A count over a total, with the percentage the server computed — never recompute it client-side, and never render a null pct as 0%.
      - `fail_open` integer, required: Clips read without a usable detector verdict in the window.
      - `total` integer, required: Clips in the window this ratio is over.
      - `pct` number, nullable: fail_open as a percentage of total. Null when the window is empty (an empty window is normal, not zero percent).
    - `legacy_validator_24h` SystemHealthRatio, required: A count over a total, with the percentage the server computed — never recompute it client-side, and never render a null pct as 0%.
      - `fail_open` integer, required: Clips read without a usable detector verdict in the window.
      - `total` integer, required: Clips in the window this ratio is over.
      - `pct` number, nullable: fail_open as a percentage of total. Null when the window is empty (an empty window is normal, not zero percent).
    - `band_7d_pct` SystemHealthDailyBand, required: A rolling daily baseline the current window is read against. Percentiles are over one point per day, so `days` is how much history the band actually had — a freshly deployed fleet reports a band of 1 or 2 days and the UI should say so rather than draw a confident envelope.
      - `p50` number, nullable: Median of the daily values in the baseline window. Null when no day had data.
      - `p90` number, nullable: 90th percentile of the daily values. Null when no day had data.
      - `days` integer, required: How many days contributed a value.
    - `failsafe_sentinels_24h` integer, required: Clips in the last 24h that NO AI verdict ever arrived for, surfaced to a human by the fail-safe sweep. They are excluded from every ratio on this page — they are not pipeline results — so a persistent nonzero value is its own signal that evals are stalling. Read it beside fail_open: one counts clips read blind, the other clips never read at all.
    - `notes` string[]: Caveats that belong on the number wherever it is rendered.
  - `gate` SystemHealthGate, required: M2 + M7 — how much the object gate is stopping, and what the vision promotions cost.
    - `window_24h` SystemHealthGateWindow, required
      - `stopped` integer, required: Clips the object gate ended before any full interpretation ran.
      - `total` integer, required: ii_gated-arm clips in the window.
      - `stop_pct` number, nullable: stopped as a percentage of total. Null when the window is empty.
      - `fire_screens` integer, required: Gate stops whose vision fire screen actually completed (an errored screen stamps no prompt version, so this counts calls made, not attempted).
      - `fire_screen_cost_usd` number, required: Summed cost of those completed fire screens, in USD.
    - `band_7d_stop_pct` SystemHealthDailyBand, required: A rolling daily baseline the current window is read against. Percentiles are over one point per day, so `days` is how much history the band actually had — a freshly deployed fleet reports a band of 1 or 2 days and the UI should say so rather than draw a confident envelope.
      - `p50` number, nullable: Median of the daily values in the baseline window. Null when no day had data.
      - `p90` number, nullable: 90th percentile of the daily values. Null when no day had data.
      - `days` integer, required: How many days contributed a value.
    - `notes` string[]: Caveats that belong on the number wherever it is rendered.
  - `queue` SystemHealthQueue, required: M3 — the human review queue, point-in-time (no window: it is a depth and an age, not a rate).
    - `depth` integer, required: Alarms waiting for a human, counted with the SAME queue-visibility predicate the operator console uses: AI-evaluated OR early-broadcast (surfaced before the verdict landed), and not operator-evaluated, not expired, not demo. An early-broadcast alarm is on an operator's screen waiting for a decision, so it belongs in the backlog this number reports.
    - `age_p95_minutes` number, nullable: 95th percentile age of those alarms, in minutes. Null when the queue is empty.
    - `oldest_unreviewed_minutes` number, nullable: Age of the oldest waiting alarm, in minutes. Null when the queue is empty.
    - `expiry_horizon_hours` integer, required: How long an unreviewed alarm survives before the hourly sweep expires it out of the queue — regardless of severity.
    - `notes` string[]: Caveats that belong on the number wherever it is rendered.
  - `heightened` SystemHealthHeightened, required: M4 — the benign-heightened flood: what the AI escalates during heightened windows, and how much of it a human then calls nothing.
    - `window_24h` SystemHealthHeightenedWindow, required
      - `heightened_evals` integer, required: Live policy decisions taken inside a heightened monitoring window.
      - `ai_escalated` integer, required: Of those, how many the AI escalated (the leading signal — available immediately).
      - `ai_escalate_pct` number, nullable: ai_escalated as a percentage of heightened_evals. Null when the window is empty.
      - `operator_graded` integer, required: Of the AI-escalated set, how many a human has dispositioned so far. This is the denominator of benign_pct, and the coverage behind it: events still in the queue are excluded, so review lag cannot move the percentage.
      - `operator_false_alarm` integer, required: Of the graded set, how many the operator called a false alarm. 'Non-threatening human activity' is graded but is deliberately NOT counted here — it is a different human judgment.
      - `benign_pct` number, nullable: operator_false_alarm as a percentage of operator_graded. Null when nothing has been graded yet.
    - `band_7d_benign_pct` SystemHealthDailyBand, required: A rolling daily baseline the current window is read against. Percentiles are over one point per day, so `days` is how much history the band actually had — a freshly deployed fleet reports a band of 1 or 2 days and the UI should say so rather than draw a confident envelope.
      - `p50` number, nullable: Median of the daily values in the baseline window. Null when no day had data.
      - `p90` number, nullable: 90th percentile of the daily values. Null when no day had data.
      - `days` integer, required: How many days contributed a value.
    - `notes` string[]: Caveats that belong on the number wherever it is rendered.
  - `camera_accept` SystemHealthCameraAccept, required: M5 — per-camera accept-rate outliers. Per-sensor vendor drift is real: one camera can move days before the fleet does.
    - `window_days` integer, required: Length of the per-camera window, in days.
    - `cameras` integer, required: Live ii_gated cameras with at least one clip in the window.
    - `fleet_accept_pct` number, nullable: Fleet-wide accept rate over the window. Null when the fleet had no clips.
    - `band` SystemHealthCameraAcceptBand, required
      - `p25` number, nullable: Fleet 25th percentile accept rate across eligible cameras. Null when no camera cleared the volume floor.
      - `p75` number, nullable: Fleet 75th percentile accept rate across eligible cameras. Null when no camera cleared the volume floor.
      - `eligible_cameras` integer, required: Cameras that cleared the volume floor and so contributed to the band.
      - `min_cameras` integer, required: How many eligible cameras the band needs before any outlier is reported at all.
    - `band_rule` string, required: The exact outlier rule the server applied, published so the UI labels what it draws instead of restating a rule that could drift.
    - `min_volume` integer, required: Minimum clips in the window for a camera to be eligible for the band or to be flagged.
    - `outliers` SystemHealthCameraRow[]: Eligible cameras outside the band, busiest first.
      - `camera_id` string, required: Camera id.
      - `camera_label` string, nullable: Operator-facing camera name.
      - `site_name` string, nullable: Site the camera belongs to.
      - `total` integer, required: ii_gated-arm clips for this camera in the window.
      - `accept_pct` number, nullable: Share of those clips the gate did NOT stop.
      - `fail_open` integer, required: Of those clips, how many were read blind.
      - `direction` string, required: Which side of the fleet band this camera sits on: 'high' (accepting far more than the fleet) or 'low' (stopping far more).
    - `notes` string[]: Caveats that belong on the number wherever it is rendered.
  - `second_look` SystemHealthSecondLook, required: M6 — the stage-2a shadow's own audit trail. Load-bearing while the shadow soaks; demote it once stage-2a is enforced or abandoned.
    - `window_24h` SystemHealthSecondLookWindow, required
      - `low_band_rows` integer, required: Low-confidence-band interpretations in the window — the population stage-2a triggers on.
      - `traces` integer, required: Of those, how many carry a stage-2a shadow trace.
      - `trace_pct` number, nullable: traces as a percentage of low_band_rows. Null when the window is empty.
      - `status_mix` object: Trace counts by status: 'ran' (the re-check completed) or 'skipped'.
      - `skipped_reasons` object: Skipped traces by their reason, e.g. not_gated, detector_failopen, zone_parity_unavailable, no_novel_frames, timeout, detector_timeout, detector_error, redecode_error, redaction_error, internal_error.
      - `decision_mix` object: What stage-2a WOULD have concluded: 'would_conclude_benign' or 'defer_to_2b'. Shadow only — nothing acts on it.
    - `notes` string[]: Caveats that belong on the number wherever it is rendered.
  - `policy` SystemHealthPolicy, required: The policy-compute fail-open — a different silent fallback from the detection one in `fail_open`, and the same class of problem: invisible until somebody runs SQL by hand.
    - `window_24h` SystemHealthPolicyWindow, required
      - `version_mix` object: Live ledger rows by policy version — which policy actually decided, in fact rather than by flag state.
      - `fallback_nonzero` integer, required: Live rows where the boundary-flip policy compute failed and silently fell back to the legacy backstop. MUST trend to zero while the flip is on.
    - `notes` string[]: Caveats that belong on the number wherever it is rendered.

---

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