---
title: "Stream run events (SSE)"
method: GET
path: "/v1/runs/{id}/events"
tags: ["runs"]
---

# Stream run events (SSE)

`GET /v1/runs/{id}/events`

## Request

- Base URL: `https://api.hyperresearch.ai`
- URL: `https://api.hyperresearch.ai/v1/runs/{id}/events`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `hr_session`

Server-sent events mirroring events.jsonl. `Last-Event-ID` (or ?last_event_id=) resumes from the run log, exclusive of that id — reconnecting replays nothing already delivered and skips nothing. Heartbeat comment every 15 s. The sentinel for "from the start of the log" is `-1`, an empty value, or omitting the parameter entirely; all three behave identically and none is an error. Always 200, never 503: a run whose RunAgent has not registered yet is waited for (about 5 s) and then answered with an empty stream carrying `retry: 2000`, and a control-plane read that fails transiently is answered the same way (with `Retry-After: 2`) rather than with a 5xx. Only a run that does not exist in this workspace is an error, and that is a 404. One connection lives at most 25 minutes; the server then ends it cleanly with a `retry:` hint and the client reconnects with `Last-Event-ID`. An `event: counters` carries the run's running totals — `sources_fetched` (sources KEPT), `notes_written`, `candidates_seen` (candidates considered), `fetch_attempts`, `agents_spawned` — so a client never has to derive them by counting events; the same fields ride on EVERY `fetch` event, including the ones that failed. Counting `fetch` rows is not a source count (E2E4-02). An `event: note` is emitted once for every source the run KEEPS, carrying `note_id`, the resolved `title`, the `domain` and the `url` — everything a Sources panel prints, at the moment the source lands. Counting `note` events counts sources; counting `fetch` events counts attempts. A kept `fetch` event carries the same `title` and `domain`, so a client that only listens for fetches can show the real title rather than a URL slug (E2E6-05/E2E6-06). Event types and their `status` values are forwarded from the run log as-is and may gain additive values; ignore any you do not recognise. An `event: step` with `status: "title"` carries a short human description of what that step is doing (`title`) and is advisory — it does not mark a step transition. The width sweep publishes three aggregate `step` events on step 2, with the numbers to describe it: `status: "search-lanes"` carries `planned`, `executed`, `failed`, `candidates` and `cap`; `status: "wave-1"` carries `attempted`, `fetched`, `failed` and `reused`; `status: "vault-reuse"` carries `notes_reused` and `reuse_scope` (`project` when the run reads its project's slice of the vault, `workspace` otherwise). Per-lane detail rides `event: fetch` with `kind: "search_lane"` (`query`, `web_results`, `discovery_used`, `merged`, `unconfigured`). Lane failure text (`web_error`, `lane_errors`, `errors`) is sanitised on the way out on the same terms as an `error` event's `message`: single-line, 300 characters, at most five entries. Only frames that are positions in the run log carry `id:`. A stream-level `event: error` has no `id:`, so a client's `Last-Event-ID` stays on the last real event. An `event: error` carries `message`: the sanitised failure reason, single-line and capped at 300 characters, plus `terminal: true` on the run's final failure or abort.

## Path parameters

- `id` string, required

## Query parameters

- `last_event_id` string: Resume the stream after this event id, exclusive. `-1`, an empty value and an absent parameter are all the sentinel for "from the start of the run log". `Last-Event-ID` takes precedence when both are sent.

## Response `200`

Event stream

## Other responses

- `400`: Invalid request
- `401`: Authentication failed
- `403`: Insufficient scope or plan
- `404`: Not found
- `429`: Rate limited or over quota
- `500`: Internal error

---

[API](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api.md) · [All operations](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/revisions/726ef831ebf4?raw)
