# List listed apps waiting for review

> The platform.app_reviews.list operation: GET /api/v1/platform/app_reviews in the REST API and the platform_app_reviews_list tool in the MCP server.

The listed-app review queue (spec §41.3): apps whose publishers applied to list them for every organization
(`pending`), oldest submission first, so the queue is worked in order. Each entry has the application
(publisher identity, privacy policy, questionnaire answers, scope justifications), the scopes already approved
(an approved app that added scopes is re-reviewed for those) and the owning organization.
`status` lists `changes_requested`, `approved` or `rejected` apps instead, latest decision first. Decide with
`platform.app_reviews.decide`. Platform admins only.

## At a glance

- **REST:** `GET /api/v1/platform/app_reviews`
- **MCP tool:** `platform_app_reviews_list`
- **Operation ID:** `platform.app_reviews.list`
- **Scope:** Platform
- **Permission:** `platform:write`
- **Risk tier:** `read`
- **Dry run:** Not supported
- **Idempotency:** Not needed (read only)
- **Modes:** Test and live
- **Pagination:** `limit` (at most 100) and `starting_after`
- **Authentication:** API key with the `platform:write` scope
- **Since:** M13

## Request

### Query parameters

| Field            | Type                                                          | Required | Description                                                                     |
| ---------------- | ------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------- |
| `status`         | one of `pending`, `changes_requested`, `approved`, `rejected` | No       | Which apps: `pending` (default), `changes_requested`, `approved` or `rejected`. |
| `limit`          | integer (1 to 100)                                            | No       | Page size, 1 to 100 (default 10).                                               |
| `starting_after` | `ocl_…` ID                                                    | No       | The `next_cursor` of the previous page.                                         |

## Response

`200 OK` with a JSON object, a page of the list (newest first):

| Field                      | Type                                                                                                                         | Description |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `object`                   | `"list"`                                                                                                                     |             |
| `data`                     | array of object                                                                                                              |             |
| `data[].id`                | `ocl_…` ID                                                                                                                   |             |
| `data[].object`            | `"app_listing"`                                                                                                              |             |
| `data[].ownerOrgId`        | `org_…` ID                                                                                                                   |             |
| `data[].name`              | string                                                                                                                       |             |
| `data[].publisher`         | string                                                                                                                       |             |
| `data[].visibility`        | one of `private`, `listed`                                                                                                   |             |
| `data[].appStatus`         | one of `active`, `disabled`                                                                                                  |             |
| `data[].status`            | one of `not_submitted`, `pending`, `changes_requested`, `approved`, `rejected`                                               |             |
| `data[].listed`            | boolean                                                                                                                      |             |
| `data[].scopes`            | array of one of 84 values, e.g. `org:read`, `org:write`, `org:admin` (all in the OpenAPI document)                           |             |
| `data[].approvedScopes`    | array of one of 84 values, e.g. `org:read`, `org:write`, `org:admin` (all in the OpenAPI document) or null                   |             |
| `data[].pendingScopes`     | array of one of 84 values, e.g. `org:read`, `org:write`, `org:admin` (all in the OpenAPI document)                           |             |
| `data[].submittedAt`       | date-time or null                                                                                                            |             |
| `data[].decidedAt`         | date-time or null                                                                                                            |             |
| `data[].reason`            | string or null                                                                                                               |             |
| `data[].application`       | object or null                                                                                                               |             |
| `data[].history`           | array of object                                                                                                              |             |
| `data[].history[].action`  | one of `submitted`, `withdrawn`, `approved`, `rejected`, `changes_requested`, `scopes_added`, `identity_changed`, `unlisted` |             |
| `data[].history[].at`      | date-time                                                                                                                    |             |
| `data[].history[].by`      | string or null                                                                                                               |             |
| `data[].history[].reason`  | string or null                                                                                                               |             |
| `data[].history[].scopes`  | array of one of 84 values, e.g. `org:read`, `org:write`, `org:admin` (all in the OpenAPI document)                           |             |
| `data[].version`           | integer                                                                                                                      |             |
| `data[].org`               | object                                                                                                                       |             |
| `data[].org.id`            | `org_…` ID                                                                                                                   |             |
| `data[].org.slug`          | string                                                                                                                       |             |
| `data[].org.name`          | string                                                                                                                       |             |
| `data[].checklist`         | object or null                                                                                                               |             |
| `data[].redirectUris`      | array of string                                                                                                              |             |
| `data[].websiteUrl`        | string or null                                                                                                               |             |
| `data[].logoUrl`           | string or null                                                                                                               |             |
| `data[].unjustifiedScopes` | array of one of 84 values, e.g. `org:read`, `org:write`, `org:admin` (all in the OpenAPI document)                           |             |
| `has_more`                 | boolean                                                                                                                      |             |
| `next_cursor`              | string or null                                                                                                               |             |

## Examples

### The queue

```http
GET /api/v1/platform/app_reviews
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "list",
  "data": [
    {
      "id": "ocl_01m4ttwd3veh9apbewxheq5xha",
      "object": "app_listing",
      "ownerOrgId": "org_01m4ttwd3veh9apbewxheq5xhb",
      "name": "Ledgerly AI",
      "publisher": "Ledgerly AI B.V.",
      "visibility": "listed",
      "appStatus": "active",
      "status": "pending",
      "listed": false,
      "scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write", "ledger:read"],
      "approvedScopes": null,
      "pendingScopes": ["filings:read", "filings:write", "tasks:read", "tasks:write", "ledger:read"],
      "submittedAt": "2026-10-30T09:00:00.000Z",
      "decidedAt": null,
      "reason": null,
      "application": {
        "publisher": {
          "legalName": "Ledgerly AI B.V.",
          "country": "NL",
          "websiteUrl": "https://ledgerly.example",
          "contact": {
            "name": "Mira de Vries",
            "email": "partners@ledgerly.example"
          }
        },
        "privacyPolicyUrl": "https://ledgerly.example/privacy",
        "questionnaire": {
          "version": 1,
          "answers": [
            {
              "questionId": "data_location",
              "answer": null,
              "details": "AWS eu-central-1 (Frankfurt), Germany"
            },
            {
              "questionId": "encryption_in_transit",
              "answer": "yes",
              "details": null
            },
            {
              "questionId": "encryption_at_rest",
              "answer": "yes",
              "details": null
            },
            {
              "questionId": "credential_storage",
              "answer": "yes",
              "details": null
            },
            {
              "questionId": "staff_access",
              "answer": "yes",
              "details": null
            },
            {
              "questionId": "incident_response",
              "answer": "yes",
              "details": null
            },
            {
              "questionId": "subprocessors",
              "answer": "yes",
              "details": "AWS (hosting), Postmark (email)"
            },
            {
              "questionId": "model_training",
              "answer": "no",
              "details": null
            },
            {
              "questionId": "data_deletion",
              "answer": "yes",
              "details": "Within 30 days of uninstalling"
            },
            {
              "questionId": "vulnerability_management",
              "answer": "yes",
              "details": null
            }
          ]
        },
        "scopeJustifications": [
          {
            "scope": "filings:read",
            "justification": "Reads filing periods to prepare each return."
          },
          {
            "scope": "filings:write",
            "justification": "Records the prepared return and its submission."
          },
          {
            "scope": "tasks:read",
            "justification": "Finds the filing tasks assigned to the app."
          },
          {
            "scope": "tasks:write",
            "justification": "Claims and completes filing tasks."
          },
          {
            "scope": "ledger:read",
            "justification": "Reconciles the return with the tax payable accounts."
          }
        ],
        "partnerTermsVersion": "1.0",
        "submittedBy": "usr_01m4ttwd3veh9apbewxheq5xhf"
      },
      "history": [
        {
          "action": "submitted",
          "at": "2026-10-30T09:00:00.000Z",
          "by": "usr_01m4ttwd3veh9apbewxheq5xhf",
          "reason": null,
          "scopes": []
        }
      ],
      "version": 3,
      "org": {
        "id": "org_01m4ttwd3veh9apbewxheq5xhb",
        "slug": "ledgerly",
        "name": "Ledgerly AI"
      },
      "checklist": null,
      "redirectUris": ["https://ledgerly.example/oauth/callback"],
      "websiteUrl": "https://ledgerly.example",
      "logoUrl": null,
      "unjustifiedScopes": []
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## Errors

| Code                                                                                   | HTTP status | When                                     | What to do                                                                      |
| -------------------------------------------------------------------------------------- | ----------- | ---------------------------------------- | ------------------------------------------------------------------------------- |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed) | 400         | A filter or pagination value is invalid. | Fix the fields listed in `details.issues` and send the request again.           |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied) | 403         | You aren't a platform admin.             | Ask an organization owner or admin for a role or scope that allows this action. |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found), [`dry_run_not_supported`](https://ownrecord.io/docs/reference/errors.md#dry_run_not_supported), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
