# Approvals

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/http-api/approvals/
> Summary: The approvals endpoints of the Tracon HTTP API — 3 operations.

3 operations. `{prefix}` is the route prefix passed to
`MapTracon`; the template uses `/tracon`.

## GET {prefix}/api/approvals/{id}

**Operation ID:** `TraconGetPendingApproval`

**Returns a single pending approval request.**

Unlike the list, this reads a request in any state, so it is how a client polls the outcome after deciding: the response then carries who decided, when, and which way. The request holds the tool call's arguments as recorded, which is what an approver reviews before deciding. An unknown id returns 404, and so does a denial by a registered IRunAuthorizationHandler.

**Authorization:** bearer authentication; `Operator` role policy when that policy is registered; `RunsRead` API-key scope.

| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
| `id` | path | yes | `string (uuid)` | — |

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → [`PendingApproval`](/http-api/schemas/pendingapproval/) | — |

## POST {prefix}/api/approvals/{id}/decide

**Operation ID:** `TraconDecideApproval`

**Decides a pending approval request.**

The decision enqueues a NEW run (same sessionId, new RunId); the old run stays AwaitingApproval. Do not start that run yourself. Repeating the SAME decision is safe and returns 200: the continuation run's identity is derived from the approval, so a repeat finishes a handoff that failed partway instead of creating a second run. A second decision asking for the OPPOSITE answer gets 409. If a registered IRunAuthorizationHandler denies the caller, the response is 404, identical to an approval request that does not exist — the 409 is never reached, so a denial cannot reveal that the request was already decided.

**Authorization:** bearer authentication; `Operator` role policy when that policy is registered; `RunsWrite` API-key scope.

| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
| `id` | path | yes | `string (uuid)` | — |

**Request body** (required):

- `application/json` → [`ApprovalDecisionRequest`](/http-api/schemas/approvaldecisionrequest/)

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → [`PendingApproval`](/http-api/schemas/pendingapproval/) | — |

## GET {prefix}/api/approvals/pending

**Operation ID:** `TraconListPendingApprovals`

**Lists the tenant's pending approval requests.**

Only requests still awaiting a decision are returned; a decided request leaves the list and stays readable by id. A request appears here when a queued run ('Prefer: respond-async') stops on a tool call that needs approval — a run driven synchronously carries its approval in the response stream instead and never reaches this mailbox. Each entry carries an expiry, which is an absolute point in the future rather than an elapsed duration. If a registered IRunAuthorizationHandler denies the caller, the response is 403 — the list is REJECTED, never silently filtered.

**Authorization:** bearer authentication; `Operator` role policy when that policy is registered; `RunsRead` API-key scope.

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → array of [`PendingApproval`](/http-api/schemas/pendingapproval/) | — |
| **403** Forbidden | `application/problem+json` → [`ProblemDetails`](/http-api/schemas/problemdetails/) | — |
