List workspace sites
Every worked value below is SYNTHETIC / UNRUN; no action was called.
Descriptor description (quoted): “List the sites in the active workspace with their published state and domains.” The response is a site-summary array and contains no domains property; use app_topolo_web.sites.domains.list for domain records.
Request
- Action:
app_topolo_web.sites.list - Method and path:
GET /api/studio/sites - Required permission:
app_topolo_web.studio:read - Input:
{} - Additional input fields: false
How it behaves
Read-only discovery. No input properties are accepted; the route supplies organization and workspace from authenticated context. Returns workspace site summaries, not full site records. Although the catalog description mentions domains, the current response schema and source summary have no domains property; use a site domain-list action for those details. Archived sites are excluded. The D1 path orders by updated_at descending; the in-memory source path follows its stored array order. A missing/empty workspace has a 200 empty array, not a 404. The precise output schema requires id, organizationId, workspaceId, slug, name, status, updatedAt and draftPreviewToken; currentVersionId and faviconUrl are optional. The pinned mapper returns id, organizationId, workspaceId, slug, name, status, updatedAt, optional currentVersionId and draftPreviewToken, with no domains field.
Worked examples
SYNTHETIC / UNRUN — workspace list returns non-archived sites
HTTP 200; response body (synthetic/unrun):
[
{
"id": "site_synth_02",
"organizationId": "org_synth_01",
"workspaceId": "workspace_synth_01",
"slug": "sample-draft",
"name": "Sample Draft",
"status": "draft",
"updatedAt": "2026-10-23T02:45:00.000Z",
"draftPreviewToken": "draft-preview-synth-02"
},
{
"id": "site_synth_01",
"organizationId": "org_synth_01",
"workspaceId": "workspace_synth_01",
"slug": "northstar-studio",
"name": "Northstar Studio",
"status": "published",
"updatedAt": "2026-10-23T02:30:00.000Z",
"currentVersionId": "version_synth_02",
"draftPreviewToken": "draft-preview-synth-01"
}
]
SYNTHETIC / UNRUN — workspace has no visible sites
HTTP 200; response body (synthetic/unrun):
[]
Errors and recovery
Current descriptor documents HTTP 403 Forbidden when the caller lacks studio:read. The route uses the shared can(c, studio:read) guard; exact route auth envelope is not expanded by this candidate. Select the intended workspace before interpreting an empty array. For a specific site, use sites.get with an ID from this response.
Who should use this guide
For operators discovering sites in the active workspace. The precise summary-array schema requires id, organizationId, workspaceId, slug, name, status, updatedAt and draftPreviewToken; currentVersionId and faviconUrl are optional. Use the separate domains.list action for domain records.
Provenance and change log
Pinned d9 source d9c75819abedaf71f9436a1d200015883a291072 (tree 186133adb5823723307184dcbd77acb1814317a1) plus the exact saved action descriptor in the current detailed catalog. The action metadata in the saved detailed catalog is bound by SHA-256 0d37dbcd6b71ee45f4e09d2a34dcb8331676dd2c0ea2184460400ec1abe688fc. Relevant implementation paths at revision d9c75819abedaf71f9436a1d200015883a291072: apps/api/src/routes/studio.ts:283-287, apps/api/src/repositories/store/sites.ts:691-700, apps/api/src/repositories/store/persistence.ts:618-639. Current-source freshness beyond the saved d9/release association is UNKNOWN; this is not fresh production action readback.
Change log — 2026-10-23 — source-derived guide content: aligned method/path/permission and input to the saved current descriptor; added synthetic/unrun branch examples; documented source behavior and recovery; left missing/ambiguous envelopes and output schema gaps explicit.
Correction change log — 2026-10-23: removed the stale missing-schema claim, described the exact summary-array contract, and marked the catalog description’s domains phrase as descriptor copy that the response does not fulfill.
Unresolved: Exact authorization error envelopes are not claimed.