---
title: "Get Talk Speakers For Site"
method: GET
path: "/sites/{site_id}/talk-speakers"
tags: ["speakers"]
---

# Get Talk Speakers For Site

`GET /sites/{site_id}/talk-speakers`

## 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/sites/{site_id}/talk-speakers`
- Auth: HTTP bearer

The speaker picker for live voice down - the ONE operator-readable
speaker route.

WHY IT EXISTS. Everything else in this router that lists speakers is
`require_site_admin` (owner or monitoring manager; it was `require_owner`
until the 2026-09-15 decision opened the speaker surface to the monitoring
centre's managers), so before this there was no way for an operator to learn
the id of a speaker they are already permitted to talk through: the three
talk-session routes all take a `speaker_id` the client must already know,
and the event payload carries only a boolean. The picker had no source.

WHY THIS GUARD IS NOT A WIDENING. `ESCALATE_VOICE_DOWN` already lets its
holder MAKE SOUND at this site through `POST /speakers/{id}/talk-sessions`.
Reading the label of the horn they are about to speak through is strictly
less than what they can already do, and the response is a minimal
projection that deliberately excludes every field describing how we reach
the device - see `TalkSpeakerResponse`, which is a disclosure boundary with
the reasoning attached.

## Path parameters

- `site_id` string, required

## Response `200`

Successful Response

- GetTalkSpeakersResponse
  - `speakers` TalkSpeakerResponse[], required: Live speakers at this site, ordered by label. Excludes retired (soft-deleted) speakers; includes disabled and unhealthy ones, flagged.
    - `id` string, uuid, required: The speaker to open a live voice session on.
    - `label` string, required: Display name, as the owner registered it.
    - `map_location_label` string, nullable: Operator-facing prose for where this speaker physically is. The field an operator actually chooses by when a site has several.
    - `enabled` boolean, required: Whether delivery and the health poll consider this speaker. A disabled speaker is returned rather than hidden so the UI can show it as unavailable - a horn that silently vanishes from the list reads as a broken console.
    - `healthy` boolean, nullable: Has a health poll confirmed this speaker? The column defaults to false, so a never-polled speaker reads false rather than null - this does NOT distinguish 'polled and failed' from 'never polled', and UI copy must not imply that it does. Advisory in either case: a healthy speaker can still refuse the stream and an unhealthy one may work, so this greys a choice rather than removing it.
    - `health_state` 'healthy' | 'unhealthy' | 'unknown': 'unhealthy' = the last health check failed; 'healthy' = it passed; 'unknown' = never checked, disabled (the poll skips a disabled speaker, so its stored verdict is stale) or no verdict. Unknown is not down: do not warn on it.
    - `unhealthy_since` string, date-time, nullable: The time of the first recorded failed check in this episode; the device may have failed earlier. Only set while health_state is 'unhealthy'. Null while unhealthy means down since before this was tracked.
    - `camera_ids` string[]: The live (non-retired), same-site cameras this speaker covers. Use camera_priorities, not positions in this list, to compare speakers for a camera. Empty means no camera mappings; it can still be talked through from the review panel's site picker.
    - `camera_priorities` object: Camera ID to this speaker's configured priority for that camera. Lower wins (0 is primary). Keys match camera_ids; list positions cannot express relative priority between different speakers.

## Other responses

- `422`: Validation Error

## Changes

- **2026-11-03** `00252d8227c1`: 2 info
  - added the optional property `speakers/items/health_state` to the response with the `200` status
  - added the optional property `speakers/items/unhealthy_since` to the response with the `200` status

[Operation history](https://skmtc.dev/verdun/apis/verdun-api/changes/sites/:site_id/talk-speakers/get.md)

---

[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/a19366be50a3?raw)
