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.
/api/v1/platform/app_reviewsThe 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) andstarting_after - Authentication: API key with the
platform:writescope - 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
GET /api/v1/platform/app_reviews
Authorization: Bearer or_test_…
Response (200):
{
"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 | 400 | A filter or pagination value is invalid. | Fix the fields listed in details.issues and send the request again. |
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: api_version_unsupported, authentication_required, api_key_invalid, resource_not_found, dry_run_not_supported, rate_limited, internal_error.