# Approvals An approval is an object, not a dialog box. When a [Worker](https://orkestr.eu/docs/workers) proposes an action it is not trusted to take alone - a deploy, a rollback, opening a pull request - the action does not run. An approval is created and waits for a human. You can list approvals, read one, and approve or deny it over the API, the console, or a Slack button. > **Why this is a resource** > > If approving is a popup, the only thing that can approve is a person looking at a screen. Making it an addressable object means the queue is inspectable, decisions are auditable after the fact, and the outcome of an approved action is something you can read back. ## Lifecycle - `pending` - proposed and waiting. The action has **not** run. - `deciding` - briefly claimed while a decision is carried out. Two concurrent decisions (a Slack click and a console click) cannot both execute the action; the second one sees the row already claimed. - `approved` - the action ran. Read `result` for what it returned, or `error` if the tool itself failed. A failed tool is still an approved decision: you said yes, and the attempt is on the record. - `denied` - the action never ran, and any unattended run that was waiting on it ends. ## Endpoints ```bash GET /api/approvals # all states, newest first GET /api/approvals?status=pending # just what needs you GET /api/approvals?worker_id= # one worker's proposals GET /api/approvals/{request_id} # one approval, any state POST /api/approvals/{request_id}/approve # run it POST /api/approvals/{request_id}/deny # discard it ``` ## What an approval looks like ```json { "request_id": "9f3c1e...", "status": "pending", "worker_name": "pr-reviewer", "worker_role": "deploy_proposer", "run_id": "4a1b...", "tool": "deploy", "args": { "project": "api", "env_vars": "***redacted***" }, "requested_at": "2026-07-26T09:14:02Z", "decided_at": null, "result": null, "error": null } ``` Arguments are shown redacted. The full arguments are stored encrypted and never leave the server - they exist only so the action can actually run once you approve. An approval card is something an agent can influence the contents of, so it is never a place secrets are printed. ## Who can approve Deciding requires a signed-in session. API tokens cannot approve - including, especially, a Worker's own token, since a worker approving its own proposal would defeat the gate entirely. An agent can *see* that its action is pending (it gets a pending result back, and can poll it) but it can never resolve it. By default only the worker's owner can approve. A worker set to `channel` approver policy can also be approved by anyone in its report channel from a Slack button - useful for a team on call, and a deliberate loosening you opt into per worker. ## Attribution An approved action is recorded as the **worker's** action, not yours. Your decision is recorded separately, on the approval itself. The activity log shows the worker that proposed the action and the policy role it acted under, so "a worker deployed this, and a human allowed it" stays two distinct facts rather than collapsing into one. > **Kill switch interaction** > > Pausing a worker, or killing agents account-wide, blocks approving its queued actions - otherwise the most dangerous residue a misbehaving agent leaves behind (an action already sitting in the queue) would still be firable after you hit the panic button. Denying stays available, so you can always clear the queue.