Boards
Kanban-Boards: ein Dokumentwurzel-Block wie eine Seite, der seine Spalten- und Lane-Konfiguration mitführt. Die Karten sind Zeilen einer impliziten Datenbank dahinter — Seiten mit Spalte, Lane und Position je Board.
10 Operationen. Jeder Pfad ist relativ zum Ursprung der Instanz; jeder Antwortkörper ist JSON, sofern nicht anders vermerkt. Die Endpunktbeschreibungen unten stammen unverändert aus der Routentabelle des Servers und bleiben englisch. Authentifizierung, Fehler und seitenweise Abfrage stehen unter API.
GET /api/v1/workspaces/{workspaceId}/boards
List the boards of a collection (flat, newest first). Requires read on the collection.
listBoards · token scope: content:read
Path parameters
workspaceId· string (uuid) — required
Query parameters
collectionId· string (uuid) — required
Response 200 — application/json
items· object[] — requiredid· string (uuid) — requiredworkspaceId· string (uuid) — requiredcollectionId· string (uuid) — requiredtitle· string — requiredicon· string | null — requiredtargetDatabaseId· string (uuid) — requiredcolumns· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200icon· string — length 0–2048collapsed· boolean
lanes· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200collapsed· boolean
noLaneCollapsed· boolean — requiredcardFields· string (uuid)[] — requiredconfigVersion· string — requiredcreatedAt· string (date-time) — requiredupdatedAt· string (date-time) — requireddeletedAt· string (date-time) | null — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
POST /api/v1/workspaces/{workspaceId}/boards
Create a board at the collection root. Requires edit on the collection. Implicitly creates the 1:1 backing database and stores its id as targetDatabaseId (ADR-0025 D2); the body doc is created lazily on first collab connect. Starts with empty columns and lanes.
createBoard · token scope: content:write
Path parameters
workspaceId· string (uuid) — required
Request body — application/json, required
collectionId· string (uuid) — requiredtitle· string — required, length 1–500icon· string — length 0–2048
Response 200 — application/json
id· string (uuid) — requiredworkspaceId· string (uuid) — requiredcollectionId· string (uuid) — requiredtitle· string — requiredicon· string | null — requiredtargetDatabaseId· string (uuid) — requiredcolumns· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200icon· string — length 0–2048collapsed· boolean
lanes· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200collapsed· boolean
noLaneCollapsed· boolean — requiredcardFields· string (uuid)[] — requiredconfigVersion· string — requiredcreatedAt· string (date-time) — requiredupdatedAt· string (date-time) — requireddeletedAt· string (date-time) | null — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
GET /api/v1/workspaces/{workspaceId}/boards/{boardId}
Fetch one board (structure plane only — config, not cards). Requires read.
getBoard · token scope: content:read
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — required
Response 200 — application/json
id· string (uuid) — requiredworkspaceId· string (uuid) — requiredcollectionId· string (uuid) — requiredtitle· string — requiredicon· string | null — requiredtargetDatabaseId· string (uuid) — requiredcolumns· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200icon· string — length 0–2048collapsed· boolean
lanes· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200collapsed· boolean
noLaneCollapsed· boolean — requiredcardFields· string (uuid)[] — requiredconfigVersion· string — requiredcreatedAt· string (date-time) — requiredupdatedAt· string (date-time) — requireddeletedAt· string (date-time) | null — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
PATCH /api/v1/workspaces/{workspaceId}/boards/{boardId}
Rename a board, change its icon, replace its column/lane config (whole lists, board-local), fold or unfold the implicit no-lane row, and/or replace the field list its cards show. Because those lists are replaced whole, pass expectedConfigVersion — the board’s configVersion the patch was computed from — for optimistic concurrency: a board that has changed since answers 409 instead of silently dropping what the caller had not seen yet. Cards of a column the patch removes are UNPLACED (they surface in the grouped read’s columnId: null group) rather than left pointing at an id no list contains. Requires edit.
updateBoard · token scope: content:write
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — required
Request body — application/json, required
title· string — length 1–500icon· string | nullcolumns· object[]id· string (uuid) — requiredlabel· string — required, length 1–200icon· string — length 0–2048collapsed· boolean
lanes· object[]id· string (uuid) — requiredlabel· string — required, length 1–200collapsed· boolean
noLaneCollapsed· booleancardFields· string (uuid)[]expectedConfigVersion· string — length 1–64
Response 200 — application/json
id· string (uuid) — requiredworkspaceId· string (uuid) — requiredcollectionId· string (uuid) — requiredtitle· string — requiredicon· string | null — requiredtargetDatabaseId· string (uuid) — requiredcolumns· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200icon· string — length 0–2048collapsed· boolean
lanes· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200collapsed· boolean
noLaneCollapsed· boolean — requiredcardFields· string (uuid)[] — requiredconfigVersion· string — requiredcreatedAt· string (date-time) — requiredupdatedAt· string (date-time) — requireddeletedAt· string (date-time) | null — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
DELETE /api/v1/workspaces/{workspaceId}/boards/{boardId}
Move a board to the trash (soft delete). Requires full.
trashBoard · token scope: content:write
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — required
Response 200 — application/json
ok·true— required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
POST /api/v1/workspaces/{workspaceId}/boards/{boardId}/move
Reorder a board among its collection’s boards — beforeId/afterId name the siblings it lands between, neither appends. Boards stay at the collection root. Requires edit.
moveBoard · token scope: content:write
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — required
Request body — application/json, required
beforeId· string (uuid)afterId· string (uuid)
Response 200 — application/json
id· string (uuid) — requiredworkspaceId· string (uuid) — requiredcollectionId· string (uuid) — requiredtitle· string — requiredicon· string | null — requiredtargetDatabaseId· string (uuid) — requiredcolumns· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200icon· string — length 0–2048collapsed· boolean
lanes· object[] — requiredid· string (uuid) — requiredlabel· string — required, length 1–200collapsed· boolean
noLaneCollapsed· boolean — requiredcardFields· string (uuid)[] — requiredconfigVersion· string — requiredcreatedAt· string (date-time) — requiredupdatedAt· string (date-time) — requireddeletedAt· string (date-time) | null — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
GET /api/v1/workspaces/{workspaceId}/boards/{boardId}/cards
The board read path (ADR-0025 D4): cards grouped by (column × lane) in ONE grouped query — a window per group, a per-group cursor, and per-group total counts. Without a cursor, every group answers its first window; with one, only that group answers its next. Requires read on the board; card pages the caller may not read are omitted, not stubbed (ADR-0016 D9), so group counts and cursors are viewer-dependent.
getBoardCards · token scope: content:read
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — required
Query parameters
cursor· string — length 1–∞windowSize· integer — 1–100
Response 200 — application/json
groups· object[] — requiredcolumnId· string (uuid) | null — requiredlaneId· string (uuid) | null — requiredcards· object[] — requiredpageId· string (uuid) — requiredworkspaceId· string (uuid) — requireddatabaseId· string (uuid) — requiredposition· string — requiredtitle· string — requiredicon· string | null — requiredcells· object — requiredcreatedAt· string (date-time) — requiredchecklist· object | null — requireddone· integer — required, 0–9007199254740991total· integer — required, −∞–9007199254740991
columnId· string (uuid) | null — requiredlaneId· string (uuid) | null — requiredboardPosition· string — required
nextCursor· string | null — requiredtotalCount· integer — required, 0–9007199254740991
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
POST /api/v1/workspaces/{workspaceId}/boards/{boardId}/cards
Add a card: create a new page as a row of the backing database, or attach an existing page by id — either way a membership carrying columnId, an optional laneId, and a position (omit the neighbours for the end of the column). Requires edit on the board.
addBoardCard · token scope: content:write
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — required
Request body — application/json, required
pageId· string (uuid)title· string — length 0–1000icon· string — length 0–2048columnId· string (uuid) — requiredlaneId· string (uuid)beforeId· string (uuid)afterId· string (uuid)
Response 200 — application/json
pageId· string (uuid) — requiredworkspaceId· string (uuid) — requireddatabaseId· string (uuid) — requiredposition· string — requiredtitle· string — requiredicon· string | null — requiredcells· object — requiredcreatedAt· string (date-time) — requiredchecklist· object | null — requireddone· integer — required, 0–9007199254740991total· integer — required, −∞–9007199254740991
columnId· string (uuid) | null — requiredlaneId· string (uuid) | null — requiredboardPosition· string — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
POST /api/v1/workspaces/{workspaceId}/boards/{boardId}/cards/{pageId}/move
Move a card to a (column × lane) and position on THIS board — one transaction over the membership's override columns (ADR-0025 D5). The permission subject is the board, at edit; the card's page is not consulted and not touched. The response redacts title/icon/cells to empty when the caller may not read the page (ADR-0016 D9): D5 authorizes the move, not a content read.
moveBoardCard · token scope: content:write
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — requiredpageId· string (uuid) — required
Request body — application/json, required
columnId· string (uuid) — requiredlaneId· string (uuid)beforeId· string (uuid)afterId· string (uuid)
Response 200 — application/json
pageId· string (uuid) — requiredworkspaceId· string (uuid) — requireddatabaseId· string (uuid) — requiredposition· string — requiredtitle· string — requiredicon· string | null — requiredcells· object — requiredcreatedAt· string (date-time) — requiredchecklist· object | null — requireddone· integer — required, 0–9007199254740991total· integer — required, −∞–9007199254740991
columnId· string (uuid) | null — requiredlaneId· string (uuid) | null — requiredboardPosition· string — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64
DELETE /api/v1/workspaces/{workspaceId}/boards/{boardId}/cards/{pageId}
Remove a card from this board (drops the backing-database membership; the page is kept). Requires edit on the board; like the move, the response redacts title/icon/cells the caller may not read (ADR-0016 D9). 409 with a needs-new-home code when this is the page's home database (ADR-0006, the same rule removeRow enforces) — name newHomeBoardId to hand the card to another board of the same collection it is already on, which re-homes and removes in one transaction, or let the UI offer trash / another board (ADR-0025 D6). That parameter needs edit on the named board and is ignored when this board is not the card's home.
removeBoardCard · token scope: content:write
Path parameters
workspaceId· string (uuid) — requiredboardId· string (uuid) — requiredpageId· string (uuid) — required
Query parameters
newHomeBoardId· string (uuid)
Response 200 — application/json
pageId· string (uuid) — requiredworkspaceId· string (uuid) — requireddatabaseId· string (uuid) — requiredposition· string — requiredtitle· string — requiredicon· string | null — requiredcells· object — requiredcreatedAt· string (date-time) — requiredchecklist· object | null — requireddone· integer — required, 0–9007199254740991total· integer — required, −∞–9007199254740991
columnId· string (uuid) | null — requiredlaneId· string (uuid) | null — requiredboardPosition· string — required
Response default — application/json
error· object — requiredcode·"bad_request"|"validation_failed"|"unauthorized"|"forbidden"|"not_found"|"conflict"|"rate_limited"|"internal"— requiredmessage· string — requiredreason· string — length 1–64