`GET /api/proposals/board` — one server-paginated, status/kind/source-filtered page of the proposals board plus the total + the status/source facets.
const url = 'https://example.com/api/proposals/board';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://example.com/api/proposals/boardParameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Active NavTab / lifecycle status (pending/applied/rejected/expired).
user or an agent task id (the derived created_by_task).
Free-text search over the proposal payload + reasoning.
Whitelisted sort column: created_at | kind | status | reviewed_at
| applied_at. Default created_at.
asc | desc (default desc).
Recompute the status/source facets (default true). The board sends false
for a kind/source/page change (the facets follow the active status only).
Responses
Section titled “Responses”GET /api/proposals/board body — one page of proposals + total + facets.
object
Workspace facets the board needs that a single page can’t derive: the NavTab status counts + the distinct sources for the source filter (scoped to the active status, matching what the loaded page used to enumerate).
object
The five board-tab counts over the workspace (independent of the active
tab). approved is the reviewed-but-not-yet-applied state — without it an
approved proposal would be unreachable from any tab.
object
One proposal on the wire. A presentation view over the row; payload is
passed through as-is so the inbox can render the proposed diff.
object
The target App, surfaced under the frontend’s app_id name (the row
stores it as the generic target_id). Only app.file_upsert carries one.
What an approve materialized ({ kind, resource_id }). Populated on the
approve response; null on list/get reads.
The proposing agent task id (when proposer_kind == "agent"); null for
a user-raised proposal.
Reviewer’s reject note. Not persisted on the row (it lives in the audit
trail), so it is null on reads.
Human one-liner derived from kind + payload (e.g. the script name or
“3 files”), so the inbox list reads without parsing the payload itself.
Examplegenerated
{ "facets": { "sources": [ "example" ], "status_counts": { "applied": 1, "approved": 1, "expired": 1, "pending": 1, "rejected": 1 } }, "items": [ { "app_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "applied_at": "2026-04-15T12:00:00Z", "apply_result": "example", "created_at": "2026-04-15T12:00:00Z", "created_by_task": "example", "expires_at": "2026-04-15T12:00:00Z", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "kind": "example", "payload": "example", "review_note": "example", "reviewed_at": "2026-04-15T12:00:00Z", "reviewed_by": "example", "status": "example", "title": "example", "workspace_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" } ], "total": 1}