WebSocket API

Wire Broker WebSocket

The sub, unsub and pub operations of the Wire Broker, the message delivery, and every reply and error, with frames.

Endpoint: wss://api.thuum.dev/api/{domain}/wire/connect?token=…. The connection needs a key linked to a Wire Broker claim. Framing, refs and general errors are on WebSocket protocol.

The operations are the Event Broker's, without storage: nothing published here is kept.

Operations#

OpFieldsFlagReply
subtopic, ref?Ssub:ok
unsubtopic, ref?—unsub:ok
pubtopic, type, data, ref?Ppub:ok with id, ts

The server pushes one more op, message, for each delivered message.

sub#

Subscribe to a topic and its whole subtree. Idempotent.

JSON
→ [{ "op": "sub", "topic": "plant", "ref": "1" }]
← [{ "op": "sub:ok", "topic": "plant", "ref": "1" }]

From then on, every message published on plant or any plant:* topic arrives as a message. Messages published before the sub:ok are gone: there is no history.

unsub#

Stop receiving a topic's messages. Idempotent, and needs no flag.

JSON
→ [{ "op": "unsub", "topic": "plant", "ref": "2" }]
← [{ "op": "unsub:ok", "topic": "plant", "ref": "2" }]

pub#

Publish a message on exactly topic. The reply comes once it has been handed to the current subscribers, and carries a random id and the server's ts. Nothing is stored under them.

JSON
→ [{ "op": "pub", "topic": "plant:line-3", "type": "readings", "data": { "t1": 71.4 }, "ref": "3" }]
← [{ "op": "pub:ok", "topic": "plant:line-3", "ref": "3", "id": "0f6c2a1e-3b7d-4e8a-9c41-2d5f8a7b6e10", "ts": 1792590697447 }]

message#

One frame per delivered message, with the exact topic it was published on:

JSON
← [{ "op": "message", "id": "0f6c2a1e-3b7d-4e8a-9c41-2d5f8a7b6e10", "topic": "plant:line-3", "type": "readings", "data": { "t1": 71.4 }, "ts": 1792590697447 }]

If the publishing connection is itself subscribed, it receives its message too.

Errors#

JSON
→ [{ "op": "pub", "topic": "plant:line-3", "type": "bad type", "data": 1, "ref": "4" }]
← [{ "op": "pub:error", "topic": "plant:line-3", "ref": "4", "code": "bad_request", "message": "type …" }]

→ [{ "op": "sub", "topic": "payroll", "ref": "5" }]
← [{ "op": "sub:error", "topic": "payroll", "ref": "5", "code": "forbidden", "message": "Missing S claim on topic" }]
OpPossible codes
subbad_request (invalid topic), forbidden
unsubbad_request (invalid topic)
pubbad_request, forbidden

An unexpected server error closes the connection with code 1011 instead of replying: its details are never logged, because they could hold your data. Reconnect.

With the client#

TypeScript
const socket = acme.wire.connect();
socket.onMessage((message) => console.log(message));
await socket.ready;

await socket.sub('plant');
const { id, ts } = await socket.pub('plant:line-3', 'readings', { t1: 71.4 });
await socket.unsub('plant');
socket.close();

Failed ops reject with WireSocketError, whose code is one of the codes above, or closed if the connection dropped first. See Sockets.