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 — so idle connections cost you nothing.

Connect to the stream

1

Get an API key

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

bash
hookstream api-keys create --name "streaming"
2

Open a WebSocket

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

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);
});
3

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

WebSocket endpoints, authentication, and channel semantics.

Learn More
Webhook Testing

The test inspector uses the same WebSocket infrastructure.

Learn More
Ask a question... ⌘I