Skip to main content
The stream pushes trades, candles and token updates as they happen. One WebSocket connection carries up to 100 subscriptions across every channel.

Connect

Open a WebSocket to wss://api.metastreams.io/v1/stream, with your key in the Authorization header of the handshake.
The server checks the handshake before it upgrades the connection: A request without WebSocket upgrade headers gets a plain-text 4xx instead of an upgrade. Browsers cannot set the Authorization header on a WebSocket, so connect from your backend.

Frames

Every frame is a JSON text message.

From you

From the server

Subscription IDs

The server assigns each subscription a subscriptionId and returns it on the subscribe ack. Every update carries the ID of the subscription it belongs to. Use the ID to route updates in your client and to unsubscribe exactly. An unsubscribe without a subscriptionId closes every subscription you hold on that channel, and its ack carries no ID.

Ordering

  • A subscription’s ack always arrives before its first update.
  • An unsubscribe’s ack always arrives after that subscription’s last update.

Channels

Every REST read that changes over time has a channel that pushes the same objects. A streamed candle or token has exactly the shape its REST read returns: OHLCV candles and Token details. A streamed trade has the shape Token trades and Identity trades return, minus some fields per subscription mode: see spot.trades. Each channel’s reference page lists every filter, every update field and every error. A stream costs no request budget after its handshake, so it is the cheaper way to follow anything that changes more than once a minute.

Snapshot, then stream

A stream sends only what happens after you subscribe. To show a complete view, combine the two:
  1. Subscribe first, and buffer the updates that arrive.
  2. Read the snapshot from the REST endpoint.
  3. Apply the buffered updates on top of the snapshot, then apply new updates as they arrive.
Subscribing before you read means nothing that happens between the two calls is lost. Take the same three steps after a reconnect, so the re-read covers the gap. Merge each object on its own key:

Errors

A refused frame gets an error frame. It uses the same codes as the REST API. An error about a subscribe frame echoes that frame’s id. A frame the server cannot parse, and a refused unsubscribe, get an error with no id. An error frame never closes the connection.

Keeping the connection alive

Send {"action": "ping"} every 30 seconds or so. If no pong arrives within a few seconds, treat the connection as dead and reconnect.

When the server closes the connection

Subscriptions do not survive a reconnect. After you reconnect, send your subscribe frames again and fill the gap with a fresh snapshot.

Reconnect loop

These loops resubscribe after every close, reconnect straight away after 1001, back off after anything else, and stop only on 401.