> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hookstream.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Real-Time Streaming

WebSocket push, channel subscriptions, and polling fallback for live updates.

Hookstream pushes updates to connected clients in real-time over WebSockets. Under the hood, a per-org `EventStream` Durable Object manages every connection using Cloudflare's [Hibernatable WebSocket API](https://developers.cloudflare.com/durable-objects/api/websockets/#websocket-hibernation) — so idle connections cost you nothing.

## Connect to the stream

**Get an API key**

Generate one from **Settings → API Keys** or via the CLI:

    ```bash
    hookstream api-keys create --name "streaming"
    ```
  **Open a WebSocket**

The endpoint is `wss://hookstream.io/v1/ws?token=<api_key>`. In the browser, session cookies also work automatically.

    ```javascript node
    import WebSocket from "ws";

    const ws = new WebSocket(`wss://hookstream.io/v1/ws?token=${process.env.HOOKSTREAM_API_KEY}`);

    ws.on("open", () => {
      ws.send(JSON.stringify({ type: "subscribe", channel: "events" }));
    });

    ws.on("message", (raw) => {
      const msg = JSON.parse(raw.toString());
      console.log(msg.type, msg.data);
    });
    ```

    ```bash websocat
    websocat "wss://hookstream.io/v1/ws?token=$HOOKSTREAM_API_KEY"
    ```
  **Subscribe to channels**

On connect, hookstream sends a welcome message with your `org_id`. Send `{ "type": "subscribe", "channel": "<name>" }` for every channel you want to receive.

## Available channels

- `events` — every new event, across all sources in the org.
- `events:<source_id>` — events from a single source.
- `deliveries` — completed delivery attempts across all destinations.
- `deliveries:<destination_id>` — delivery attempts for a single destination.
- `issues` — issue created, updated, or resolved.
- `collections:<collection_id>` — Instant Database sync events.

Subscribe to as many as you like — the DO uses Cloudflare's native tag-based filtering so you only receive messages for channels you asked for.

## Message format

Every message is JSON with a `type` and a `channel`:

```json
{ "type": "event", "channel": "events", "data": { "...full event object..." } }
{ "type": "delivery", "channel": "deliveries", "data": { "...full delivery attempt..." } }
{ "type": "issue", "channel": "issues", "data": { "...full issue object..." } }
```

The `data` field is the complete resource — the same shape you'd get from the REST API.

## Reconnect automatically

The dashboard's `useEventStream` hook handles reconnection with exponential backoff (1s → 2s → 4s → capped at 30s) and re-sends channel subscriptions after reconnecting. If you're writing your own client, mirror that behavior.

## Polling fallback

Every dashboard page also polls the REST API on an interval, just in case the WebSocket drops. When connected, polling slows down to 30 seconds. When disconnected, it speeds up to 5 seconds so the UI stays fresh. The `usePolling` hook in the frontend manages this automatically.

If you're building your own client, the same pattern works — treat the WebSocket as the fast path and the REST API as the safety net.

## Next Steps

**[WebSockets API](/api/websockets)**

WebSocket endpoints, authentication, and channel semantics.
  **[Webhook Testing](/guides/webhook-testing)**

The test inspector uses the same WebSocket infrastructure.