# client.approvals

> client.approvals — the approvals operations.

`client.approvals` — the `approvals` operations.

On `AsyncKindgi` every method is the same, awaited.

## `client.approvals.list()`

```python signature
list(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    scope_kind: Literal['tenant', 'org', 'project'] | None = None,
    scope_id: str | UUID | None = None,
    status: Literal['pending', 'assigned', 'in_review', 'approved', 'rejected', 'escalated', 'expired', 'withdrawn'] | list[Literal['pending', 'assigned', 'in_review', 'approved', 'rejected', 'escalated', 'expired', 'withdrawn']] | None = None,
    assigned_to: Literal['me'] | None = None,
    decided_by: Literal['me'] | None = None,
    order: Literal['asc', 'desc'] | None = None,
    required_role: Literal['standard', 'senior', 'admin'] | None = None,
    created_after: str | None = None,
    wait_token_id: str | UUID | list[str | UUID] | None = None,
    run_id: str | UUID | None = None,
    include_descendants: bool | None = None,
    timeout: float | None = None,
) -> ApprovalCollectionPage
```

List approvals visible to the caller. `GET /v1/approvals`

Requires a reviewer: a token that carries a `reviewerRole`, or whose user is a registered reviewer (the roster gives the role). With authorization on, a person who is the tenant's admin (through a session or an `admin` key not limited to a project) reads at every tier: with no roster entry, as an `admin` reviewer; with a lower role, their own tier, and any tier they ask for with `requiredRole`. The roster doesn't show such a reader, but the access audit records the tenant-admin check (`authz-decision`), made only where it changes what the roster gives. Role-scoped: reviewers only see approvals whose `requiredRole` rank ≤ their rank (standard < senior < admin). With authorization on, only approvals whose project the caller may read. `scopeKind`/`scopeId` narrow to one project's approvals, or every project's in an org; approvals from before Kindgi 0.1.3 have no project and are listed only without a scope.

## `client.approvals.get()`

```python signature
get(approval_id: str | UUID, /, *, timeout: float | None = None) -> Approval
```

Fetch a single approval. `GET /v1/approvals/{approvalId}`

Requires a reviewer, or (with authorization on) a person who is the tenant's admin, as the list does; the tenant's admin reads an approval of any tier. Returns 404 for ids that exist but require a higher role than the caller (avoids cross-tier existence leaks — see API-ROUTE-CONVENTIONS.md §2.4), or that are in a project the caller may not read. A decided approval carries its `decision`: what the reviewer decided, why, and who (`decidedBy`, `user:<userId>`).

## `client.approvals.complete()`

```python signature
complete(
    approval_id: str | UUID,
    body: CompleteApprovalBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> CompleteApprovalResult
```

Submit a decision on an approval. `POST /v1/approvals/{approvalId}/complete`

Records the decision (`HitlBinding.submitReview`). When the approval carries a `waitTokenId` and the decision is `approve` or `reject`, also completes the waitpoint so the suspended run resumes, with `{ decided, rationale?, decidedBy, approvalId }`: the run's journal records who decided which approval (`decidedBy` is `user:<userId>`).

## `client.approvals.audit_bundle()`

```python signature
audit_bundle(
    approval_id: str | UUID,
    body: ExportAuditBundleBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> ExportAuditBundleResult
```

Export a signed audit bundle for a decided approval. `POST /v1/approvals/{approvalId}/audit-bundle`

Signs the approval, its decision and its evidence with the deployment's export key, and records the export (an `export-signed` audit event). The same envelope as the other signed exports, so one verifier reads all three; check `publicKey` against `GET /v1/export-signing-keys`. For a decided approval only (approved, rejected, escalated, expired, withdrawn): a pending one is `409 approval-not-decided`. A deployment with no export key answers `404 signing-not-configured`.
