# List approvals visible to the caller

GET

/v1/approvals

```sh
curl --request GET \
  --url 'https://example.com/v1/approvals?limit=25&scopeKind=tenant&assignedTo=me&decidedBy=me&order=asc&requiredRole=standard' \
  --header 'Authorization: Bearer <token>'
```

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.

## Authorizations

- **[bearerAuth](https://docs.kindgi.com/v0.1.10/reference/api.md#bearerauth)**

## Parameters

### Query Parameters

**limit**

integer

default: 25 >= 1 <= 100

1..100. Default 25.

**cursor**

string

Where the previous page ended: its `nextCursor`, as it came. A runtime that seals cursors takes one only for the same list, filters and caller, within a day; otherwise `400 bad-input`, and the list starts again without it. Absent → first page.

**scopeKind**

Discriminator for the ?scopeKind + ?scopeId + ?inherit triplet. Tenant carries no id (implicit from session); org/project require scopeId.

string

Allowed values: tenant org project

Optional scope discriminator. If absent, no scope filter is applied.

**scopeId**

string

\>= 1 characters

Required IF scopeKind is `org` or `project`. MUST be absent if scopeKind=`tenant` (tenant is implicit from the session). Malformed combinations return 400 scope-invalid.

**status**

Array\<string>

Allowed values: pending assigned in_review approved rejected escalated expired withdrawn

Only approvals in these statuses: one, or several, repeated (`status=pending&status=escalated`) or comma-separated (`status=pending,assigned,in_review`).

**assignedTo**

string

Allowed values: me

`me`: only the approvals assigned to the caller’s own reviewer row (none when the caller has no row).

**decidedBy**

string

Allowed values: me

`me`: only the approvals the caller’s own reviewer row decided (none when the caller has no row).

**order**

string

default: desc

Allowed values: asc desc

`desc` (newest first, the default) or `asc` (oldest first). A page’s `nextCursor` continues its own order; the page says which order it’s in (`order`).

**requiredRole**

Reviewer role class. Hierarchy: standard < senior < admin.

string

Allowed values: standard senior admin

Filter by required reviewer role. Caller must have a rank ≥ the value — else 403.

**createdAfter**

string format: date-time

ISO 8601 timestamp; return approvals created strictly after this.

**waitTokenId**

Array\<string>

<= 50 items

Only approvals linked to one of these run waits (an approval’s `waitTokenId`; a run’s journal names its open waits in `wait.suspended` entries). Repeat it for several, at most 50.

**runId**

string format: uuid

Only the approvals this run asked for.

**includeDescendants**

boolean

With `runId`: also the approvals its child runs asked for, at any depth (a flow’s agent steps).

## Responses

### 200

Page of approvals.

application/json

object

**data**

required

Array\<object>

object

**id**

required

string format: uuid

**tenantId**

required

string format: uuid

**projectId**

string format: uuid

**subjectKind**

required

string

**subjectRef**

required

object

**_key_**

additional properties

any

**requiredRole**

required

Reviewer role class. Hierarchy: standard < senior < admin.

string

Allowed values: standard senior admin

**status**

required

string

Allowed values: pending assigned in_review approved rejected escalated expired withdrawn

**assignedTo**

string format: uuid

**batchKey**

string

**title**

string

**description**

string

**context**

object

**_key_**

additional properties

any

**provenanceRef**

object

**runId**

required

string format: uuid

**provenanceId**

string format: uuid

**waitTokenId**

string

**createdAt**

required

string format: date-time

**updatedAt**

required

string format: date-time

**decidedAt**

string format: date-time

**expiresAt**

string format: date-time

**decision**

The reviewer’s decision, once one is recorded. Absent while the approval is open, and when it ended without one (it expired, a timeout escalated it, or its run’s end withdrew it).

object

**decision**

required

string

Allowed values: approve reject escalate withdraw

**decidedBy**

Who decided, as an actor: `user:<userId>`, the reviewer’s user. The run’s journal and provenance name the decider the same way. The Kindgi runtime always records it; a deployment whose HITL binding doesn’t leaves it out.

string

**reviewerId**

required

string format: uuid

**reviewerRoleAtDecision**

required

Reviewer role class. Hierarchy: standard < senior < admin.

string

Allowed values: standard senior admin

**decidedAt**

required

string format: date-time

**rationale**

string

**sessionProvider**

The provider of the session the reviewer decided with: `site:<id>` for a site’s sign-in, an identity provider’s id for a single sign-on session. Absent for an API key, and on decisions an older runtime recorded.

string

**deciderName**

The reviewer’s display name when they decided: a person renamed since still shows as they were. Absent on decisions an older runtime recorded.

string

**requestedBy**

Who asked for it, when recorded: `user:<id>`, `service_account:<id>` or `system:<what>`.

string

**separateApprover**

Whether the person who asked may not approve it (four eyes). A runtime that knows it always sends it, `false` included.

boolean

**withdrawnBecause**

Why it was withdrawn, when its run’s end withdrew it (a reviewer’s withdrawal has its `decision` instead).

string

Allowed values: run-cancelled run-ended

**escalatedFrom**

The approval this one was escalated from.

string format: uuid

**escalatedTo**

The approval this one was escalated to.

string format: uuid

**nextCursor**

Opaque cursor for the next page, in the same order; treat as opaque on the client.

string

**hasMore**

required

boolean

**order**

The order the page is in: `asc` (oldest first) or `desc` (newest first). Absent from a runtime before Kindgi 0.1.6, which lists newest first and ignores `order`.

string

Allowed values: asc desc

**decidedBy**

`me` on every page of a list asked for with `?decidedBy=me`, an empty one too: it holds only the approvals the caller decided. Absent from a runtime before Kindgi 0.1.9, which ignores `decidedBy` and lists them all.

string

Allowed values: me

##### Example

```json
{
  "data": [
    {
      "requiredRole": "standard",
      "status": "pending",
      "decision": {
        "decision": "approve",
        "reviewerRoleAtDecision": "standard"
      },
      "withdrawnBecause": "run-cancelled"
    }
  ],
  "order": "asc",
  "decidedBy": "me"
}
```

### 400

Malformed query parameter or scope.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 401

Missing / malformed / expired / revoked bearer token.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 403

The caller isn’t a reviewer or the tenant’s admin, or asked for a tier above its own and isn’t the tenant’s admin.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

## See also

- [Approvals reference](https://docs.kindgi.com/v0.1.10/guides/approvals/approvals-reference.md)
- [Kindgi 0.1.9](https://docs.kindgi.com/v0.1.10/releases/0.1.9.md)
- [Let a store's staff ask and approve in WordPress](https://docs.kindgi.com/v0.1.10/sites/wordpress.md)
- [Every error code](https://docs.kindgi.com/v0.1.10/reference/errors.md)
