---
title: "Show: every clip around this alarm across chosen cameras, stably paged"
method: GET
path: "/events/{event_id}/show"
tags: ["events"]
---

# Show: every clip around this alarm across chosen cameras, stably paged

`GET /events/{event_id}/show`

## 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}/show`
- Auth: HTTP bearer

The Show scene for one alarm (`event_id` is the anchor): every clip at the anchor's site in a window, open queue alarms and closed context (`reviewed`, `filtered`, `agent_closed`, classified exactly like `GET /events/{id}/around`) merged in ONE oldest-first pass on `(created_at, id)`, so an alarm that closes between pages is returned once. `until=anchor` (default): window = anchor time minus `before_seconds` to plus `after_seconds`; `until=now`: the last `before_seconds` up to the snapshot (`after_seconds` ignored). `camera_id` (repeatable, at most 50, at the anchor's site) narrows the scene; the anchor's camera is always included; absent = every camera at the site. Membership, paging and the error rules mirror `GET /events/open-alarms`: every page bounds clips by creation time (`created_at <= snapshot.as_of`) and by current membership at that page's read (open, or closed context); a clip created at or before `as_of` that only becomes visible or closed after it is returned if its key is still ahead of the cursor; `counts` (`total`, `by_state`, `by_camera`) are page-one observations (`total` and `by_state` repeat unchanged from page one on later pages; `by_camera` is returned on page one only) and the rows returned can differ from them; on `truncated`, `omitted` is the eligible clips after the last returned one at that read (a lower bound when `omitted_capped`). A 200 is always a true statement, anything else is UNKNOWN, never an empty scene. Items carry media REFERENCES only (`media.clip_url_path`, `media.snapshot_path`): no presign, no S3 call, no video. Central staff only; the anchor goes through the same scope check as `/around` (out of scope, demo and unknown are one 404) and every row is tenant-scoped in SQL on every page. Read-only: Show never acquires, claims or marks viewed what it displays. Capability: `alarm_show_read` on `GET /auth/me`.

## Path parameters

- `event_id` string, uuid, required

## Query parameters

- `camera_id` string[], nullable: Narrow to these cameras at the anchor's site (repeatable)
- `before_seconds` integer: Seconds before the anchor (or before the snapshot when until=now)
- `after_seconds` integer: Seconds after the anchor (ignored when until=now)
- `until` 'anchor' | 'now': `anchor`: window around the alarm. `now`: the last `before_seconds` up to the snapshot
- `limit` integer: Rows per page
- `cursor` string, nullable: `next_cursor` from the previous page; absent = a new pass. An invalid cursor is 422 `CURSOR_INVALID`, an expired one 422 `CURSOR_EXPIRED`

## Response `200`

Successful Response

- AlarmShowResponse
  - `status` 'more' | 'complete' | 'truncated', required: `more`: this page is fine and `next_cursor` continues the pass. `complete`: the last page; nothing after it in scope as of `snapshot.as_of`. `truncated`: the pass hit `limits.pass_ceiling`; the eligible rows counted in `omitted` will NOT be returned (the oldest are always the ones returned).
  - `snapshot` PagedSnapshot, required
    - `as_of` string, date-time, required: The snapshot instant, pinned on page 1 and identical on every page of the pass. Only rows created at or before it are returned; a row created later, or one that only becomes visible to the queue after it, is the push stream's and the next pass's (it may still appear if its key is ahead of the cursor). `complete` means complete AS OF this instant.
    - `server_time` string, date-time, required: The database clock when this page was read. Age = server_time - queued_at, no workstation clock.
  - `window` ShowWindow, required
    - `start` string, date-time, required: Window start (on `created_at`), inclusive
    - `end` string, date-time, required: Window end (on `created_at`), inclusive
    - `before_seconds` integer, required: Seconds before the anchor (or before the snapshot when until=now)
    - `after_seconds` integer, required: Seconds after the anchor (ignored when until=now)
    - `until` 'anchor' | 'now', required: `anchor`: window around the alarm. `now`: up to the snapshot
  - `anchor` ShowAnchor, required
    - `event_id` string, required: The alarm the request is anchored on
    - `camera_id` string, required: The anchor's camera, always included in the scope
    - `camera_name` string, required: The anchor camera's label
    - `site_id` string, required: The site the scene is read from
    - `created_at` string, date-time, required: The anchor's alarm time
  - `scope` PagedScope, required
    - `site_id` string, required: The site read
    - `camera_ids` string[], nullable: The cameras read, or null for every camera at the site
    - `kind` 'cameras' | 'site', required: `cameras` when narrowed by `camera_id`, else `site`
  - `items` ShowItem[], required: This page's clips, oldest first
    - `event_id` string, required: The clip's event id: the only identity of an alarm
    - `camera_id` string, required: The camera that recorded the clip
    - `camera_name` string, nullable: The camera's label
    - `zone` string, nullable: The camera zone the motion was in, when known
    - `created_at` string, date-time, required: Clip time; the paging key with `event_id`
    - `occurred_at` string, date-time, nullable: The ingestor-reported motion time, when sent
    - `queued_at` string, date-time, nullable: Null for a clip that never entered the queue (stopped by a gate)
    - `offset_seconds` number, required: created_at minus the anchor's, in seconds
    - `is_anchor` boolean, required: True for the alarm the request is anchored on
    - `state` 'open' | 'reviewed' | 'filtered' | 'agent_closed', required: `open` (in the queue), `reviewed` (an operator closed it), `filtered` (stopped before AI review by a gate), `agent_closed`. The state at the moment this page ran.
    - `disposition` string, nullable: The closing disposition; null while open
    - `closed_at` string, date-time, nullable: When it was closed; null while open
    - `closed_by_operator_id` string, nullable: The closing operator, for a `reviewed` clip
    - `closed_by_name` string, nullable: The closing operator's name, for a `reviewed` clip
    - `summary` string, nullable: The AI summary of the clip, when one exists
    - `claim` object, nullable: The queue row's `claim` payload (`operator_id`, `operator_name`, `claimed_at`, `expires_at`, `expires_in_seconds`) while someone holds the alarm, else null. Own vs foreign: compare `operator_id` with the caller's id. Open rows only.
    - `media` ShowMedia, required
      - `clip_available` boolean, required: False while the clip is not yet attached (an operator-raised alarm)
      - `clip_url_path` string, required: GET this for a fresh presigned clip URL; never fetched by this read
      - `snapshot_path` string, required: GET this for the alarm's picture; never fetched by this read
  - `next_cursor` string, nullable: Opaque; send it back with the same parameters. Null on the last page. An invalid cursor is 422 `CURSOR_INVALID`, an expired one 422 `CURSOR_EXPIRED`
  - `counts` ShowCounts, required
    - `total` integer, required: Every clip in the window created by `as_of`, counted when page 1 was read (rows returned over the pass can differ by clips that became visible or closed mid-pass)
    - `by_state` object, required: Counts for open, reviewed, filtered and agent_closed
    - `by_camera` object, nullable: PAGE 1 ONLY (null on later pages)
  - `limits` PagedLimits, required
    - `page_default` integer, required: Rows per page when `limit` is not sent
    - `page_max` integer, required: Largest `limit` accepted
    - `pass_ceiling` integer, required: Most rows one pass returns; beyond it the last page is `truncated` and `omitted` says how many eligible rows remained
  - `omitted` integer, nullable: Set only when `truncated`: the eligible rows after the last returned key at this read (the page's own filters and keyset), at least this many when `omitted_capped`. A read-time count, not page 1's total minus the rows returned.
  - `omitted_capped` boolean: True when the bounded remainder count hit its cap (10,000): `omitted` is then a lower bound. Always false unless `truncated`.

## Other responses

- `422`: `CURSOR_INVALID` for an invalid cursor (malformed, forged, or not belonging to this request), `CURSOR_EXPIRED` for an expired one (restart from page 1), or `INVALID_PARAMETER`
- `503`: Deadline or database failure (code PAGED_READ_UNAVAILABLE). Retry; never an empty list.

---

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