A valid request URL is required to generate request examples{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "unauthorized",
"reason": "missing_credentials",
"hint": "<string>"
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "rate_limited",
"message": "<string>"
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}Look at a device's screen
The current screen, as raw image bytes. The media type says which encoding.
YOU DO NOT NEED THE LEASE. Any credential in the organisation that can see the device can watch it, whoever is holding it right now. That is the difference between this route and every other way to reach a screen: the MCP screenshot tool takes a leaseId and refuses without it, and a run’s /vrx frame endpoint is bound to that one run. This route exists so a person can see what a device is doing before deciding whether to interrupt it.
Watching changes nothing, so it writes no receipt. It also returns no frameId, and that is not an omission: a frame id is the token you bind an action to, and taking one here would make it the device’s current frame and cause the next action by whoever actually holds the lease to be refused as stale. If you intend to act, acquire the device and take a screenshot through the tool that issues frames.
An offline device answers 409, not 404. It exists; there is simply no screen to read at the moment. A device your organisation does not own answers 404 exactly as an id that never existed does.
Responses are no-store. A screen is live state and a cached one is worse than none.
Hosted deployments only. A local checkout does not mount this route, so calling it there is a 404.
A valid request URL is required to generate request examples{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "unauthorized",
"reason": "missing_credentials",
"hint": "<string>"
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "rate_limited",
"message": "<string>"
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}Authorizations
The control surface credential. Send Authorization: Bearer <token>.
Two kinds of token are accepted and they are told apart by shape, not by a separate header. A token beginning pbk_ is an org scoped API key, whose public half and secret half are generated together and of which only a hash of the secret is ever stored; anything else is treated as an OAuth 2.1 access token and verified against the authorization server's keys.
Both resolve to the same context: an org, a principal and a set of scopes. Nothing downstream branches on which channel you used, with one deliberate exception, key management, which requires a signed-in person so that a key can never mint another key.
Scopes are enforced when MCP tools are REGISTERED rather than when they are called, so a tool your credential cannot use is absent from tools/list rather than refused mid gesture.
Path Parameters
The deviceId from a listing.
Response
The screen, as image bytes. The media type says which encoding.