GET /workspaces/{id}/settings — read the persisted workspace settings the FE pre-hydrates from (today: the system-LLM credential pin). A workspace MEMBER may read it; the PATCH on the same path stays admin-only.
const url = 'https://example.com/api/workspaces/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/settings';const options = {method: 'GET', headers: {cookie: 'supacloud_session=<supacloud_session>'}};
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/workspaces/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/settings \ --cookie supacloud_session=<supacloud_session>Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Workspace ID whose settings to read
Responses
Section titled “Responses”Workspace settings (the system-LLM credential pin)
The workspace-settings read body. Carries the system-LLM credential pin (null
when unpinned) and — ADR 0049 P3 / Tier-3 (#547/#548) — the per-scope memory
GOVERNANCE policy (always present; a never-configured workspace returns the
conservative default). A passthrough() on the FE schema leaves room for further
settings without a wire break.
object
#583 Item 2 / #582 — the Debug-light CEILING. When true, members may opt
their own live/follow session into debug; when false (the fail-closed
default), no one can enable debug in this workspace. A workspace MEMBER may
read it (correct: a non-admin needs it to gate the per-session toggle UI).
#712 — the workspace-tier standard-closeout config ({memory, project_docs, user_docs, wiki}, mig 283). Always present: a workspace that never configured
closeout returns the built-in default so the closeout panel hydrates without a
sparse-table special case. It is the DEFAULT every project inherits (per step) when
the project + task tiers leave a step unset.
#708 W8 — the workspace environment-scope FLOOR (all | production | staging | development, mig 290), or null when no floor is set. A concrete value narrows
every autonomous run’s blast radius to at most that environment class. A workspace
MEMBER may read it (to render the resolved effective gates); PATCH stays admin-only.
#838 — the workspace-level workflow-failure alert target (telegram_bot
resource + chat id, mig 319), or null when alerting is off. A workflow
run terminalizing to failed sends one Telegram message there.
object
The channel the alert is sent to — a Telegram chat id (numeric or
@channel) or a Discord channel snowflake, per the resource’s kind.
The chat resource whose bot token sends the alert. #1052: a telegram_bot
OR a discord resource — the transport follows this resource’s kind, so
the alert reaches whichever chat surface the workspace works in.
#977 — the external-MCP OPS per-token hourly aggregate override (mig 330),
or null when the env/default (30/h) applies.
#977 — the external-MCP READ per-tool hourly-window override (mig 330), or
null when the built-in window applies.
ADR 0049 P3 / Tier-3 — the per-scope memory governance policy (auto-publish / require-review / retention-days, keyed by workspace|project|personal). Always present so the governance panel hydrates without a sparse-table special case; a never-configured workspace gets the conservative default.
object
The governance rule for ONE memory scope: whether new memories of that scope skip
the review queue (auto_publish), whether they must be human-reviewed
(require_review), and how long they are retained before the decay sweep may
archive them (retention_days, 0 = keep forever).
auto_publish and require_review are intentionally NOT collapsed into one flag:
the conservative default is “review required, not auto-published”, and a future
“auto-published BUT still logged for review” mode keeps both axes meaningful. The
validation below rejects the contradictory auto_publish && require_review combo.
object
New memories of this scope skip the review queue and land live immediately.
New memories of this scope must be human-reviewed before they go live.
Days a memory of this scope is retained before the decay sweep may archive it;
0 keeps it forever (the default).
not matching
The governance rule for ONE memory scope: whether new memories of that scope skip
the review queue (auto_publish), whether they must be human-reviewed
(require_review), and how long they are retained before the decay sweep may
archive them (retention_days, 0 = keep forever).
auto_publish and require_review are intentionally NOT collapsed into one flag:
the conservative default is “review required, not auto-published”, and a future
“auto-published BUT still logged for review” mode keeps both axes meaningful. The
validation below rejects the contradictory auto_publish && require_review combo.
object
New memories of this scope skip the review queue and land live immediately.
New memories of this scope must be human-reviewed before they go live.
Days a memory of this scope is retained before the decay sweep may archive it;
0 keeps it forever (the default).
not matching
The governance rule for ONE memory scope: whether new memories of that scope skip
the review queue (auto_publish), whether they must be human-reviewed
(require_review), and how long they are retained before the decay sweep may
archive them (retention_days, 0 = keep forever).
auto_publish and require_review are intentionally NOT collapsed into one flag:
the conservative default is “review required, not auto-published”, and a future
“auto-published BUT still logged for review” mode keeps both axes meaningful. The
validation below rejects the contradictory auto_publish && require_review combo.
object
New memories of this scope skip the review queue and land live immediately.
New memories of this scope must be human-reviewed before they go live.
Days a memory of this scope is retained before the decay sweep may archive it;
0 keeps it forever (the default).
not matching
#926 — the workspace-level quota-fallback chain OVERRIDE (#867 substrate,
sparse per-tier JSON as stored), or null when never configured — the
built-in chains (TierChains::builtin) then apply. Round-trips exactly what
the admin PATCHed; the effective chains additionally layer any per-profile
retry_policy.model_fallback.chains override at task launch.
#984 item 926 — the RESOLVED quota-fallback chains a task at this workspace
would actually get: the stored model_fallback_chains override merged over
TierChains::builtin() (sc_svc_orchestration::model_fallback::resolve_chains,
the SAME seam the runtime resolver uses). Always present — a workspace that
never configured an override still has effective chains (the built-in ones) —
so the GUI editor can prefill from this rather than hard-coding a model list.
A malformed stored override degrades to the built-in chains here too, mirroring
the resolver’s own fail-open-to-built-in posture.
The owner-pinned credential backing INTERNAL system-prompt LLM calls, or
null when no pin is set (the default most-specific precedence applies).
object
The pinned credential id (api_key_refs.id or agent_oauth_tokens.id).
The credential kind: api_key or oauth_token.
Examplegenerated
{ "allow_debug": true, "closeout_config": "example", "environment_scope_floor": "example", "failure_notify": { "chat_id": "example", "resource_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" }, "mcp_external_ops_hourly_limit": 1, "mcp_external_read_hourly_limit": 1, "memory_governance": { "personal": { "auto_publish": true, "require_review": true, "retention_days": 1 }, "project": { "auto_publish": true, "require_review": true, "retention_days": 1 }, "workspace": { "auto_publish": true, "require_review": true, "retention_days": 1 } }, "model_fallback_chains": "example", "model_fallback_chains_effective": "example", "system_llm_credential": { "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "kind": "example" }}Authentication required
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
Machine-readable, stable error code.
Present only on a quota-exceeded 403 — the inline upgrade-CTA payload.
object
The entitlement feature key that was hit, e.g. apps.max_count.
The plan’s limit for this key.
Where to send the user to upgrade.
Current usage (count or bytes, per the key).
Human-readable message (the server’s English text; the client may localize
by code).
Example
{ "code": "not_found"}Permission denied
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
Machine-readable, stable error code.
Present only on a quota-exceeded 403 — the inline upgrade-CTA payload.
object
The entitlement feature key that was hit, e.g. apps.max_count.
The plan’s limit for this key.
Where to send the user to upgrade.
Current usage (count or bytes, per the key).
Human-readable message (the server’s English text; the client may localize
by code).
Example
{ "code": "not_found"}Workspace not found
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
Machine-readable, stable error code.
Present only on a quota-exceeded 403 — the inline upgrade-CTA payload.
object
The entitlement feature key that was hit, e.g. apps.max_count.
The plan’s limit for this key.
Where to send the user to upgrade.
Current usage (count or bytes, per the key).
Human-readable message (the server’s English text; the client may localize
by code).
Example
{ "code": "not_found"}Structured server error
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
Machine-readable, stable error code.
Present only on a quota-exceeded 403 — the inline upgrade-CTA payload.
object
The entitlement feature key that was hit, e.g. apps.max_count.
The plan’s limit for this key.
Where to send the user to upgrade.
Current usage (count or bytes, per the key).
Human-readable message (the server’s English text; the client may localize
by code).
Example
{ "code": "not_found"}