Skip to content

List all sessions (oversight).

GET
/v1/admin/sessions
curl --request GET \
--url 'http://localhost:8080/v1/admin/sessions?state=all' \
--header 'Authorization: Bearer <token>'
state
string
default: all
Allowed values: all active ended failed

active = pending, assigned, starting, running, stopping - every NON-TERMINAL state. That is one state wider than the reservation-holding set (pending holds no GPU yet), because “live sessions” on an oversight page means “not finished”, not “consuming a slot”. ended = stopped only. failed = failed only. all (the default) filters nothing. An unrecognized value is 400 validation_failed with code invalid_state, never a silent fallback to all: a filter that quietly stops filtering shows an operator sessions they asked not to see.

OK.

Media typeapplication/json
object
items
Array
object
id
required
string format: uuid
user_id
required
string format: uuid
app_id
required
string format: uuid
host_id
required
string | null format: uuid
state
required
string
Allowed values: pending assigned starting running stopping stopped failed
state_detail
required
string | null
error_message
required
string | null
failure_code
required

First-run-experience §S5. Machine-readable classification of a terminal failure - “app_exited_early” today. Sits beside error_message (free-text prose that may be rewritten freely); the UI branches on THIS. Always serialized; null unless a failure warranted it.

string | null
app_log_tail
required

First-run-experience §S5. The app container’s own captured log tail (newline-joined, oldest first, ~100 lines bound) - the only surviving copy, since app containers run –rm. Always serialized; null unless a failure warranted capturing it. Rendered preformatted, distinct from error_message’s prose rendering.

string | null
profile_id
required

The profile the session was launched from; null for a legacy/tier/override launch. UI-P4: this is now a LAUNCH PROFILE id, i.e. the USER’S PICK. The rung it resolved to is stream_profile_id.

string | null
stream_profile_id
required

UI-P4: the RUNG this launch resolved to (e.g. “1080p60-h264”). Always serialized; null for every pre-UI-P4 session and for any legacy/tier/override/console launch. profile_id answers “what did the user pick”, this answers “what did they get” - and because a rung carries its own resolution, the two can legitimately disagree about width/height/fps/ bitrate. The stream block below is always the truth for the running session.

string | null
stream
required
object
width
required
integer
height
required
integer
fps
required
integer
bitrate_kbps
required
integer
h264_profile
string
Allowed values: constrained-baseline baseline main high
codec

Multi-codec: the resolved session video codec on session.stream; absent on an app’s display_stream. Additive; h264 for every pre-multi-codec session. h264_profile applies only when codec is h264.

string
Allowed values: h264 h265 av1
playout0_ms

AS-02: tier-selected initial receiver playout target (ms) on session.stream; absent on an app’s display_stream.

integer
mic

Microphone capture (2026-08-02): the GRANTED state on session.stream (request mic AND instance mic_capture_enabled); absent on an app’s display_stream and on pre-amendment sessions (absent = false).

boolean
external_width

Session-display-stream (approved 2026-08-16) (2026-08-16, approved — PR #15). Current EXTERNAL (encoded/streamed) width on session.stream; absent on an app’s display_stream. PRESENT WHENEVER THE CONTROL PLANE KNOWS the current external size — i.e. it has seen a 202 from PATCH /v1/sessions/{id}/display or a session_metrics sample reporting it — INCLUDING when that size equals the launch width/height. ABSENT MEANS UNKNOWN (a fresh control plane, or no such signal yet for this session), NOT “at launch size” — do not infer launch size from absence. Ephemeral, in-memory control-plane cache of the last-known value (agent session_metrics is the authoritative source), lost on a control-plane restart until the next 202 or session_metrics sample repopulates it. See control-api.md for the INTERNAL-vs-EXTERNAL vocabulary.

integer
external_height

Session-display-stream (approved 2026-08-16). Pairs with external_width; see its description.

integer
external_resize_supported

Session-display-stream (approved 2026-08-16). Whether the assigned host’s encoder can live-resize the stream at all (readback of agent-api.md session_metrics.external_resize_supported). Absent until an amendment-aware agent reports = unknown, never false.

boolean
external_owner

Abr-resolution-fps-ladder (approved 2026-08-16) amendment (2026-08-16, approved — PR #15). Who currently owns the live external size on session.stream: “auto” (the host’s ABR resolution ladder) or “pinned” (a PATCH /v1/sessions/{id}/display stream_width/ stream_height set it to a non-launch size, which suspends the ladder for the rest of the session or until released). Readback of agent-api.md session_metrics.external_owner. PRESENT ONLY WHEN KNOWN AND external_width/ external_height differ from the launch width/height — mirrors external_width’s presence rule, since the agent reports external_owner only in that same window. Absent on every pre-amendment session and while the external size sits at launch.

string
Allowed values: auto pinned
rungs

Session-display-stream (approved 2026-08-16). The fixed, aspect-ratio-filtered table of [width,height] pairs this session’s stream_width/stream_height may be set to via PATCH /v1/sessions/{id}/display (always <= the launch size, launch size always included). Always present on session.stream for a running session; absent on an app’s display_stream. Not the admin-configured stream-profile “rungs” (AS10-01) — a separate, fixed table unrelated to the admin encode-rung catalog. 21:9 family membership is by a set of reduced ratios {43:18, 64:27, 7:3} — 3440x1440 reduces to 43:18, 2560x1080 to 64:27 — control-api.md’s table is the reference, not a computed tolerance.

Array<Array<integer>>
codec_decision
required
One of:

UI-P6: how this session’s rung/codec was resolved. Persisted at launch and echoed on every session body; null for every pre-UI-P6 session and for any launch that walked no rung chain (console, or a legacy/tier launch that resolved no launch profile). THE THREE OUTCOMES ARE DELIBERATELY DISTINGUISHABLE and a client must not collapse them, because stream.codec is identical in all three. Won on merit: selected with rejected_by=null, clamps_bypassed=false, floor=false, override=null. Operator override: override names the forced codec and the selected rung has clamps_bypassed=true with rejected_by=null (it SKIPPED clamps 2/3, 4, 5 and 6 rather than surviving them). Floor: floor=true and the selected rung is clamps_bypassed=true WHILE STILL CARRYING the rejected_by that killed it - it was dispatched despite being rejected. floor and clamps_bypassed answer different questions (“did anything survive?” vs “was THIS rung measured?”) and the override case sets the second without the first; do not merge them.

object
result_rung
required

The dispatched rung id.

string
result_codec
required

Multi-codec: the WIRE session video codec (h265 is HEVC). Resolved server-side at launch; the client answers the single codec the host offers. Distinct from CatalogCodec, which spells HEVC ‘hevc’.

string
Allowed values: h264 h265 av1
override
required
One of:

Multi-codec: the WIRE session video codec (h265 is HEVC). Resolved server-side at launch; the client answers the single codec the host offers. Distinct from CatalogCodec, which spells HEVC ‘hevc’.

string
Allowed values: h264 h265 av1
floor
required

NO rung survived the clamp chain and the unconditional h264 floor fired.

boolean
considered
required

Every rung WALKED, in position order. The walk stops at the first survivor, so a clean top-rung win lists exactly one entry - that is the whole decision, not a truncation.

Array<object>

UI-P6: one rung’s verdict in the resolution walk.

object
rung_id
required
string
codec
required

Wire vocabulary (h264|h265|av1), except when rejected_by is unknown_codec, where it is the raw unmappable catalog value - the only useful thing to show for a hand-edited row.

string
rejected_by
required
One of:

UI-P6: the clamp that rejected a rung during the walk. Treat this set as OPEN - render an unrecognised value rather than assuming the list is closed. host_encoder=clamp 1, client_decode=clamp 2/3 (codec), decode_height=clamp 2/3 (resolution), decode_history=clamp 4, hardware_encoder=clamp 5, encoder_throughput=clamp 6 (#506: the host’s reported sustained encode throughput for this codec cannot carry the LAUNCH-EFFECTIVE width x height x fps - the rung’s values with any explicit stream.* size override applied - see agent-api.md capacity.codec_throughput; a host that reports no hint never rejects this way), unknown_codec=a rung whose catalog codec does not map (hand-edited data; codec then carries the raw catalog value).

string
Allowed values: host_encoder client_decode decode_height decode_history hardware_encoder encoder_throughput unknown_codec
selected
required

The rung that was actually dispatched. Exactly one entry per recorded decision.

boolean
clamps_bypassed
required

This rung was dispatched WITHOUT being measured against the full clamp chain - the clamp-0 override path (clamps 2/3/4/5/6 skipped) or the floor (every clamp skipped). Never set on a rung that won the walk.

boolean
negotiated_codec
required

UI-P6: the wire codec the CLIENT reports it is actually decoding (normalised getStats mimeType), beside stream.codec, which is what the SERVER resolved. They should agree; when they do not, that is how a silent fallback or a mis-negotiated m-line presents, so both are kept and neither is reconciled away. NOT constrained to the Codec enum - a value the server never resolves (vp9) is preserved rather than dropped, because it is the loudest disagreement there is. Always serialized; null until the client reports one.

string | null
health_state

AS10-06: computed stream-health classification; present only when the session is running/unsustainable.

string
Allowed values: healthy network_degrading abr_at_floor client_decode_degrading client_presentation_degrading unsustainable failed
health_reason

AS10-06: optional human explanation accompanying a degraded health state.

string
app_launch_state

Steam game-exit lifecycle amendment (2026-08-02): coarse in-container application launch state last reported by the agent (agent-api.md session_metrics. app_launch_state, the normative definition). Read-only; there is no request field. OMITTED when the app image does not report launch state - absence means UNKNOWN, and a client must treat an absent field and an unrecognised value identically and fall back to transport-level readiness. A hint and a metric, never a session-state authority and never access control: state remains the only progress signal.

string
Allowed values: starting client_only game_running game_exited
created_at
required
string format: date-time
started_at
required
string | null format: date-time
ended_at
required
string | null format: date-time
latest_metrics

Latest_metrics on each session list item — present only when telemetry exists.

object
agent

One row from GET /v1/admin/sessions/{id}/metrics.

object
source
required
string
Allowed values: agent browser
ts_unix_ms
required
integer
metrics
required
One of:

Metrics from the node-agent encode pipeline.

object
fps
number
bitrate_kbps
integer
encode_ms
number
frames_encoded
integer
frames_dropped
integer
encode_ms_p50
number
encode_ms_p95
number
encode_ms_max
number
overlay_frames
integer
abr_floor_kbps

The governor’s live floor, sent ONLY when the ladder has moved it off the launch floor. Absent means ‘the floor the session launched with’, never ‘unknown’. Uncurated: readable via GET …/metrics, not in the diagnostic lens.

number
abr_mode

The ABR mode this session is actually running (‘smooth’ | ‘protective’ | ‘off’). Reported rather than inferred: deriving it from setpoint presence was wrong for ‘off’, where rtpgccbwe stays attached. Uncurated (a label, not a series).

string
abr_setpoint_kbps

The in-session ABR governor’s CURRENT CBR setpoint at drain time — a level, not a window average. Absent when ABR is disarmed.

number
adaptation_state

The agent’s own per-window bottleneck label (‘healthy’ | ‘network_congested’ | ‘encoder_saturated’ | ‘unknown’). SIGNAL-ONLY — it changes no ABR behaviour, and it can never say ‘client_presentation_limited’ because the agent never sees browser data (invariant #1).

string
compositor_fps

Frames emitted by waylanddisplaysrc per second, BEFORE caps normalisation and interpipe. The first stage where a rate can differ from what the app painted.

number
compositor_pts_delta_p50_ms

P50 spacing of consecutive compositor buffer PTS. NOMINAL, NOT REALIZED: PTS come off the shared pipeline clock at the negotiated rate, so this sits at a flat ~16.668 ms at 60 fps however badly the wall-clock cadence jitters. For realized emit spacing read probe_compositor_frame_interval_p95_ms.

number
compositor_pts_delta_p95_ms

P95 of the same NOMINAL PTS spacing. Same trap as the p50: a healthy-looking 16.7 here is not evidence the compositor emitted on time.

number
external_owner

Who owns the external size — ‘auto’ (the ladder) or ‘pinned’ (a user/admin PATCH). Rides the size echo, so it is present only while the size is off the launch size.

string
external_resize_supported

Whether this session’s encode path can change the external resolution live. Always sent by a capable agent; ABSENT MEANS UNKNOWN, not false.

boolean
gcc_estimate_kbps

The raw rtpgccbwe bandwidth estimate BEFORE the governor’s EWMA / deadband / step logic. The delta against abr_setpoint_kbps is the governor’s own smoothing contribution.

number
interpipe_queue_drops

Leaky-queue overruns in the window. Host-side loss BEFORE the encoder; distinct from frames_dropped (encoder) and from the client’s frames_dropped (presentation).

integer
interpipe_queue_dwell_p50_ms

P50 time a buffer spent between the interpipe sink and src. Omitted when nothing traversed.

number
interpipe_queue_dwell_p95_ms

P95 interpipe dwell — where a queue that is filling shows up before drops do.

number
interpipe_queue_level_max

Deepest the interpipe queue got, in buffers, since the previous drain reset it. A max, so one burst sets it for the whole window — which is the point.

integer
ladder_fps

The encoded frame rate the fps rung currently asks for. Present only BELOW the launch rate; only a 120 fps session can ever carry it.

integer
ladder_res_rung

The ladder’s current external-resolution rung index (0 = launch). Present only when non-zero.

integer
ladder_speed_bias

The ABR ladder’s current encoder speed-bias rung. Present only when non-zero — absent is ‘baseline quality posture’, never ‘unknown’.

integer
probe_capture_to_enc_in_p50_ms

Host-stage latency probe: p50 of compositor src to encoder sink — the pre-encode transit the interpipe hides. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_capture_to_enc_in_p95_ms

Host-stage latency probe: p95 of compositor src to encoder sink — the pre-encode transit the interpipe hides. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_compositor_frame_interval_p95_ms

P95 REALIZED wall-clock spacing of compositor emits — the honest counterpart to the nominal compositor_pts_delta_p95_ms. Probe-gated.

number
probe_enc_out_to_send_p50_ms

Host-stage latency probe: p50 of encoder src to the pre-SRTP seam, FIFO-paired and guarded at one frame period so a persistent off-by-one cannot inflate every sample. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_enc_out_to_send_p95_ms

Host-stage latency probe: p95 of encoder src to the pre-SRTP seam, FIFO-paired and guarded at one frame period so a persistent off-by-one cannot inflate every sample. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pay_to_send_p50_ms

Host-stage latency probe: p50 of payloader to the pre-SRTP seam, keyed on the RTP timestamp rather than on order, so unlike enc_out_to_send it cannot desync and keeps its tail. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pay_to_send_p95_ms

Host-stage latency probe: p95 of payloader to the pre-SRTP seam, keyed on the RTP timestamp rather than on order, so unlike enc_out_to_send it cannot desync and keeps its tail. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pts_to_emit_p50_ms

Host-stage latency probe: p50 of the compositor’s own PTS-to-emit hold, from Element::current_running_time. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pts_to_emit_p95_ms

Host-stage latency probe: p95 of the compositor’s own PTS-to-emit hold, from Element::current_running_time. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pts_unmatched

Encoder-input PTS that never matched a compositor-emit ring entry — the correlation key stopped surviving to the encoder. Probe-gated.

integer
probe_send_desyncs

Encoder-src entries dropped from the S3 pairing for exceeding one frame period of age — the count that says enc_out_to_send’s tail is truncated rather than clean. Probe-gated.

integer
render_height

The compositor’s CURRENT app-facing wl_output logical height; see render_width.

integer
render_width

The compositor’s CURRENT app-facing wl_output logical width. Present only when it differs from the session’s pinned stream size. With render_height and ui_scale this is the ONLY authoritative readback of live render resolution — the value lives nowhere else.

integer
rtp_bitrate_kbps

RTP packet bitrate before WebRTC transport overhead (SRTP, RTX, FEC). Always a little above bitrate_kbps; a large gap is retransmission.

number
rtp_fps

RTP access units completed per second, counted on marker packets — the last host-side rate before the wire.

number
source_fps

New buffers committed by the MAPPED FULLSCREEN app top-level per second. Cursor, popup, subsurface and configure-only commits are excluded, so this is the app’s own paint rate, not Wayland traffic.

number
stream_height

The session’s CURRENT external (encoded) height; see stream_width.

integer
stream_width

The session’s CURRENT external (encoded) width, read back from the encode graph’s NEGOTIATED caps — not from the last request. Present only when != the launch size, so absent means ‘at launch size’, never ‘unknown’.

integer
ui_scale

The compositor’s CURRENT fractional-scale preferred_scale. Present only when != 1.0.

number
browser

One row from GET /v1/admin/sessions/{id}/metrics.

object
source
required
string
Allowed values: agent browser
ts_unix_ms
required
integer
metrics
required
One of:

Metrics from the node-agent encode pipeline.

object
fps
number
bitrate_kbps
integer
encode_ms
number
frames_encoded
integer
frames_dropped
integer
encode_ms_p50
number
encode_ms_p95
number
encode_ms_max
number
overlay_frames
integer
abr_floor_kbps

The governor’s live floor, sent ONLY when the ladder has moved it off the launch floor. Absent means ‘the floor the session launched with’, never ‘unknown’. Uncurated: readable via GET …/metrics, not in the diagnostic lens.

number
abr_mode

The ABR mode this session is actually running (‘smooth’ | ‘protective’ | ‘off’). Reported rather than inferred: deriving it from setpoint presence was wrong for ‘off’, where rtpgccbwe stays attached. Uncurated (a label, not a series).

string
abr_setpoint_kbps

The in-session ABR governor’s CURRENT CBR setpoint at drain time — a level, not a window average. Absent when ABR is disarmed.

number
adaptation_state

The agent’s own per-window bottleneck label (‘healthy’ | ‘network_congested’ | ‘encoder_saturated’ | ‘unknown’). SIGNAL-ONLY — it changes no ABR behaviour, and it can never say ‘client_presentation_limited’ because the agent never sees browser data (invariant #1).

string
compositor_fps

Frames emitted by waylanddisplaysrc per second, BEFORE caps normalisation and interpipe. The first stage where a rate can differ from what the app painted.

number
compositor_pts_delta_p50_ms

P50 spacing of consecutive compositor buffer PTS. NOMINAL, NOT REALIZED: PTS come off the shared pipeline clock at the negotiated rate, so this sits at a flat ~16.668 ms at 60 fps however badly the wall-clock cadence jitters. For realized emit spacing read probe_compositor_frame_interval_p95_ms.

number
compositor_pts_delta_p95_ms

P95 of the same NOMINAL PTS spacing. Same trap as the p50: a healthy-looking 16.7 here is not evidence the compositor emitted on time.

number
external_owner

Who owns the external size — ‘auto’ (the ladder) or ‘pinned’ (a user/admin PATCH). Rides the size echo, so it is present only while the size is off the launch size.

string
external_resize_supported

Whether this session’s encode path can change the external resolution live. Always sent by a capable agent; ABSENT MEANS UNKNOWN, not false.

boolean
gcc_estimate_kbps

The raw rtpgccbwe bandwidth estimate BEFORE the governor’s EWMA / deadband / step logic. The delta against abr_setpoint_kbps is the governor’s own smoothing contribution.

number
interpipe_queue_drops

Leaky-queue overruns in the window. Host-side loss BEFORE the encoder; distinct from frames_dropped (encoder) and from the client’s frames_dropped (presentation).

integer
interpipe_queue_dwell_p50_ms

P50 time a buffer spent between the interpipe sink and src. Omitted when nothing traversed.

number
interpipe_queue_dwell_p95_ms

P95 interpipe dwell — where a queue that is filling shows up before drops do.

number
interpipe_queue_level_max

Deepest the interpipe queue got, in buffers, since the previous drain reset it. A max, so one burst sets it for the whole window — which is the point.

integer
ladder_fps

The encoded frame rate the fps rung currently asks for. Present only BELOW the launch rate; only a 120 fps session can ever carry it.

integer
ladder_res_rung

The ladder’s current external-resolution rung index (0 = launch). Present only when non-zero.

integer
ladder_speed_bias

The ABR ladder’s current encoder speed-bias rung. Present only when non-zero — absent is ‘baseline quality posture’, never ‘unknown’.

integer
probe_capture_to_enc_in_p50_ms

Host-stage latency probe: p50 of compositor src to encoder sink — the pre-encode transit the interpipe hides. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_capture_to_enc_in_p95_ms

Host-stage latency probe: p95 of compositor src to encoder sink — the pre-encode transit the interpipe hides. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_compositor_frame_interval_p95_ms

P95 REALIZED wall-clock spacing of compositor emits — the honest counterpart to the nominal compositor_pts_delta_p95_ms. Probe-gated.

number
probe_enc_out_to_send_p50_ms

Host-stage latency probe: p50 of encoder src to the pre-SRTP seam, FIFO-paired and guarded at one frame period so a persistent off-by-one cannot inflate every sample. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_enc_out_to_send_p95_ms

Host-stage latency probe: p95 of encoder src to the pre-SRTP seam, FIFO-paired and guarded at one frame period so a persistent off-by-one cannot inflate every sample. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pay_to_send_p50_ms

Host-stage latency probe: p50 of payloader to the pre-SRTP seam, keyed on the RTP timestamp rather than on order, so unlike enc_out_to_send it cannot desync and keeps its tail. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pay_to_send_p95_ms

Host-stage latency probe: p95 of payloader to the pre-SRTP seam, keyed on the RTP timestamp rather than on order, so unlike enc_out_to_send it cannot desync and keeps its tail. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pts_to_emit_p50_ms

Host-stage latency probe: p50 of the compositor’s own PTS-to-emit hold, from Element::current_running_time. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pts_to_emit_p95_ms

Host-stage latency probe: p95 of the compositor’s own PTS-to-emit hold, from Element::current_running_time. Present ONLY when QUASAR_LATENCY_PROBE is on AND that stage sampled this window — absent means not measured, never 0. Observability only: nothing in the control plane may key on it.

number
probe_pts_unmatched

Encoder-input PTS that never matched a compositor-emit ring entry — the correlation key stopped surviving to the encoder. Probe-gated.

integer
probe_send_desyncs

Encoder-src entries dropped from the S3 pairing for exceeding one frame period of age — the count that says enc_out_to_send’s tail is truncated rather than clean. Probe-gated.

integer
render_height

The compositor’s CURRENT app-facing wl_output logical height; see render_width.

integer
render_width

The compositor’s CURRENT app-facing wl_output logical width. Present only when it differs from the session’s pinned stream size. With render_height and ui_scale this is the ONLY authoritative readback of live render resolution — the value lives nowhere else.

integer
rtp_bitrate_kbps

RTP packet bitrate before WebRTC transport overhead (SRTP, RTX, FEC). Always a little above bitrate_kbps; a large gap is retransmission.

number
rtp_fps

RTP access units completed per second, counted on marker packets — the last host-side rate before the wire.

number
source_fps

New buffers committed by the MAPPED FULLSCREEN app top-level per second. Cursor, popup, subsurface and configure-only commits are excluded, so this is the app’s own paint rate, not Wayland traffic.

number
stream_height

The session’s CURRENT external (encoded) height; see stream_width.

integer
stream_width

The session’s CURRENT external (encoded) width, read back from the encode graph’s NEGOTIATED caps — not from the last request. Present only when != the launch size, so absent means ‘at launch size’, never ‘unknown’.

integer
ui_scale

The compositor’s CURRENT fractional-scale preferred_scale. Present only when != 1.0.

number
username

Users.username for user_id. Omitted when the user row is gone.

string
app_name

Apps.name for app_id. Omitted when the app row is gone.

string
host_name

Hosts.node_name for host_id. Omitted while the session is unassigned (host_id is null) and when the host row is gone.

string
next_cursor
string | null
Example
{
"items": [
{
"state": "pending",
"stream": {
"h264_profile": "constrained-baseline",
"codec": "h264",
"external_owner": "auto"
},
"codec_decision": {
"result_codec": "h264",
"override": "h264",
"considered": [
{
"rejected_by": "host_encoder"
}
]
},
"health_state": "healthy",
"app_launch_state": "starting",
"latest_metrics": {
"agent": {
"source": "agent"
},
"browser": {
"source": "agent"
}
}
}
]
}

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, restart_required, 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. 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
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"
}
]
}
}

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, restart_required, 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. 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
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"
}
]
}
}