---
title: "Get a tool-approval request"
method: GET
path: "/v1/permission-requests/{permission_request_id}"
tags: ["permission-requests"]
---

# Get a tool-approval request

`GET /v1/permission-requests/{permission_request_id}`

## Request

- Base URL: `https://api.patricia.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.patricia.app/v1/permission-requests/{permission_request_id}`
- Auth: HTTP bearer

Fetch a single approval request by id, scoped to the caller's tenant. Argument values are sanitized and visible only to callers who can decide requests (runs:execute) and are rendered in FULL on this detail view, so an approver can review everything the tool will run with; read-only callers receive a value-free input_summary instead.

## Path parameters

- `permission_request_id` string, uuid, required

## Headers

- `X-Tenant-Id` string, nullable

## Response `200`

Successful Response

- PermissionRequestRow: Row shape for the approval queue. All fields optional so ``fields=`` projection validates (runflow pattern). ``input`` is shaped per caller by the router (``routers/permission_requests.py``), never returned raw: sanitized values for callers holding the approval scope (``runs:execute``), null with ``input_summary`` populated for plain ``runs:read`` callers. The SQL below still selects the stored column; the shaping is response-time.
  - `id` string, uuid, nullable
  - `run_id` string, uuid, nullable
  - `tool_name` string, nullable
  - `risk_tier_code` string, nullable
  - `status_code` string, nullable
  - `can_approve` boolean
  - `can_deny` boolean
  - `dispatch_blocked` boolean: True when the bound account is personal and the run's actor is not its connector, so an approval would be refused. Deliberately separate from can_approve, which keeps its own meaning: whether this caller holds approval authority under the audience policy.
  - `dispatch_block_reason` string, nullable: Machine-readable code naming why dispatch is blocked, or null when it is not.
  - `input` object, nullable: Tool arguments, sanitized. Present only for callers holding runs:execute (the authority that can decide this request); null for read-only callers, which receive input_summary instead. Null with no input_summary means the request carries no stored arguments.
  - `input_summary` ArgSummaryEntry[], nullable: Value-free per-argument summary, populated in place of input for callers without runs:execute.
    - `key` string, required: Argument name (schema-level, never customer data).
    - `type` string, required: JSON type of the hidden value: string, number, boolean, object, array, or null.
    - `size` integer, nullable: Size of the hidden value: characters for a string, item count for an array, key count for an object. Null for other scalars, and always null for a credential-named argument.
  - `repeat_coverage_announced` boolean, nullable
  - `task_offer_manifest` object, nullable
  - `task_offer_manifest_digest` string, nullable
  - `delivery_ref` string, nullable
  - `approver_actor_id` string, uuid, nullable
  - `expires_at` string, date-time, nullable
  - `resolved_at` string, date-time, nullable
  - `created_at` string, date-time, nullable

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden. Inspect response body `code` for the specific reason (for example: PERMISSION_DENIED, EMAIL_NOT_VERIFIED, TENANT_ACCESS_REQUIRED, ROLE_UNRESOLVED)
- `404`: Not found
- `422`: Validation error

---

[API](https://skmtc.dev/patricia/apis/patricia-api.md) · [All operations](https://skmtc.dev/patricia/apis/patricia-api/llms.txt) · [OpenAPI document](https://skmtc.dev/patricia/apis/patricia-api/revisions/0dfb44495ea1?raw)
