Skip to content

Read instance settings (registration_mode, …).

GET
/v1/admin/settings
curl --request GET \
--url http://localhost:8080/v1/admin/settings \
--header 'Authorization: Bearer <token>'

OK.

Media typeapplication/json
object
settings
required
object
steam_preparation_enabled
required
boolean
default: true
steam_preparation_revision
required
string
/^[1-9][0-9]*$/
registration_mode
required
string
Allowed values: closed invite_only open
storage_provider
required

Managed-home backing store: auto = local when the session host has an effective home root, volume otherwise. Affects new homes only.

string
Allowed values: auto local volume
image_update_policy

P3 (image management). Instance-wide update policy applied by POST /v1/admin/images/sync. Column exists since migration 0054 (DDL default notify) but only reaches the wire from P3. Optional in the envelope so pre-P3 servers stay conformant.

string
Allowed values: manual notify auto
mic_capture_enabled
required

Microphone capture amendment (2026-08-02). Instance-wide gate for the POST /v1/sessions mic request. Default false (ship-dark). Server-enforced at launch; flipping it affects subsequent launches only.

boolean
library_discovery_interval_minutes
required

Admin-libraries amendment (2026-08-01). The operator-set scan interval, minutes, default 360. THE DATABASE COLUMN IS THE OPERATOR PATH AND THE ENV VAR IS AN OVERRIDE, NOT A DEFAULT: when QUASAR_LIBRARY_SCAN_INTERVAL is set it wins - and its documented 0 = hard-kill-regardless-of-the-database-flag semantics are unchanged. LibraryStatus.scan_interval_secs remains the RESOLVED value (database-then-env-override), and LibraryStatus.interval_overridden_by_env says which source won so a UI can grey a control the environment has pinned.

integer
>= 15 <= 10080
library_discovery_appdetails_enabled
required

Admin-libraries amendment (2026-08-01). The operator-set third-party appdetails lookup switch, default false - the same privacy decision QUASAR_STEAM_APPDETAILS_LOOKUP carried, now settable from the admin UI. Same override rule as the interval: a SET env var wins (a privacy-hardened deployment can pin it off in the environment), and LibraryStatus.appdetails_overridden_by_env reports when that happened.

boolean
library_discovery_enabled
required

Steam library discovery Phase 4 (migration 0045). THE MASTER SWITCH, AND THE ONLY SWITCH. Default false - ship-dark, the posture artwork already holds - and with it false the scheduler returns before its first query and the agent pull answers an empty list: no scan rows, no agent work, no third-party calls. Under operator decision 1 AUTO-PUBLISH IS THE BEHAVIOUR, NOT A MODE (there is no review queue), so there is deliberately no second “publish” toggle: its false branch would select a path that was never built. Read PER PASS and per request rather than cached at boot, so flipping it in the admin UI takes effect without a restart.

boolean
allowed_origins

First-run wizard v2 §S6e (migration 0064). The admin-editable signaling origin allow-list, normalized (scheme + lowercased host). THIS IS THE DATABASE COLUMN, NOT NECESSARILY WHAT /v1/signal ENFORCES: QUASAR_ALLOWED_ORIGINS, when SET, overrides it outright - including when set to the empty string, which is how a hardened deployment pins the list off. That override rule is what makes the migration a behavioural no-op on upgrade for every existing deployment. GET /v1/admin/access-check reports the RESOLVED list plus which source won, so a UI can grey out a control the environment has pinned - the same shape library_discovery_interval_minutes uses. AN EMPTY LIST IS NOT “DENY ALL”: /v1/signal still admits a same-origin request and a request with no Origin header at all, so a fresh instance with nothing configured works. Optional in the envelope so pre-amendment servers stay conformant.

Array<string>
release_channel

Platform-release amendment 1 (#104/#106, migration 0074); beta added by amendment 3 (#121, migration 0079); preview added by amendment 48 (#840, migration 0107). The instance’s platform- release channel: stable = tagged, noted releases; beta = those AND the prereleases among them; edge = whatever was last published from release_edge_branch, with no notes; preview = every build of develop, with its commit list. DEFAULT stable - an instance that has never been configured is not shown prereleases or branch builds. Read per request rather than at boot, so a switch needs no restart. Optional in the envelope so pre-amendment servers stay conformant.

string
Allowed values: stable beta edge preview
release_edge_branch

Platform-release amendment 1 (#104/#106, migration 0074). The branch the edge channel follows; default develop. Reported whatever the channel is (it selects nothing while the channel is stable) so a UI can render the control without a second read. Optional in the envelope so pre-amendment servers stay conformant.

string
release_check

Amendment 48 (#840, migration 0107). How often platform.release_detect runs. NULL, THE DEFAULT, FOLLOWS THE CHANNEL: daily on preview, weekly on every other channel. Optional in the envelope so pre-amendment servers stay conformant; a client reads absent as null.

string | null
Allowed values: daily weekly
release_webhook_enabled

Release notifications, ADDITIVE (#123, migration 0080). Whether a detected platform release is announced to release_webhook_url. Default false. Optional in the envelope so a pre-#123 server stays conformant; a client reads absent as false.

boolean
release_webhook_url

Release notifications, ADDITIVE (#123, migration 0080). The configured webhook URL, or “” when none is set. It is admin-only, as this whole envelope is. THE SIGNING SECRET IS NOT HERE and never will be: it is an instance_secrets row read through GET /v1/admin/secrets, which reports configured/readable and a masked hint, never a value.

string
platform_auto_apply

Unattended automatic apply, ADDITIVE (amendment 8, #122, migration 0081). Whether a detected platform release is applied without a click. Default false. Optional in the envelope so a pre-#122 server stays conformant; a client reads absent as false.

boolean
steam_warm_enabled

Warm Steam, ADDITIVE (amendment 39, #759, migration 0105). Default false. Optional in the envelope so a pre-amendment server stays conformant; absent reads as false.

boolean
steam_warm_rewarm

Amendment 39. Default library_open.

string
Allowed values: library_open next_steam_launch
steam_warm_idle_minutes

Amendment 39. Default 10.

integer
>= 1 <= 60
default_timezone

Amendment 49 (#845). Default UTC. Optional in the envelope so a pre-amendment server stays conformant.

string
default_language

Amendment 49. Default en-US.

string
default_region_format

Amendment 49. null = the same as the language.

string | null
default_keyboard
object
layout
required

One xkeyboard-config layout name, e.g. gb.

string
/^[A-Za-z0-9_-]{1,32}$/
variant
required

One variant of that layout, e.g. extd; empty for the basic variant.

string
/^[A-Za-z0-9_-]{0,64}$/
default_match_cursor
string
Allowed values: auto on off
default_mouse_sensitivity
number
default_raw_mouse
boolean
default_flip_scroll
boolean
default_nintendo_layout
boolean
updated_by
required
string | null format: uuid
updated_at
required
string format: date-time
Example
{
"settings": {
"steam_preparation_enabled": true,
"registration_mode": "closed",
"storage_provider": "auto",
"image_update_policy": "manual",
"release_channel": "stable",
"release_check": "daily",
"steam_warm_rewarm": "library_open",
"default_match_cursor": "auto"
}
}

Missing/invalid/expired/revoked token.

Media typeapplication/json
object
error
required
object
code
required

E.g. validation_failed, unauthorized, forbidden, not_found, conflict, session_quota_exceeded, home_in_use, home_not_provisioned, parent_app_disabled, profile_ineligible, profile_not_launchable_for_app, no_host_available, capacity_exhausted, host_not_ready, restart_required, stale_revision, unsupported_source, approval_superseded, approval_expired, attempt_conflict, cancel_too_late, retry_exhausted, home_conflict, placement_ineligible, inherited_placement, recovery_uncertain, rate_limited, internal. Open string, not an enum: new codes are additive and an unknown one falls through to a client’s generic per-status branch.

string
message
required
string
live_sessions

Present on restart_required.

integer
session_id

Steam library discovery Phase 3, ADDITIVE: present on home_in_use when the guard could name the CONFLICTING live session - the one already holding the home. It is here so the client can offer “go to your running session” with a link instead of a dead-end toast. OMITTED rather than empty when the conflict is known but the session is not, so a client branches on presence and never renders a link to nowhere. Also omitted when the holder is the caller’s parked session or released runtime (amendment 39). Load-bearing once derived tiles exist: the lock is held by the PARENT’s home, so a user who clicks a game tile can be refused because a DIFFERENT app (the Steam launcher, or another game from the same install) is running, and without the session id the refusal reads as a bug. See control-api.md §Derived tiles.

string format: uuid
derived_tiles

Steam library discovery Phase 3, ADDITIVE: present on the 409 conflict from DELETE /v1/apps/{id} when the app has derived tiles and ?delete_derived=true was not sent. A LIST, not a count - the point of the confirmation is that the admin sees what they are about to destroy. Capped; an empty array means the tiles could not be listed, never that there are none.

Array<object>
object
id
required
string format: uuid
name
required
string
reason

Amendment 40 (#602), ADDITIVE: a machine-readable cause under code. On 503 no_host_available, home_host_unavailable: the launch is pinned to the host that holds the caller’s home for this app (Amendment 53: or it is pinned to the host of the caller’s Steam home for a sharing launch) and that host is offline or no longer enrolled. Only an admin clears it, so a client does not spend its automatic retry on it. Names no host. Amendment 53 (#1001), on 409 home_in_use: steam_library_open_in_desktop (the holder mounts the Steam library as a shared home) or steam_game_running (the refused launch shares the library and a Steam session holds it); absent when the holder is already stopping. Open string: a client treats an unknown value as absent.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"live_sessions": 1,
"session_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"derived_tiles": [
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"name": "example"
}
],
"reason": "example"
}
}

Authenticated but insufficient role / not the owner (precedes resource lookup).

Media typeapplication/json
object
error
required
object
code
required

E.g. validation_failed, unauthorized, forbidden, not_found, conflict, session_quota_exceeded, home_in_use, home_not_provisioned, parent_app_disabled, profile_ineligible, profile_not_launchable_for_app, no_host_available, capacity_exhausted, host_not_ready, restart_required, stale_revision, unsupported_source, approval_superseded, approval_expired, attempt_conflict, cancel_too_late, retry_exhausted, home_conflict, placement_ineligible, inherited_placement, recovery_uncertain, rate_limited, internal. Open string, not an enum: new codes are additive and an unknown one falls through to a client’s generic per-status branch.

string
message
required
string
live_sessions

Present on restart_required.

integer
session_id

Steam library discovery Phase 3, ADDITIVE: present on home_in_use when the guard could name the CONFLICTING live session - the one already holding the home. It is here so the client can offer “go to your running session” with a link instead of a dead-end toast. OMITTED rather than empty when the conflict is known but the session is not, so a client branches on presence and never renders a link to nowhere. Also omitted when the holder is the caller’s parked session or released runtime (amendment 39). Load-bearing once derived tiles exist: the lock is held by the PARENT’s home, so a user who clicks a game tile can be refused because a DIFFERENT app (the Steam launcher, or another game from the same install) is running, and without the session id the refusal reads as a bug. See control-api.md §Derived tiles.

string format: uuid
derived_tiles

Steam library discovery Phase 3, ADDITIVE: present on the 409 conflict from DELETE /v1/apps/{id} when the app has derived tiles and ?delete_derived=true was not sent. A LIST, not a count - the point of the confirmation is that the admin sees what they are about to destroy. Capped; an empty array means the tiles could not be listed, never that there are none.

Array<object>
object
id
required
string format: uuid
name
required
string
reason

Amendment 40 (#602), ADDITIVE: a machine-readable cause under code. On 503 no_host_available, home_host_unavailable: the launch is pinned to the host that holds the caller’s home for this app (Amendment 53: or it is pinned to the host of the caller’s Steam home for a sharing launch) and that host is offline or no longer enrolled. Only an admin clears it, so a client does not spend its automatic retry on it. Names no host. Amendment 53 (#1001), on 409 home_in_use: steam_library_open_in_desktop (the holder mounts the Steam library as a shared home) or steam_game_running (the refused launch shares the library and a Steam session holds it); absent when the holder is already stopping. Open string: a client treats an unknown value as absent.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"live_sessions": 1,
"session_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"derived_tiles": [
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"name": "example"
}
],
"reason": "example"
}
}