Skip to content
Select themeSelect language

`GET /api/apps/board` — one server-paginated, filtered + sorted page of the Apps board plus the total + the workspace-wide facet chips.

GET
/api/apps/board
curl --request GET \
--url https://example.com/api/apps/board \
--cookie supacloud_session=<supacloud_session>
q
string

Free-text search over the App name + description.

framework
string

framework filter chip (plain | react | svelte).

deploy_status
string

deploy_status filter chip — the page’s tab/dropdown vocabulary (deployed | paused | undeployed | draft). draft matches a never-deployed App (or a literal draft deployment); any other value matches the App’s canonical derived deploy status exactly.

sort
string

Whitelisted sort column: name | created_at | updated_at. Default updated_at.

dir
string

asc | desc (default desc).

limit
integer format: int64
offset
integer format: int64
include_facets
boolean

Recompute the facet chips (default true). The board sends false on a page/sort change since the chip counts are workspace-wide.

One page of Apps.

Media typeapplication/json

GET /api/apps/board body — one page of Apps + total + facet chips.

object
facets
One of:
null
items
required
Array<object>

Lightweight list-row view – drops manifest_yaml so a workspace with dozens of large manifests does not balloon the list-API payload. The detail GET still returns the full AppView with the manifest.

#358 board: enriched with the per-card runtime state so the Apps list renders deploy status / version / route, the latest build, and the member counts without an extra round-trip. Every runtime field is nullable / defaulted so a never-deployed (draft) App lists cleanly. Serialised snake_case (the struct has no rename_all), matching the existing list fields and the App domain row.

object
created_at
required
string format: date-time
deploy_status

Active deployment status (deployed | paused | draft | undeployed). None ⇒ the App has never been deployed (draft).

string | null
deployed_version

Version string of the active deployment (e.g. 1.0.0). None when there is no deployment.

string | null
description
string | null
framework
required

ADR 0030 – build framework, so list cards can show a framework badge without fetching the full manifest.

string
id
required
string format: uuid
latest_build_at

Finished-at of the most-recent build (completed_at). None when the App has never been built OR the latest build is still running.

string | null format: date-time
latest_build_status

Status of the most-recent build (queued | claimed | building | succeeded | failed). None when the App has never been built.

string | null
name
required
string
resource_count
required

Number of resources wired into the App (membership join).

integer format: int64
route

Public route of the active deployment, /a/{workspace}/{route}. None when there is no deployment.

string | null
script_count
required

Number of scripts wired into the App (membership join).

integer format: int64
slug
required
string
updated_at
required
string format: date-time
workflow_count
required

Number of workflows wired into the App (membership join).

integer format: int64
workspace_id
required
string format: uuid
total
required
integer format: int64
Examplegenerated
{
"facets": {
"by_deploy_status": [
{
"count": 1,
"value": "example"
}
],
"by_framework": [
{
"count": 1,
"value": "example"
}
],
"total": 1
},
"items": [
{
"created_at": "2026-04-15T12:00:00Z",
"deploy_status": "example",
"deployed_version": "example",
"description": "example",
"framework": "example",
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"latest_build_at": "2026-04-15T12:00:00Z",
"latest_build_status": "example",
"name": "example",
"resource_count": 1,
"route": "example",
"script_count": 1,
"slug": "example",
"updated_at": "2026-04-15T12:00:00Z",
"workflow_count": 1,
"workspace_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"
}
],
"total": 1
}

Structured client 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"
}

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"
}