Production Board

WebSocket transport

Optional: same CRUD surface plus live events over one socket.

WebSockets are optional. The HTTP API covers every operation on its own - if you'd rather keep things simple, stop at the auth + per-model pages and ignore this one. The WebSocket transport is here when you want live events (no polling), or when you'd rather pay one TLS handshake for a long burst of operations. Connect to /xapi2/ch, hand it the same Bearer token the HTTP API accepts, and run any CRUD op (list, read, create, update, delete) plus subscribe over the same socket. Auth, scopes, rate limits, audit, and access checks are identical to HTTP - only the transport differs.

How it works

Handshake

Connect to /xapi2/ch?token=<jwt-or-pat>, or send the token via the Sec-WebSocket-Protocol: bearer, <token> header. Server replies with a hello frame on accept.

Live events

Send { op: "subscribe", id, dataType } to receive event frames whenever a row of that type is created, updated, or deleted - filtered server-side by your read access.

Streaming list

WS list streams results as list_chunk frames (default 25/page, hard cap 10k rows total) followed by a final list_done carrying the same metadata HTTP's meta block does. Useful for large initial loads.

Examples

const ws = new WebSocket(
`wss://${location.host}/xapi2/ch?token=${encodeURIComponent(token)}`,
)
ws.onopen = () => {
// Receive live created/updated/deleted events for this type.
ws.send(JSON.stringify({ op: "subscribe", id: "sub-1", dataType: "board" }))
}
ws.onmessage = (msg) => {
const frame = JSON.parse(msg.data)
if (frame.op === "event") console.log(frame.event, frame.dataType, frame.object ?? frame.id)
}