WebSocket
Broadcast events to connected WebSocket clients via the EventStream Durable Object.
The websocket provider broadcasts delivered events to any WebSocket client subscribed to a named channel. Under the hood it uses hookstream's EventStream Durable Object (one per org, Hibernatable WebSockets), so there's no extra infrastructure to manage.
When to use this: you're building a live dashboard, a developer tool that streams webhooks to the browser, or a multi-client broadcast fan-out where many viewers need the same events.
Unlike the other providers, WebSocket doesn't make an outbound HTTP call — it hands the event to the per-org EventStream DO, which fans it out to every connected subscriber on the configured channel.
Configuration
Channel identifier to broadcast on. Alphanumeric with dots, underscores, or hyphens (^[a-z0-9._-]+$/i). Clients subscribe to this exact name.
Authentication
The destination itself has no auth — it just publishes into your org's DO. Access control happens on the client side when subscribing.
Clients connect to /v1/ws with an API key and subscribe to the channel:
textwss://hookstream.io/v1/ws?token=$HOOKSTREAM_API_KEY
After the upgrade, send a subscribe frame:
json{ "type": "subscribe", "channel": "live-orders" }
Message Format
Broadcasts are sent as JSON frames with type: "event.delivered":
json{ "type": "event.delivered", "channel": "live-orders", "data": { "event_id": "evt_abc123", "destination_id": "dest_xyz", "payload": "{...webhook body as a string...}" } }
The payload field is the raw event body as a string (so it matches exactly what would've been POSTed to an HTTP destination).
Example
bashcurl -X POST https://hookstream.io/v1/destinations \ -H "X-API-Key: $HOOKSTREAM_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Live Dashboard", "type": "websocket", "config": { "channel_name": "live-orders" } }'
Browser client:
jsconst ws = new WebSocket(`wss://hookstream.io/v1/ws?token=${API_KEY}`); ws.onopen = () => ws.send(JSON.stringify({ type: "subscribe", channel: "live-orders" })); ws.onmessage = (e) => console.log(JSON.parse(e.data));
Gotchas
If no client is connected when an event is delivered, the broadcast is dropped. Use WebSocket alongside another destination (HTTP, SQS, S3) if you need durability.
One EventStream DO per org handles all channels, so subscribers on different channels inside the same org share the same hibernating DO. This is cheap — Hibernatable WebSockets incur no idle cost.