Skip to content
Select themeSelect language

`GET /api/workspaces/{id}/backlog/board` (ADR 0045 Stage 1). RBAC: `Read`. The per-project Kanban board (`Vec<ProjectBacklogBoard>` — per-project columns, so the per-card schema stays project-id-free).

GET
/api/workspaces/{id}/backlog/board
curl --request GET \
--url https://example.com/api/workspaces/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/backlog/board \
--cookie supacloud_session=<supacloud_session>
id
required
string format: uuid

Workspace ID whose per-project board to build

Per-project backlog board (one entry per project)

Media typeapplication/json
Array<object>

ADR 0045 Stage 1 — one project’s slice of the cross-project workspace board. The workspace board endpoint returns Vec<ProjectBacklogBoard> (per-project columns) rather than a flat merged column list, so the per-card schema (BacklogCard, which carries no project_id) stays stable. columns reuses the existing BacklogColumn board contract verbatim (one column per state in board order).

object
columns
required
Array<object>

One board column: a state plus the cards in it (priority ASC NULLS LAST then created_at — the order list_backlog_items already returns).

object
items
required
Array<object>

One backlog card on the board (ADR 0039 S8 CONTRACT). updated_at is RFC3339. gates_green means precisely “a human drag → done will be ACCEPTED right now” (BE3): the INDEPENDENT audit passed (a backlog.awaiting_human_merge audit row exists) AND the item is CURRENTLY in_review (the state = 'in_review' filter — the merge gate refuses to release any non-in_review item, BE1 — so a parked card carrying a stale marker reads false). It is NOT “merged” and NOT “awaiting release”; the FE uses it to decide whether to offer the drag → done gesture. The reviewer bar (required_reviewers) is orthogonal — a green item may still need N human approvals, which the drag → done records.

object
external_id
required
string
gates_green
required
boolean
id
required
string format: uuid
kind
string | null
last_error
string | null
priority
integer | null format: int32
readiness
string | null
run_id
string | null format: uuid
scope

#532 (U2) — the classification SCOPE axis (small|medium|large), None until classified.

string | null
source
required

The issue SOURCE (linear | notion | a git-provider name), #708 X3 (was tracker).

string
state
required
string
title
string | null
updated_at
required
string
state
required
string
project_id
required
string format: uuid
project_name
required
string
Examplegenerated
[
{
"columns": [
{
"items": [
{
"external_id": "example",
"gates_green": true,
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"kind": "example",
"last_error": "example",
"priority": 1,
"readiness": "example",
"run_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"scope": "example",
"source": "example",
"state": "example",
"title": "example",
"updated_at": "example"
}
],
"state": "example"
}
],
"project_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"project_name": "example"
}
]

Authentication required

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

Permission denied

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

Structured server error

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}