ApexStream logoApexStream

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 apexstream

3) 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_dashboard
import { 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.

github.com/apexstream/examples

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 apexstream
import { 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();