get_api_management_v1_workspaces_slug_state
Authorizations
Section titled “Authorizations”Responses
Section titled “Responses”Sanitized workspace state
object
#998 — the workspace’s agent profiles, so an M2M caller can check a pin
BEFORE launching instead of discovering a bad one as a 400. Deliberately
the SHARED AgentProfileSummary projection rather than a management-local
DTO: the decision about which profile columns may leave the instance is
made once, in sc-svc-tenancy::agent_profiles_summary, so this surface and
the profile.* MCP tools cannot drift apart. READ-ONLY — the apply (PUT)
side takes a different struct (ManagementWorkspaceState) and ignores
unknown sections, so this can never become a write path.
The outward-facing view of one agent profile: identity, lifecycle and what the profile PINS. Deliberately free of prompts, allowlists and open config bags — see the module header.
object
The harness the profile runs (claude, codex, …).
A disabled profile still resolves by id/slug, so a caller checking a pin must be able to see that it would not actually be selectable.
ADR 0045 §3.2 — does a task under this profile arm the interactive tool-approval
gate? (resolve_interactive_approvals_for_run OR-folds it with the slider.)
#1161 — ADDED DELIBERATELY, per this module’s rule that widening is a decision.
The reason: #1152 made a profile authorable from the Management API and from the
profile.create/profile.update MCP tools, and BOTH write this column — but the
only read-back either door has is this projection, so a provisioning run could set
the gate and had no way to confirm it landed. A write with no matching read is not
“one shape”; it is a shape you have to take on faith. It belongs with
review_required: a governance PIN of the profile, not prompt or allowlist
material, and the same class of fact the summary already answers (“what does this
profile pin?”). It is not a secret and it widens no capability — the slider can
arm the gate for every profile regardless of this flag.
fixed | auto | … — together with fixed_model this is the answer to
“which model does a task pinned to this profile actually get?”.
Bumped on every profile edit — lets a caller detect that the thing it verified earlier is no longer the thing it is launching against.
object
FA-M1 — None when the reading token lacks management:budget:read. The
full workspace-state read is gated only on workspaces:read, so the budget
block is withheld (not merely zeroed) from a token without the granular
scope, rather than bypassing it. The credential + variable blocks are
withheld by returning EMPTY lists (their absence is indistinguishable from a
workspace that has none — no shape change needed there).
object
{ api_key, oauth, system } ⇒ bool toggles. Runtime stays
serde_json::Value; the spec types it as a Record<string, bool>.
object
#1026 — the OAuth subscriptions CONNECTED to this workspace, read from
agent_oauth_tokens, independent of whether a quota window was ever measured.
This is the surface’s PRESENCE source: deriving presence from
per_provider_windows is what forced the #626 B1 seed to write a phantom window
for every provider. With presence here, the seed can be provider-true and a
provider with no readable quota (quota_readability == "none") shows as an
account without a gauge instead of an empty gauge that never fills.
#1026 — one OAuth subscription CONNECTED to this workspace, independent of whether any quota window has ever been measured for it.
Presence and measurement are two different facts. The usage surface used to derive
presence from provider_quota_state rows, which is precisely why the #626 B1 connect
seed had to write two phantom windows for EVERY provider (without a row a fresh
connect read as “No subscription credentials connected”). With presence sourced here,
the seed is free to be provider-true — and a provider whose quota is not readable at
all can be shown honestly, as an account with no gauge rather than an empty gauge.
object
OAuth account e-mail (or provider handle); None when the provider exposed none.
The agent_oauth_tokens row id — the same id the windows carry as
credential_id, so the FE joins the two without a heuristic.
Plan/tier badge from agent_oauth_tokens.plan_label (mig 263); None for every
OIDC provider (openai/google return no plan at connect).
'probe' (a live provider endpoint answers) · 'harness' (only the harness
reports windows, so a measurement appears after the first task) · 'none' (no
producer exists — no quota is readable for this provider). From the declarative
sc_svc_foundation::provider_windows table.
#1160 — WHY the quota is unreadable, when quota_readability == "none";
None otherwise. 'no_provider_quota_api' · 'harness_reports_no_usage' ·
'provider_not_modelled' — three DIFFERENT statements that the surface used
to collapse into one causeless sentence beside an unrelated “never measured”
line, which is what made an honest structural limit look like a broken
measurement.
The operator’s target window saturation in [0.0, 1.0] (e.g. 0.85) driving
the throttling_soon warning, from the autonomy policy. None → the surface
falls back to the Balanced default (GOTCHA-FILLTARGET).
#626 Nutzung — the same windows summed per (provider, window_type, scope) across
a provider’s connected accounts (the “2 KONTEN · summiert” popover header). Derived
from per_provider_windows; empty when there are no windows.
#626 Nutzung — one provider’s windows summed across its connected accounts, for the
“2 KONTEN · summiert” popover header. One summary per (provider, window_type, scope)
over the per-account [ProviderWindowStatus] list (the FE still lists the per-account
rows underneath). Computed by calculations::aggregate_windows_by_provider.
object
How many distinct accounts (credentials) contribute to this summary.
Percent of the summed window consumed, 0.0..=100.0; 0.0 when limit is None.
Sum of limit across the accounts — None when ANY account’s limit is unknown
(an unknown limit is not assumed zero; the summed gauge would mislead).
all (overall budget) or model:<id> (a per-model sub-budget) — windows are
summed only within the SAME scope (an all window is never folded into a
per-model one).
Sum of used across the accounts in this group.
'rolling_5h' | 'weekly' | 'monthly'.
ADR 0045 Stage 2a — per-credential subscription/API saturation windows
(one entry per (provider, window)), computed from the
provider_quota_state snapshots by calculations::window_status. Empty on an
API-key-only workspace with no quota snapshots (the $-bars above still apply).
ADR 0045 Stage 2a — one provider-quota window in the usage surface. Serialized by
GET /api/settings/budget and GET /workspaces/{id}/usage. The COMPUTATION (from
a [crate::services::provider_quota::QuotaState]) lives in
calculations::window_status; this is the wire shape (+ Default so callers
compile before that computation lands).
object
Human label for the credential’s account (OAuth account email), resolved in
load_budget_status. None when unresolved (e.g. an Anthropic OAuth token
whose scopes return no email — see the OAuth-email follow-up).
#626 Nutzung — 'primary' | 'overflow', DERIVED at read time (no column): per
provider, the credential with the MOST headroom in its all-scope window is the
primary (the one the quota-aware dispatcher prefers, mirroring
provider_quota::multi_key::resolve_credential_with_most_headroom); the rest are
overflow. Account-level — the same role is stamped on EVERY window of a
credential (incl. its per-model windows). None when the provider has a single
account (no overflow concept).
The credential this window belongs to. Lets the FE list per-account windows distinctly when one provider has several connected accounts (#555).
'oauth_subscription' | 'api_key' — drives the FE capability detection
(saturation gauges show only for subscription credentials).
Percent of the window consumed, 0.0..=100.0. 0.0 when the limit is unknown.
#1160 — is what this snapshot says still true NOW?
'current' (the measured window is still open — these ARE the current
figures) · 'outdated' (the window ENDED and nothing re-measured it yet; a
last-known state, never the current utilisation) · 'unreported' (a whole
further window passed with no measurement — nobody is reporting this window
any more, so no surface may draw it).
The projection carried measured_at but no VERDICT on it, so every renderer
had to invent its own staleness rule — and all three (web reports, web
settings, chat /usage) simply drew a dead snapshot as live. Classified once
by sc_svc_foundation::provider_windows::window_freshness from the window
DEFINITION, so the answer cannot differ per surface.
None = unknown limit (a new/Unsupported credential) ⇒ no gauge, no warning.
#1025 — WHEN this snapshot was written (provider_quota_state.updated_at, set to
now() on every upsert). The DTO carried window_start / resets_at /
minutes_to_refresh but no measurement time at all, so the surface could not say
how OLD a reading is — a two-week-stale gauge looked exactly like a fresh one.
Required (the column is NOT NULL), so the FE never has to guess.
#1026 — the PROVENANCE CLASS of this window, folded from [Self::source] by
sc_svc_foundation::provider_windows::measurement_class:
'provider' (read from the provider, its harness, or a real 429) ·
'estimate' (OUR spend arithmetic — telemetry; the provider reported nothing) ·
'pending' (seeded, never measured). The FE must NOT render an estimate as a
provider measurement: telemetry_estimate fills used from
workspace_month_spend_ledger and limit from 80 % of the configured $-cap, yet
it lands in the same subscription-saturation list as a real probe.
Whole minutes until resets_at; None if unknown.
#626 Nutzung — the subscription plan/tier badge (“Max 20x”, “ChatGPT Pro”, …)
read off the credential’s agent_oauth_tokens.plan_label (migration 263), resolved
in load_budget_status. None for an API key, a legacy row, or any provider whose
OAuth profile body exposed no plan at connect.
#626 D4.3 — the count of REDEEMABLE rate-limit-reset credits the provider
advertises for this credential window (Codex
rateLimitResetCredits.availableCount, migration 270). None = no reset-credit
surface (every non-Codex window, and a Codex window probed before the spine read
it). The FE renders it as a chip; the redeem/consume action is a follow-up.
When the window resets; None if unknown.
#626 H2 — the window’s scope: all (the credential’s overall budget) or
model:<id> (a per-model sub-budget, e.g. a Codex Spark or Claude Sonnet
window). ALWAYS present (the DB enforces NOT NULL DEFAULT 'all' and the
projection clones it verbatim), so it is a REQUIRED string in the contract —
no #[serde(default)] (this DTO is serialize-only; the attribute would only
drop it from the OpenAPI required set). The FE renders per-model windows
distinctly and sums per-account windows under one provider.
'real_limit_hit' | 'status_probe' | 'telemetry' | 'default' | 'task_boundary'
— snapshot provenance so the FE can distinguish a hard hit from a low-confidence
estimate.
True when fill_pct is within the throttling band of fill_target — the FE
surfaces an amber “approaching limit” state.
'rolling_5h' | 'weekly' | 'monthly'.
Per-provider in-flight reservation (USD). Runtime stays serde_json::Value;
the spec types it as a Record<string, number>.
object
Per-provider monthly cap (USD). Runtime stays serde_json::Value; the spec
types it as a Record<string, number>.
object
Per-provider month spend (USD). Runtime stays serde_json::Value; the spec
types it as a Record<string, number>.
object
object
object
object
#1214 — installed official-catalog listings, each with whether the catalog has moved past it. Empty on a workspace with no installs.
What the READ side reports back per installed listing.
object
True when a newer non-withdrawn version exists in the catalog — the same question the #351 update signal answers in the UI, so a provisioning run can see drift without installing anything.
object
object
object
#1161 D2 — the project’s automation arms, so a management caller can READ BACK what
it wrote through the spec’s automations block. Without this the write side could
only be confirmed by running the pipeline: the fields went in and nothing came out.
Ordered by kind; empty for a project with no arms.
#1161 D2 — the management read projection of ONE automation arm. Deliberately NARROW:
it carries the arm’s identity plus the two fields that had no management door
(review_enabled, pipeline_config), and NEVER the row’s webhook_secret — a read
projection must not become a secret-exfiltration path.
object
#538 (mig 231) — the pipeline knobs bag: the return-to-sender loop’s max_rounds /
max_cost_usd ceilings, the convergence level and the per-stage overrides.
#538 (mig 231) — the independent forensic audit tail.
#1214 — the git binding, None when the workspace has none. Read half of
the write block above: without it the provisioning loop could only be
verified from a browser, which is the dependency the block removes.
object
The resource NAME, resolved back from the stored id — so a read/apply
round-trip is expressible in the same vocabulary. None means the binding
carries no credential (a public repo), or the resource has since been
deleted.
object
#1161 C12 — the profile PIN this schedule fires under; null is the ungated
(no-pin) shape. The schedule-side sibling of ManagementTaskInfo.agent_profile_id.
#908 — the step width of an interval cadence in minutes; null for
calendar cadences.
object
#1161 C12 — the profile PIN this task was stored with, so an M2M caller can
verify the gate it armed instead of probing the column with raw SQL. null is
the ungated (no-pin) shape.
object
object
Examplegenerated
{ "agent_profiles": [ { "created_at": "2026-04-15T12:00:00Z", "default_agent_type": "example", "description": "example", "effort_default": "example", "enabled": true, "execution_mode": "example", "fixed_model": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "interactive_approval": true, "is_workspace_default": true, "model_policy": "example", "name": "example", "review_required": true, "slug": "example", "tags": [ "example" ], "updated_at": "2026-04-15T12:00:00Z", "version": 1 } ], "ai_credentials": [ { "account_email": "example", "expires_at": "2026-04-15T12:00:00Z", "fingerprint": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "key": "example", "provider": "example", "scope": "example" } ], "budget": { "alerts": [ "example" ], "api_mode_controls": { "additionalProperty": true }, "connected_subscriptions": [ { "account_email": "example", "credential_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "plan_label": "example", "provider": "example", "quota_readability": "example", "quota_unreadable_reason": "example" } ], "critical_threshold_percent": 1, "effective_month_spend_usd": 1, "fill_target": 1, "hard_stop": true, "inflight_reserved_usd": 1, "month_spend_usd": 1, "monthly_cap_usd": 1, "per_provider_summary": [ { "account_count": 1, "fill_pct": 1, "limit": 1, "provider": "example", "scope": "example", "used": 1, "window_type": "example" } ], "per_provider_windows": [ { "account_email": "example", "account_role": "example", "credential_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "credential_type": "example", "fill_pct": 1, "freshness": "example", "limit": 1, "measured_at": "2026-04-15T12:00:00Z", "measurement": "example", "minutes_to_refresh": 1, "plan_label": "example", "provider": "example", "reset_credits": 1, "resets_at": "2026-04-15T12:00:00Z", "scope": "example", "source": "example", "throttling_soon": true, "used": 1, "window_start": "2026-04-15T12:00:00Z", "window_type": "example" } ], "provider_inflight_reserved_usd": { "additionalProperty": 1 }, "provider_monthly_caps_usd": { "additionalProperty": 1 }, "provider_spend_usd": { "additionalProperty": 1 }, "remaining_usd": 1, "status": "example", "threshold_alerts_percent": [ 1 ], "warning_threshold_percent": 1 }, "git_credentials": [ { "account_email": "example", "expires_at": "2026-04-15T12:00:00Z", "fingerprint": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "key": "example", "provider": "example", "scope": "example" } ], "invites": [ { "email": "example", "role": "example" } ], "mailbox_credentials": [ { "account_email": "example", "expires_at": "2026-04-15T12:00:00Z", "fingerprint": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "key": "example", "provider": "example", "scope": "example" } ], "marketplace_installs": [ { "name": "example", "slug": "example", "update_available": true, "version": "example" } ], "members": [ { "admin": true, "approved": true, "display_name": "example", "email": "example", "role": "example" } ], "oauth_credentials": [ { "account_email": "example", "expires_at": "2026-04-15T12:00:00Z", "fingerprint": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "key": "example", "provider": "example", "scope": "example" } ], "projects": [ { "automations": [ { "enabled": true, "kind": "example", "pipeline_config": "example", "review_enabled": true } ], "git_provider": "example", "git_repo_url": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "key": "example", "name": "example" } ], "repo_sync": { "auto_push": true, "branch": "example", "credential_resource": "example", "last_sync_at": "2026-04-15T12:00:00Z", "last_sync_sha": "example", "repo_url": "example", "sync_mode": "example" }, "schedules": [ { "agent_profile_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "agent_type": "example", "cadence": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "interval_minutes": 1, "key": "example", "next_run_at": "2026-04-15T12:00:00Z", "status": "example", "title": "example" } ], "tasks": [ { "agent_profile_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "agent_type": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "key": "example", "project_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "status": "example", "title": "example" } ], "variables": [ { "created_at": "2026-04-15T12:00:00Z", "fingerprint": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "is_secret": true, "key": "example", "project_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "value": "example" } ], "workspace": { "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "name": "example", "owner_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "slug": "example" }}