# Stream room

> Payload of one stream message; the message kind selects the shape.

`GET https://api.cymatics.tech/v1/rooms/{room}/stream`

Scope: `results:read` · Server-Sent Events

## Request

Send your key as `Authorization: Bearer cym_test_…`. Requires the `results:read` scope. Test keys read the simulator; live keys read your paired Cymos.

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `room` (SDK and CLI: `room_id`) | path | `string` | Yes | Room id |
| `signals` | query | `string[]` | No | Signals |
| `rate_hz` | query | `number, ≥ 0.1 and ≤ 120` | No | Rate hz |
| `view` | query | `fused \| device` | No | View |
| `Last-Event-ID` | header | `string` | No | Scoped bounded replay cursor. |

## Response

A Server-Sent Events stream. Each message carries an `id`, an `event` kind and a `data` line holding the same `{ data, meta }` envelope as every JSON response. Reconnect with `Last-Event-ID` to resume. See [Streaming](https://docs.cymatics.tech/streaming).

`200 · text/event-stream`

```
id: 3f9c2a7d1b6e4c08.42.result
event: result
data: {"data":{"value":1,"timestamp":"2026-10-24T23:55:30.000Z","confidence":0.92,"object":"result","id":"res_01","signal":"heart_rate_bpm","room_id":"room_bedroom","device_id":"dev_bedroom","track_id":"trk_001","person_id":"person_001","model":{"id":"model_vitals","version":"demo-1"},"received_at":"2026-10-24T23:55:30.000Z","updated_at":"2026-10-24T23:55:30.000Z","revision":1},"meta":{"request_id":"req_01","project_id":"proj_demo","livemode":false,"generated_at":"2026-10-24T23:55:30.000Z"}}
```

## Errors

| Status | Description |
| --- | --- |
| `429` | `rate_limit_exceeded`: Too many requests this minute for the key (or twice that across the project), or too many open streams for the project. Retry after the seconds in Retry-After.<br>`quota_exceeded`: A live key's project has used its monthly live-hour cap. There is no Retry-After. Don't retry; raise the live-hour cap in the dashboard. Headers: Retry-After, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset. |
| `503` | `live_unavailable`: This operation has no live data for this project yet (for example, no paired Cymo covers it). Don't retry the same request; pair a Cymo that covers it, or build against a test key.<br>`service_unavailable`: A dependency, such as API key verification, is unreachable, or the project is busy with another write. Retry after the seconds in Retry-After, with backoff. |
| `4XX` | Invalid request, credential, permission or revision. |
| `default` | Error with a stable code and request ID. |

Every error is a `{ error, meta }` envelope with a stable `code`. See [Errors](https://docs.cymatics.tech/errors) for each code and whether to retry.

## Call it

**TypeScript · @cymos/sdk**

```ts
import { Cymo } from "@cymos/sdk";

const cymo = new Cymo({ apiKey: process.env.CYMO_API_KEY! });

for await (const message of cymo.rooms.stream({ room_id: "room_bedroom" })) {
  console.log(message.id, message.kind, message.data);
}
```

**terminal · cymatics CLI**

```sh
$ cymatics rooms stream --room-id room_bedroom --max-events 5
```

**curl**

```sh
curl -N "https://api.cymatics.tech/v1/rooms/room_bedroom/stream" \
  -H "Authorization: Bearer $CYMO_API_KEY" \
  -H "Accept: text/event-stream"
```

**MCP tool**

```
stream_room({ room_id: "room_bedroom", duration_ms: 10000, max_samples: 20 })
```

The MCP tool `stream_room` calls this operation with your key. It watches the stream for `duration_ms` (up to 60 s) or until `max_samples` messages (up to 200), then returns them and says whether more followed.
