ApexStream
ApexStream Cloud — install, connect, and examples
Use ApexStream Cloud for a hosted control plane and WebSocket gateway: register, issue an app key from the dashboard, add the `apexstream` client to your project, and connect to `/v1/ws` with TLS.
1) Account and keys in the dashboard
Sign in (or register) and open `/dashboard`. Create organization → project → application, then copy the WebSocket URL and app API key shown for that app.
Use `wss://` in production. Paste keys into environment variables or server-side config—do not embed admin or long-lived secrets in public front-end bundles.
2) Install the JavaScript client
From your application folder:
npm install apexstream3) Connect with ApexStreamClient
The same env names as in [`apexstream/examples`](https://github.com/apexstream/examples) Vite clients: put the gateway URL and app key in `client/.env` — `VITE_APEXSTREAM_WS_URL` and `VITE_APEXSTREAM_API_KEY` (see each demo’s `.env.example`).
One `ApexStreamClient` per connection. Call `connect()` before `subscribe` / `publish`. Match the demos: pass `allowInsecureTransport: true` only when the URL starts with `ws://` (local/dev); `wss://` cloud URLs do not need it.
# client/.env — same pattern as apexstream/examples/*/client/.env.example
VITE_APEXSTREAM_WS_URL=wss://api.apexstream.org/v1/ws
VITE_APEXSTREAM_API_KEY=paste_app_key_from_dashboardimport { ApexStreamClient } from "apexstream";
const wsUrl = import.meta.env.VITE_APEXSTREAM_WS_URL!;
const apiKey = import.meta.env.VITE_APEXSTREAM_API_KEY!;
const client = new ApexStreamClient({
url: wsUrl,
apiKey,
allowInsecureTransport: wsUrl.startsWith("ws://"),
});
await client.connect();
const off = client.subscribe("orders", (payload) => {
console.log("event", payload);
});
client.publish("orders", { kind: "placed", id: "ord_123" });
off();
await client.disconnect();4) Runnable examples on GitHub
End-to-end demos live in `apexstream/examples`: realtime chat, live metrics dashboard, signed webhooks, presence and cursors, operator analytics (External API), and an AI agents bus. Each folder has its own README, `.env.example`, and `client/` — run with Vite + React and your gateway URL and keys.
WebSocket URL and authentication
Connect with `GET` to the gateway WebSocket path `/v1/ws` (for example `wss://your-host/v1/ws`). Use TLS (`wss://`) in production.
`api_key` (or `apiKey`) may be passed in the query string, as header `X-Api-Key`, or as `Authorization: Bearer` when the token is not a JWT (see gateway `authenticateAPIKey`).
JWT: use query `token` / `jwt`, or `Authorization: Bearer` with a standard three-segment JWT. After a successful handshake the app is inferred from the key or JWT claims — you usually do not pass a separate `app_id` in the query for the typical api_key flow.
Wire protocol — JSON frames
Every frame is JSON with a `type` field (not `op`). Examples below match what `ApexStreamClient` sends and what the gateway returns.
Subscribe — one channel per message. The gateway responds with a `subscribed` acknowledgement (shape may include `app_id` and `channel`).
Publish — send a `payload` object on a channel. Subscribers receive a `message` frame with the same `channel` and `payload`.
Errors — `type: "error"` with a human-readable `message` (rate limits, JWT scope, unknown `type`, etc.).
Extended realtime may add metadata (for example durable ids) on `message` — see gateway and client types when you enable those features.
Presence: the gateway may emit frames such as `presence_snapshot` / `presence_update` with `channel` and `payload`. Exact shapes live in the gateway code — document them from the repo when you need strict contracts.
{
"type": "subscribe",
"channel": "orders:123"
}{
"type": "subscribed",
"app_id": "…",
"channel": "orders:123"
}{
"type": "publish",
"channel": "orders:123",
"payload": { "status": "shipped" }
}{
"type": "message",
"app_id": "…",
"channel": "orders:123",
"payload": { "status": "shipped" }
}{
"type": "error",
"message": "channel required"
}JavaScript SDK (`apexstream`)
Package `apexstream`, class `ApexStreamClient`. One client instance per connection; call `connect()` before `subscribe` / `publish`.
`subscribe` returns an unsubscribe function. Use `disconnect()` when you are done. Optional `client.on('open', …)` runs after the WebSocket opens.
On the wire, `publish` maps to `type: "publish"` with the `payload` you pass from code.
Browser (Vite) — same pattern as [`apexstream/examples`](https://github.com/apexstream/examples): `VITE_APEXSTREAM_WS_URL` and `VITE_APEXSTREAM_API_KEY` in `client/.env`. Use `allowInsecureTransport: wsUrl.startsWith("ws://")` (see the chat demo). Node publishers may use `APEXSTREAM_WS_URL` / env-based keys instead of `import.meta.env`.
npm install apexstreamimport { ApexStreamClient } from "apexstream";
const wsUrl = import.meta.env.VITE_APEXSTREAM_WS_URL!;
const apiKey = import.meta.env.VITE_APEXSTREAM_API_KEY!;
const client = new ApexStreamClient({
url: wsUrl,
apiKey,
allowInsecureTransport: wsUrl.startsWith("ws://"),
});
client.connect();
client.on("open", () => {
console.log("connected");
});
const off = client.subscribe("chat:room-1", (payload, meta) => {
console.log(payload, meta);
});
client.publish("chat:room-1", { text: "hello" });
off();
client.disconnect();