---
title: "List pending approvals (WCP plane)"
method: GET
path: "/api/v1/workflows/approvals/pending"
tags: ["Workflow Control Plane"]
---

# List pending approvals (WCP plane)

`GET /api/v1/workflows/approvals/pending`

## Request

- Base URL: `https://orchestrator.getaxonflow.com`
- URL: `https://orchestrator.getaxonflow.com/api/v1/workflows/approvals/pending`
- Auth: none declared
- TypeScript: <https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api/docs/api/v1/workflows/approvals/pending/get.ts> (a function with typed inputs; its response is checked against the schema)

List workflow steps currently awaiting human approval for the caller's
tenant (all planes). Cross-reference the MAP-plane equivalent at
`/api/v1/plans/approvals/pending`, which scopes to MAP-backed
workflows and populates `plan_id` on every entry.

Reachable on Evaluation and above. Listing is a read over entries that
already exist, so it follows the resolve rule rather than the creation
entitlement: CREATING an approval entry requires Professional,
Enterprise or Enterprise Plus, but a deployment that already holds
entries can always list, approve and reject them. Community has no
approval queue to list.

**A tier that may not list gets `404`, not `403`.** This route is
REGISTERED conditionally (`RegisterEnterpriseRoutes`, or the community
branch gated on the resolve entitlement), so on a deployment that is
not entitled the path is not on the router at all. The `403` below is
therefore NOT a tier refusal — it described one until issue #3948, and
that description was of a status this operation cannot produce for that
reason. It is the agent-gateway proxy-auth refusal, which this handler
raises itself, before it looks at tenancy.

Every refusal THIS HANDLER produces carries the triplet
`{error, code, message}` envelope — this plane's writer. Its MAP
counterpart uses the flat envelope throughout for the same reason in
reverse, and the two are documented as they are rather than converged,
because converging either is a wire change on that plane.

One refusal a client can receive is NOT this handler's and is not the
triplet: a request that does not reach the orchestrator through the
agent gateway is stopped by the deployment-wide internal-service gate
before any route matches, and that answers the FLAT envelope. It
applies identically to every operation in this document and is
therefore described here rather than repeated on each one.

## Query parameters

- `limit` integer

## Response `200`

List of pending approvals

- PendingApprovalsResponse: List of pending approvals across workflows for the caller's tenant.
  - `pending_approvals` PendingApproval[]
    - `workflow_id` string: WCP workflow identifier.
    - `workflow_name` string: Human-readable workflow name.
    - `plan_id` string: MAP plan identifier. Populated on the MAP-plane listing (`/api/v1/plans/approvals/pending`); omitted (omitempty) on the WCP-plane listing.
    - `step_id` string: Step awaiting approval.
    - `step_index` integer: Zero-based index of the step within the workflow.
    - `step_name` string: Human-readable step name.
    - `step_type` 'llm_call' | 'tool_call' | 'connector_call' | 'human_task' | 'synthesis' | 'action' | 'gate': Type of step operation.
    - `decision` 'allow' | 'block' | 'require_approval': Gate decision that paused the step — always `require_approval` for pending entries.
    - `decision_reason` string: Why approval is required.
    - `policies_matched` object[]: Policies that triggered the approval requirement.
    - `step_input` object: Step input payload (may be redacted by PII rules).
    - `approval_status` 'pending' | 'approved' | 'rejected': Current approval state — `pending` for listed entries.
    - `created_at` string, date-time: Time of the first /gate call that paused the step.
  - `count` integer: Total number of pending approvals matching the scope.

## Other responses

- `401`: Missing tenant or org identity. BOTH `X-Org-ID` and `X-Tenant-ID` must be present and neither may be the unowned-row sentinel; they are stamped by the AxonFlow Agent gateway or the customer-portal proxy from a validated credential, never supplied by the client. This was documented as `400` and has always been `401`. The refusal does not depend on the resource — the handler binds the caller scope before it looks at any workflow — so `401` is correct and `400` never described it. The MAP counterpart now answers `401` here too; it previously read `X-Tenant-ID` raw and answered `400`, which is the mismatch issue #3948 records. Note the ORDER: the proxy-auth gate below runs BEFORE this one, so a request that is both unproxied and unbound is answered `403`.
- `403`: The request did not arrive through the AxonFlow Agent gateway. Raised by this handler's own proxy-auth gate, which runs BEFORE the tenancy bind, so it is reachable independently of `401`. It is NOT a tier refusal: this route is registered conditionally, so an unentitled deployment answers `404` (see the description above).

---

[API](https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api.md) - [All operations](https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api/llms.txt) - [OpenAPI document](https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api/revisions/f408ef3ec9dd?raw)
