Skip to main content
GET
Error

Authorizations

Authorization
string
header
required

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

runId
string
required

The runId returned when the run was started, or the run's agentRunId (it starts run_).

Query Parameters

waitMs
integer

How long to wait for a state change, in whole milliseconds, 0 to 25000 (25 seconds). A longer wait is refused, not shortened: loop on the call instead of holding one open.

Required range: 0 <= x <= 25000
sinceState
enum<string>

Return as soon as the state is no longer this one. Without it, the call returns immediately. Must be one of the run states: an unknown value is refused rather than treated as a state the run is never in. A run state.

Available options:
queued,
running,
needs_user_control,
paused,
succeeded,
failed,
canceled

Response

The run.

The public projection of a run, and who started it. The run token is deliberately absent: it is returned once, when the run is started, and never again.

runId
string
required
agentRunId
string
required
deviceId
string
required
goal
string
required

What the run was asked to accomplish, in the words it was started with.

executor
enum<string>
required

Who drives this run: phonebase (we do) or self_hosted (your worker does).

Available options:
phonebase,
self_hosted
state
enum<string>
required

Where the run is now. succeeded, failed and canceled are terminal. paused means a person put the agent on hold: the worker's channels are shut until Resume. It is not needs_user_control, which can mean the agent is asking for help or an interrupted hosted run is waiting for explicit continuation. A non-null recovery distinguishes the latter.

Available options:
queued,
running,
needs_user_control,
paused,
succeeded,
failed,
canceled
stepSeq
integer
required

Metered steps issued so far. One step is one frame served.

maxSteps
integer
required

The run's step ceiling.

deadlineAt
string<date-time> | null
required

Absolute wall clock deadline, or null when the stored deadline is not a renderable instant. FROZEN while the run is paused: the time the agent spends on hold is not charged to the run, and resuming slides this forward by however long the hold lasted. It is null during recovery waiting; recovery.remainingMs reports the saved time budget.

createdAt
string<date-time>
required
updatedAt
string<date-time>
required
workerFirstContactAt
string<date-time> | null
required

When a self-hosted worker first reached this run, or null when none ever did. On a self_hosted run you supply the worker, and one that stays queued with null here is waiting for it. A phonebase run is driven in process and never sets this.

initiator
object
required

WHO. The same shape answers three questions: who took an action (Receipt.actor), who is holding a device (Lease.holder), and who started a run (RunView.initiator). One shape on purpose, so the three can never disagree about what a given credential is called.

scheduleId
string | null
required

The schedule that started this run, or null when a person or a key did. Present and null rather than absent, so you can tell those apart from an older server that does not say.

pausedAt
string<date-time> | null
required

When a person put the run on hold, or null when it is not on hold. Present and null rather than absent, so a consumer can tell "not on hold" from an older server that does not report it.

manualControlUntil
string<date-time> | null
required

When the hold ends, or null when the run is not paused. This is the clock that runs while the run is on hold, not deadlineAt. Past it, a run nobody resumed is canceled with an explanation in detail; no new failure reason is used. The name is kept from when a hold was a person's manual control window; a person needs no window to act on the device now.

lastFrame
object | null
required

The last frame this run was served, or null when it has been served none. On a finished run this is the frame the model's report was written from, because finish_run ends the turn and nothing is captured after it, so a reader can put what the model said next to the screen it read that off. viewport is the frame's own pixel geometry, which is the coordinate basis it was captured in and not necessarily the device's current size.

recovery
object | null

An interrupted hosted run waiting for explicit continuation, or null. Older servers may omit this field. Progress and remaining budget are preserved; no action is replayed automatically.

reason
enum<string>

Why the run ended, when it did not simply succeed.

Available options:
worker_reported_failure,
budget_exhausted,
deadline_exceeded,
canceled_by_caller,
lease_lost,
interrupted_by_restart
detail
string

Free text about how the run ended. A worker's own report, or, when the run hit its deadline, the control plane's explanation of which kind of timeout it was.