Skip to content

The Verdict for a session — state, evidence, reason, window, clock, tier, falsifiers.

GET
/v1/admin/sessions/{id}/verdict
curl --request GET \
--url http://localhost:8080/v1/admin/sessions/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/verdict \
--header 'Authorization: Bearer <token>'

ST-09. Observability only; reading a verdict never changes a session.

id
required
string format: uuid
from
integer

Window start, unix ms. Same default (5 min) and clamp ([2,10] min) as the diagnostic bundle.

to
integer

Window end, unix ms.

OK.

Media typeapplication/json

The single stream-health judgement as a value (ST-09): state + prose evidence + the falsifiers that would overturn it + window/clock/tier. Observational only, no session authority. An unknown verdict string is DATA to a consumer.

object
verdict
required

The control plane owns this vocabulary and grows it; the enum below is today’s set, not a closed world.

string
Allowed values: likely_encoder_saturation likely_network_congestion likely_client_presentation_limit nominal indeterminate_client_hidden unknown
evidence
required
Array<string>
reason
required

One sentence.

string
window
required
object
from_ms
required
integer
to_ms
required
integer
n_host
required

Agent samples in the window.

integer
n_client
required

Browser samples in the window.

integer
warmup_excluded_ms

Milliseconds at the head of the window excluded from warm-up-sensitive rules (hitch detection and the encoder.fps floor). 0 when nothing was excluded.

integer
clock
required
object
quality
required
string
Allowed values: measured unmeasured
offset_ms
number
uncertainty_ms
number
applied

Whether the offset was actually applied to the client-clock series before the rules ran. False for an unmeasured clock, in which case every cross-source coincidence claim is downgraded and says so.

boolean
age_ms

Now minus the clock’s measured_at (ms). Staleness is visible: the client re-posts the offset while it drifts, so a large age means the estimate stopped being refreshed.

integer
evidence_tier
required
string
Allowed values: full host_only client_only insufficient
falsifiers
required
Array<object>

One named, estimator-qualified number the verdict relies on (ST-09). holds is whether the data satisfies the condition; a series with no samples reports value null, n 0, holds false and a note. Some falsifiers are INFORMATIVE — client.present_beat_fraction is compared against the upper bound of its own unit, so it cannot fail; it is in the set to carry the number and the note that explains it.

object
name
required

Taxonomy series name, e.g. encoder.fps.

string
estimator
required
string
Allowed values: p10 p95 max delta mean any count_ge_threshold
value
required

Null when the series had no samples in the window.

number | null
op
required
string
Allowed values: >= <= > < ==
threshold
required
number
unit
required
string
Allowed values: fps ms count bool fraction
n
required

Samples the estimator consumed.

integer
holds
required
boolean
note
string
thresholds_version
required
string
Example
{
"verdict": "likely_encoder_saturation",
"clock": {
"quality": "measured"
},
"evidence_tier": "full",
"falsifiers": [
{
"estimator": "p10",
"op": ">=",
"unit": "fps"
}
]
}

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"
}
]
}
}

No such resource.

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"
}
]
}
}