supanovasupanovaDOCS
Open Launchpad
Launchpad documentation
Developers

WebSocket market stream

Subscribe to trades, tickers, and candles, then recover correctly after gaps or reconnects.

Connect to the market stream for updates on selected pairs:

text
wss://launch-api.supanova.app/api/v1/market/ws

The stream is read-only. It does not submit orders or confirm a private account's settlement.

Authenticate the connection

Pass your read key in the WebSocket upgrade's X-API-Key header. Keys in query strings are rejected. Never append ?api_key=… to the URL.

The browser's native WebSocket API cannot set an arbitrary authentication header. For a keyed integration, connect from your server and expose only the data your frontend needs. Do not ship your customer key to the browser.

Subscribe to channels

Read a real pair_id from the Market API, then send one subscription frame:

json
{
  "op": "subscribe",
  "channels": [
    "trades.<pair_id>",
    "ticker.<pair_id>",
    "candles.1m.<pair_id>"
  ]
}

Replace <pair_id> with the complete value, including its :curve or :amm suffix.

ChannelData
trades.<pair_id>Trade rows, oldest first. The initial snapshot contains the latest 20.
ticker.<pair_id>Pair statistics, updated on new fills and at least every 30 seconds.
candles.<interval>.<pair_id>The forming candle. A closed candle is sent again with closed: true.

Unsubscribe with the same channel names and "op": "unsubscribe". Send {"op":"ping"} for an application-level ping; the server responds with {"op":"pong"}.

Read messages

Data messages have this structure:

json
{
  "channel": "ticker.<pair_id>",
  "type": "snapshot",
  "seq": 1,
  "ts": 0,
  "data": {}
}

This is a structural example: ts and data are populated by the stream. type is snapshot or update. Control messages use op, including subscribed, unsubscribed, pong, and error.

Node.js connection example

Install ws, set SUPANOVA_API_KEY and SUPANOVA_PAIR_ID in the environment, and run this as an ES module:

javascript
import WebSocket from "ws";

const apiKey = process.env.SUPANOVA_API_KEY;
const pairId = process.env.SUPANOVA_PAIR_ID;
if (!apiKey || !pairId) throw new Error("Set API key and pair ID first");

const socket = new WebSocket("wss://launch-api.supanova.app/api/v1/market/ws", {
  headers: { "X-API-Key": apiKey },
});

socket.on("open", () => {
  socket.send(JSON.stringify({
    op: "subscribe",
    channels: [`ticker.${pairId}`, `trades.${pairId}`],
  }));
});

socket.on("message", (bytes) => {
  const message = JSON.parse(bytes.toString());
  if (message.op === "error") {
    console.error(message.code, message.message);
    return;
  }
  if (message.channel) console.log(message.channel, message.seq, message.data);
});

socket.on("error", (error) => console.error("Stream error:", error.message));
socket.on("close", (code) => console.log("Stream closed:", code));

This example prints messages. A production consumer also needs the reconciliation and reconnect behavior below.

Recover missing data

Track seq separately for each channel. It increases by one per message on that channel. A gap means your local state may be incomplete.

For trades, fetch recent trades over REST, page back until the last processed trade ID, and deduplicate by id. A trade can appear in both the initial snapshot and the first update. Do not count it twice.

After reconnecting, take a fresh snapshot and reconcile it with your stored state. Resubscribe only to the channels you need. Use exponential backoff with jitter so a service interruption does not create a reconnect loop.

Limits and close codes

Read the subscription limit from GET /api/v1/market/info. Inbound frames are limited to 4 KiB and 10 frames per second. Batch related subscriptions in a single frame.

CodeResponse
4401The key was revoked or expired. Stop reconnecting with it and replace or renew the credential.
1013The consumer could not keep up. Reduce work in the message handler, reconcile through REST, and reconnect after a delay.

The server also uses WebSocket ping/pong to detect dead connections. A client library should respond to protocol pings; do not disable that behavior. A keyed connection closes within about five seconds of revocation or expiry.

supanova Launchpad docsDeveloper settings