WebSockets
Reconnection
Heartbeats, exponential backoff and resumable delivery with last_event_id.
Coming soon
The WebSocket feed is in development. This reference describes the v1 protocol so you can build against it today; it will be available on the Trader plan and above. Until launch, poll the REST endpoints once per window.Heartbeats
Sent every 15 seconds. Reconnect if no message arrives for 45 seconds.
{
"type": "heartbeat",
"ts": "2026-11-14T20:07:45.000Z"
}Exponential backoff
When the connection drops, wait before reconnecting and double the delay after each failure: 1 s, 2 s, 4 s … capped at 30 s, with random jitter so that many clients do not reconnect in lockstep. Reset the delay after a connection has been healthy for a minute.
Resuming a stream
After reconnecting and authenticating, send resume with the last event id you processed. The server replays missed events from the last 5 minutes, then continues live.
{
"op": "resume",
"last_event_id": "evt_01JD3Z4K9C"
}{
"type": "resumed",
"replayed": 14,
"last_event_id": "evt_01JD3ZM2XB"
}Filling longer gaps
If your last event is older than the replay window, the server answers with {"type":"resume_failed","reason":"window_expired"}. Re-subscribe, then backfill the gap from the REST history and market history endpoints using from.
Reference implementation
import WebSocket from "ws";
const CHANNELS = ["signals:BTC:15m", "markets:BTC:15m"];
let lastEventId = null;
let attempt = 0;
function connect() {
const ws = new WebSocket("wss://api.probora.xyz/v1/signals", {
headers: { Authorization: `Bearer ${process.env.PROBORA_API_KEY}` },
});
let watchdog;
const kick = () => {
clearTimeout(watchdog);
watchdog = setTimeout(() => ws.terminate(), 45_000); // no message for 45 s
};
ws.on("open", () => {
kick();
ws.send(JSON.stringify({ op: "subscribe", channels: CHANNELS }));
if (lastEventId) ws.send(JSON.stringify({ op: "resume", last_event_id: lastEventId }));
setTimeout(() => (attempt = 0), 60_000);
});
ws.on("message", (raw) => {
kick();
const event = JSON.parse(raw.toString());
if (event.id) lastEventId = event.id;
// handle event…
});
ws.on("close", () => {
clearTimeout(watchdog);
const delay = Math.min(30_000, 1000 * 2 ** attempt++) * (0.5 + Math.random() / 2);
setTimeout(connect, delay);
});
}
connect();Questions or feedback on the API? [email protected]