---
title: "Create External Talkdown"
method: POST
path: "/events/{event_id}/external-talkdowns"
tags: ["external-talkdowns"]
---

# Create External Talkdown

`POST /events/{event_id}/external-talkdowns`

## 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/events/{event_id}/external-talkdowns`
- Auth: HTTP bearer

Open the audit row for one talk-down attempt.

Idempotent on `(operator, client_ref)`: a retry returns the existing row
with a 200, indistinguishable from the first write. NO ACTIVITY-LOG ENTRY
here — `requested` only records that a button was pressed, and the row
itself already says so.

## Path parameters

- `event_id` string, required

## Request body

- CreateExternalTalkdownRequest: Open the audit row for ONE talk-down attempt through a vendor console. THERE IS NO TIMESTAMP FIELD HERE, AND NO STATUS FIELD. A new row is always `requested`, and `requested_at` is the SERVER's clock — the browser that sends this is the one piece of the system whose clock nobody controls, and "when did an operator make sound at a customer site" is exactly the kind of fact that must not be client-assertable. THERE IS NO `event_id` IN THE BODY either: it is the path segment, so the two can never disagree. UNKNOWN KEYS ARE REJECTED rather than ignored. A client that sends `connected_at` or `status` has misunderstood the contract, and silently dropping the field would let it believe the value landed. That is the whole reason for `extra="forbid"` on a request model in a repo that mostly does not use it.
  - `provider` 'verkada_command', required
  - `mode` 'mic' | 'clip', required
  - `client_ref` string, required: The extension's per-attempt id, minted once per click. THE IDEMPOTENCY KEY: re-sending this request with the same value returns the existing row rather than opening a second one. Reusing one across two different events is a client bug and is refused with 409.

## Response `200`

Successful Response

- ExternalTalkdownResponse: One talk-down attempt through a vendor console. THERE IS NO `announced_at` AND THERE MUST NEVER BE ONE. A vendor console reports that the CALL came up, never that audio was delivered; `agent_actions.announced_at` means positively-verified playback and is what a quiet auto-dismissal rests on. `status = connected` is the strongest honest fact this path has.
  - `id` string, uuid, required: The talk-down record id.
  - `event_metadata_id` string, uuid, required: The alarm this was about.
  - `camera_id` string, uuid, required: The camera whose vendor console was driven.
  - `parent_id` string, uuid, required: The client, denormalised so a tenant-scoped read needs no join.
  - `site_id` string, uuid, required: The site, denormalised for the same reason.
  - `operator_id` string, uuid, nullable: Who talked. Null once that account has been deleted — the record outlives it.
  - `provider` 'verkada_command', required
  - `mode` 'mic' | 'clip', required
  - `status` 'requested' | 'connected' | 'ended' | 'failed', required
  - `fail_reason` 'timeout' | 'not_logged_in' | 'phone_not_found' | 'busy' | 'extension_error'
  - `client_ref` string, required: The extension's per-attempt id; the idempotency key this row was created under.
  - `requested_at` string, date-time, required: When the operator pressed the button, on the SERVER's clock.
  - `connected_at` string, date-time, nullable: When the vendor console reported the call up. Null if it never did.
  - `ended_at` string, date-time, nullable: When the attempt reached a terminal state.
  - `duration_ms` integer, nullable: connected_at to ended_at in milliseconds. Null when the call never connected — which is the honest answer, not zero.
  - `detail` string, nullable: Free-text attempt trail. Never a URL or a token.
  - `created_at` string, date-time, nullable: Row creation timestamp.
  - `updated_at` string, date-time, nullable: Row update timestamp.

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