Skip to content
Select themeSelect language

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.

GET
/api/workspaces/{id}/settings
curl --request GET \
--url https://example.com/api/workspaces/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/settings \
--cookie supacloud_session=<supacloud_session>
id
required
string format: uuid

Workspace ID whose settings to read

Workspace settings (the system-LLM credential pin)

Media typeapplication/json

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
allow_debug
required

#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).

boolean
calibration_carrier_preference
required

#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.

string
Allowed values: subscription_first score
closeout_config
required

#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.

default_max_subagents
required

#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.

integer | null format: int32
default_resource_class
required
One of:
null
default_tool_approval_deny_minutes

#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.

integer | null format: int32
environment_scope_floor
required

#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.

string | null
failure_notify
required
One of:
null
harness_config
required

#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.

mcp_external_ops_hourly_limit
required

#977 — the external-MCP OPS per-token hourly aggregate override (mig 330), or null when the env/default (30/h) applies.

integer | null format: int32
mcp_external_read_hourly_limit
required

#977 — the external-MCP READ per-tool hourly-window override (mig 330), or null when the built-in window applies.

integer | null format: int32
memory_embedding
required

#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
model
string | null
provider
string | null
memory_embedding_effective
required
One of:
null
memory_governance
required

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
personal

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
auto_publish

New memories of this scope skip the review queue and land live immediately.

boolean
require_review

New memories of this scope must be human-reviewed before they go live.

boolean
retention_days

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.

integer format: int32
<= 10000
not matching
auto_publish
required
require_review
required
project

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
auto_publish

New memories of this scope skip the review queue and land live immediately.

boolean
require_review

New memories of this scope must be human-reviewed before they go live.

boolean
retention_days

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.

integer format: int32
<= 10000
not matching
auto_publish
required
require_review
required
workspace

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
auto_publish

New memories of this scope skip the review queue and land live immediately.

boolean
require_review

New memories of this scope must be human-reviewed before they go live.

boolean
retention_days

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.

integer format: int32
<= 10000
not matching
auto_publish
required
require_review
required
model_defaults_gap
required

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.

string | null
model_defaults_ready
required

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.

boolean
model_fallback_chains
required

#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.

model_fallback_chains_effective
required

#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.

system_llm_credential
One of:
null
vision_model
required

#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.

string | null
vision_model_effective
required

#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.

string | null
voice_config
required

#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

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 license_required license_expired bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited too_many_requests 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 license_required license_expired bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited too_many_requests 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"
}

Workspace not found

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 license_required license_expired bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited too_many_requests 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 license_required license_expired bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited too_many_requests 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"
}