# Events

Every run records an ordered stream of events in the open [event protocol](/docs/standard/events), `protocol: 0`, stored verbatim: `protocol`, `run_id`, `sequence`, `timestamp`, `type`, `runner`, and `data`. Sequences are gapless from 1. Nothing is appended after a terminal event (`run.completed`, `run.failed`, `run.cancelled`): whichever lands first wins, so a cancel racing a completion records exactly one ending.

## Read events

`GET /v1/runs/:id/events`

Key `runs:read`, or session: member.

| Query   | Type                | Meaning                                       |
| ------- | ------------------- | --------------------------------------------- |
| `after` | integer, at least 0 | Return events after this sequence. Default 0. |
| `limit` | integer, 1 to 500   | Default 100.                                  |

Response `200`, with `cache-control: no-store`:

```json
{
    "events": [
        {
            "protocol": 0,
            "run_id": "wb_d8m99qyw2e4qqhitfff63f1n",
            "sequence": 1,
            "timestamp": "2026-10-28T14:05:40.112Z",
            "type": "run.started",
            "runner": "opencode",
            "data": {}
        }
    ],
    "next": 1
}
```

`next` is the sequence to pass as `after` for the following page.

## Stream events

Send the same request with `Upgrade: websocket` to open a stream. The server replays every event after `after`, then sends each new event as one JSON text frame, and closes with code 1000 after the terminal event.

- The stream is read only. Send commands over HTTP; see [Commands](/docs/api/commands).
- A socket lives 15 minutes on the credential it connected with. After that, the next frame closes it with code 4001 (`reauthenticate`) instead; connect again at once with the last sequence you saw as `after`.
- A client that disconnects reconnects with the last sequence it saw.
- A WebSocket upgrade authenticated by a session cookie must come from the dashboard origin, or it is refused with 403. A key with an `Authorization` header needs no origin.

## What events carry

Events never contain secret values. Before an event is stored, every value injected into the run's sandbox is replaced with `[redacted]`: the organization's secrets the run received, the runner's password, the image pull token, and the run's GitHub credential.

Notable events for integrations:

| Type                                           | Meaning                                                                                                                                                                                      |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `repository.preparing`, `repository.ready`     | Checkout started and finished, with `repository` and `revision`. `repository.ready` may carry `warnings`, such as a `gh` that could not be installed.                                        |
| `input.requested`, `question.requested`        | The run needs an answer. Its status is `needs_input`.                                                                                                                                        |
| `plan.updated`                                 | The agent's whole todo list.                                                                                                                                                                 |
| `usage.updated`                                | Model tokens and cost for a step.                                                                                                                                                            |
| `outcome.available`                            | The outcome was kept, before the terminal event.                                                                                                                                             |
| `preview.available`                            | A server was announced.                                                                                                                                                                      |
| `delivery.completed`                           | The agent opened or updated a pull request: the run, outcome, repository, base revision, branch, base branch, head commit and tree, and pull request. Once per pull request and head commit. |
| `run.completed`, `run.failed`, `run.cancelled` | The end. The terminal event may carry `infrastructure`, the sandbox's duration and resources.                                                                                                |

## Realtime

`GET /v1/realtime`

Key `runs:read`, or session: member. A WebSocket on the organization's realtime channel. Every socket in the organization receives every frame.

| Query          | Type | Meaning        |
| -------------- | ---- | -------------- |
| `organization` | slug | For a session. |

Each frame is JSON with a `type` and a `topic`:

| `type`       | `topic`                | Body                                                                                                                                                                                    |
| ------------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `run`        | `run:<id>`             | `run`: `id`, `status`, `previews`, `previews_until`. Sent when a run moves to `needs_input` or ends, in a project or not, and when its previews or preview window change. Never a link. |
| `task`       | `project:<slug>`       | `task`: a project task, as in [Projects](/docs/api/projects#list-tasks).                                                                                                                |
| `project`    | `project:<slug>`       | `project`: a project, as in [Projects](/docs/api/projects#the-project-object).                                                                                                          |
| `connection` | `connection:<user id>` | `connection`: `user_id`, `key_id`, `client_name`. An agent tool a person connected used its key for the first time.                                                                     |

Frames are lossy: a client that reconnects loads current state again. The socket is read only, and one that sends a message is closed. It lives 15 minutes per credential, then closes with 4001 like a run event socket. The MCP `wait` tool uses this socket to wait on many runs.
