> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gavai.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Approvals

> Review and action human-in-the-loop approval requests surfaced by agents mid-run.

export const ErrorTable = ({errors}) => <div className="gv-error-table" role="table" aria-label="Errors and fixes">
    <div className="gv-error-table__head" role="row">
      <span className="gv-error-table__col-head" role="columnheader">Error</span>
      <span className="gv-error-table__col-head" role="columnheader">Cause</span>
      <span className="gv-error-table__col-head" role="columnheader">Fix</span>
    </div>
    {errors.map((err, i) => <div className="gv-error-table__row" role="row" key={i}>
        <code className="gv-error-table__code" role="cell">{err.code}</code>
        <div className="gv-error-table__cause" role="cell">{err.cause}</div>
        <div className="gv-error-table__fix" role="cell">{err.fix}</div>
      </div>)}
  </div>;

export const Def = ({term, type, defaultValue, required, children}) => <>
    <dt className="gv-def-list__term">
      <span className="gv-def-list__name">{term}</span>
      {type && <span className="gv-def-list__type">{type}</span>}
      {required && <span className="gv-def-list__required">required</span>}
      {defaultValue !== undefined && <span className="gv-def-list__default">
          default <code>{defaultValue}</code>
        </span>}
    </dt>
    <dd className="gv-def-list__description">{children}</dd>
  </>;

export const DefList = ({children}) => <dl className="gv-def-list">{children}</dl>;

export const ExpectedOutput = ({caption = "Expected output", children}) => <div className="gv-output">
    <div className="gv-output__label">
      <svg className="gv-output__icon" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
        <polyline points="15 10 20 15 15 20" />
        <path d="M4 4v7a4 4 0 0 0 4 4h12" />
      </svg>
      <span>{caption}</span>
    </div>
    <div className="gv-output__body">{children}</div>
  </div>;

export const APIBadge = ({method = "GET", path, scope}) => {
  const m = method.toUpperCase();
  return <span className="gv-api-badge">
      <span className={`gv-api-badge__method gv-api-badge__method--${m.toLowerCase()}`}>
        {m}
      </span>
      <code className="gv-api-badge__path">{path}</code>
      {scope && <span className="gv-api-badge__scope">
          <span className="gv-api-badge__scope-label">scope</span>
          <code>{scope}</code>
        </span>}
    </span>;
};

export const Eyebrow = ({label, tone = "default"}) => <div className={`gv-eyebrow gv-eyebrow--${tone}`}>
    <span className="gv-eyebrow__bar" aria-hidden="true" />
    <span className="gv-eyebrow__label">{label}</span>
  </div>;

<Eyebrow label="RESOURCE" />

When an agent reaches a step that needs human sign-off, it pauses and creates an approval record. Operators review the action and its payload, then approve or deny. The agent resumes or stops based on the decision. By the end of this page you will know which endpoints exist, the status values an approval moves through, and the consequences of denial.

Approval endpoints live at root `/v1/approvals` — they are **not** workspace-scoped in the URL path. A token with `approvals:read` or `approvals:write` can act on records from any workspace the token has access to.

<Note>
  To see which agent produced an approval, use the `agent_id` field on the record and cross-reference [Agents](/api-reference/resources/agents).
</Note>

## An approval in shape

<ExpectedOutput>
  ```json theme={null}
  {
    "id":         "apr_01H...",
    "agent_id":   "agt_01H...",
    "run_id":     "run_01H...",
    "status":     "pending",
    "action":     "send_email",
    "payload":    { "to": "customer@example.com", "subject": "Your invoice" },
    "created_at": "2025-11-02T01:00:10Z"
  }
  ```
</ExpectedOutput>

`action` and `payload` are agent-defined — interpretation is whatever the agent's configuration says they mean.

## Endpoints

<APIBadge method="GET" path="/v1/approvals" scope="approvals:read" />

List pending and historical approval records.

<APIBadge method="GET" path="/v1/approvals/{id}" scope="approvals:read" />

Fetch a single approval record.

<APIBadge method="POST" path="/v1/approvals/{id}/approve" scope="approvals:write" />

Approve the requested action — the run resumes.

<APIBadge method="POST" path="/v1/approvals/{id}/deny" scope="approvals:write" />

Deny the requested action — the run stops.

## Status values

<DefList>
  <Def term="pending">Awaiting an operator decision. The agent run is paused.</Def>
  <Def term="approved">An operator approved. The run resumed.</Def>
  <Def term="denied">An operator denied. The run was stopped permanently at the current step.</Def>
</DefList>

## Filtering and pagination

`GET /v1/approvals` accepts `status` (one of `pending`, `approved`, `denied` — omit for all), `limit` (default 20, max 100), and `cursor`. See [Pagination](/api-reference/pagination) for cursor mechanics.

<Warning>
  Denying an approval stops the run permanently. The agent does not retry the step or continue to later steps. To re-run the task, trigger the agent again after addressing the underlying issue.
</Warning>

## Common errors

<ErrorTable
  errors={[
{ code: "404 not_found", cause: "No approval with that id exists, or it is not accessible to this token.", fix: "Verify the id and that the token can reach the workspace the approval belongs to." },
{ code: "409 already_decided", cause: "The approval was already approved or denied.", fix: "Fetch the approval to see the final decision; the action cannot be reversed." },
]}
/>

## Related

<Card title="Agents" icon="robot" href="/api-reference/resources/agents">
  Manage the agents that produce approval records.
</Card>
