---
title: "Undo your own site-story Close all"
method: POST
path: "/eval/operator/bulk/undo"
tags: ["eval"]
---

# Undo your own site-story Close all

`POST /eval/operator/bulk/undo`

## 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/eval/operator/bulk/undo`
- Auth: HTTP bearer

Takes back the caller's own bulk false-alarm / non-threatening closes (the `disposed` ids of `POST /eval/operator/bulk`), up to 1,000 ids per request. The window is 10 s + a 2 s latency allowance from the caller's NEWEST own bulk false-alarm / non-threatening close anywhere (not just among the requested ids), measured on the database clock and judged once at request start. Each requested row must also be the caller's own bulk false-alarm / non-threatening close and no more than 90 s old; an older row is never undone. Each event is reopened in its own transaction: the evaluation and any training sample captured from it are deleted and the alarm returns to the queue UNCLAIMED. Ids that stay closed come back in `failed` with a `code` (`not_found`, `not_closed` = already open, `forbidden`, `not_yours`, `not_undoable` = not a bulk false-alarm/non-threatening close, `audited`, `too_late`, `error`); the rest still reopen. 403 for the whole request when the caller lacks the review_label_alarms permission. A single-alarm close is undone on `POST /eval/operator/{event_id}/undo`, which still refuses bulk rows.

## Request body

- BulkUndoOperatorEvalRequest
  - `event_ids` string[], required: The events a site-story "Close all" just closed (the `disposed` ids the bulk close returned), up to 1,000 per request (the close takes 500). Duplicates are collapsed. Each event is reopened in its own transaction, so some can be refused while the rest still come back.
  - `surface` 'site_bulk' | 'camera_bulk' | 'rail_bulk': Which console surface sent a bulk close (`POST /eval/operator/bulk`). Written, verbatim, as the claim_log `surface` of every line of that call and nothing else. `site_bulk` (By site, Close all) is the default when the client sends nothing; the single-event close is always `single` and never uses this enum.
  - `closes` string, nullable: The `request_id` the bulk close answered with, echoed back so the claim log can tie this undo to that close. Log correlation only: it is never read for authority.

## Response `200`

Successful Response

- BulkUndoOperatorEvalResponse
  - `reopened` string[], required: Event ids that are open again, in request order. The alarms come back UNCLAIMED: the story holds no claims, and claiming hundreds of alarms would lock out teammates.
  - `failed` BulkUndoOperatorEvalFailure[], required: Event ids that stayed closed, each with the reason, in request order
    - `event_id` string, required: The event that was NOT reopened
    - `status` integer, required: The status the single-event route would use: 404 unknown / hidden / not closed, 403 out of scope or not the caller's close, 409 not undoable, audited or too late.
    - `code` string, required: Machine code: `not_found`, `not_closed` (it is already open: a second click, or a retry after a lost answer), `forbidden`, `not_yours`, `not_undoable` (not a bulk false-alarm / non-threatening close), `audited`, `too_late`, `error`.
    - `reason` string, required: Why, in the single-event undo route's words
  - `request_id` string, required: This call's id: the `request=` value on its claim_log lines

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