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).
#1227 (mig 371) - the calibrator’s CARRIER ORDER for this workspace:
subscription_first (the default - every model reachable through a
subscription with measured headroom orders ahead of every model reachable
only through an API key) or score (the score alone decides). Always
present; a workspace that never touched it reads the default.
#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.
#838 (mig 358) — the workspace-DEFAULT ceiling on how many subagents ONE task
may run at once, or null when no workspace default is set. The last tier of
task.config.max_subagents ?? profile.max_subagents ?? this ?? (no env).
Subagents are helpers the HARNESS spawns inside one task and one container —
not teammates (max_teammates, separate worktrees) and not sub-tasks (real
task rows). Only the first shares a memory allowance, which is what the
ceiling protects. How hard it binds varies by harness: the FE labels it from
the selected model’s subagent_cap_level, so an advisory limit is never shown
as a guarantee.
#1176 (mig 361) — the workspace-DEFAULT resource class, or null when no
workspace default is set. The last tier of
task.config.resource_class ?? profile.resource_class ?? this ?? normal.
A class decides how much MACHINE a task gets: its container memory cap AND
how many of the workspace’s parallel slots it holds — one budget, not two,
so heavy trades parallelism for room instead of multiplying the host’s
peak footprint. This tier is the only one a PROFILE-LESS task can reach,
which is every workflow and auto-dev run.
#1175 (mig 363) — the workspace-DEFAULT tool-gate deny budget in minutes,
or null when none is set. The last tier of
task.config.tool_approval_deny_minutes ?? profile ?? this ?? 1440.
It bounds ONLY a gate whose caller explicitly chose the deny timeout
policy. The default for every runner-raised gate is hold, which waits for
a person however long that takes and has no deadline to configure.
#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.
#1397 (mig 404) — the workspace’s per-harness agent config bag
({"opencode": {…}}), or null when never configured. A workspace MEMBER
may read it so the settings card hydrates; PATCH stays admin-only.
#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.
#1228 slice 2 — the workspace’s memory-EMBEDDING config (mig 368): pinned provider and/or model, or empty = auto (first keyed provider, provider default model). Always present so the card hydrates.
object
#1228 slice 2 — what is IN FORCE: the embedder the workspace actually resolves
(config + credentials), or null when no usable embedding credential exists —
in which case retrieval runs on the deterministic hash. Resolved by the SAME
fold the query paths and the re-index sweep use.
object
… of which carry a vector under model_key; the rest wait for the sweep.
Live (unarchived, valid) memories of the workspace.
The stored memory_embeddings.model key (<provider>:<model>) — the
re-index migration key.
#1228 review F6.4 — true when this model is NOT in the embedding price table: every ledger booking under it is costed at the ceiling estimate, not at a list price. Derived from the PURE table (never from a runtime call), so an operator reading this page learns that the spend figure is an estimate without the page itself costing anything.
The background re-index’s last error, when it is currently failing.
Since when it has been failing (the first failure after a success).
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. Defaults per scope: shared scopes (workspace/project)
start at [DEFAULT_SHARED_RETENTION_DAYS] (#1228), personal at 0.
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. Defaults per scope: shared scopes (workspace/project)
start at [DEFAULT_SHARED_RETENTION_DAYS] (#1228), personal at 0.
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. Defaults per scope: shared scopes (workspace/project)
start at [DEFAULT_SHARED_RETENTION_DAYS] (#1228), personal at 0.
not matching
Why the model-defaults step is not done yet, naming the offending tier and
entry; null when [Self::model_defaults_ready] is true. Surfaced so the
checklist can say what to fix rather than only that something is unfinished.
Whether the workspace’s DEFAULT models are decided and reachable — the
onboarding “Standardmodelle” step. true when the fast and balanced
tiers each lead with an entry whose provider this workspace holds a
credential for and, where that head is a subscription, carry 1-2 fallback
providers behind it.
Computed server-side on purpose. It is the SAME value
workspaces::graduate_onboarding refuses on, so the checklist step and the
server can never disagree about whether the step is done — a browser-local
re-derivation of the rule is exactly how a button and a gate drift apart.
#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.
#838 (B1) — the workspace’s VISION-model override (mig 357), or null when the
instance default applies. This is the model that describes an image for a model
that cannot read one, and the fallback the visual-verify judge uses when a project
arm has pinned no vision_judge_model of its own. A workspace MEMBER may read it
(so the settings panel hydrates); PATCH stays admin-only.
#838 (B1) — the RESOLVED default a task at this workspace would actually use: the
override above, else the instance default. Present so the settings panel can show
what is in force (“inheriting gpt-5.6-luna”) instead of an empty field that looks
like nothing is configured. null only when neither tier is set anywhere.
This reports what is CONFIGURED, not whether it is currently usable — usability additionally depends on the live catalog and a keyed provider, both of which can change between this read and a task launch, so asserting it here would be a claim the response cannot honour.
#980 (mig 408) — the workspace’s voice-stack config
({"mode": …, "asr"?, "streaming_asr"?, "tts"?, "llm"?}), or null when never
configured (the deployment’s own stack applies). A workspace MEMBER may read it so
the settings card hydrates; PATCH stays admin-only.
Example
{ "calibration_carrier_preference": "subscription_first", "default_resource_class": "normal"}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"}