Skip to main content
WSS
The OHLCV WebSocket emits one frame per bar update for each (pool, timeframe) you subscribe to. You get mid-bar updates while a bar is open (is_closed: false) and an update when it closes (is_closed: true). A closed bar may be sent again as a correction, so the last closed frame for a bar is the one that counts (see Frame shape). This is the right channel when you want to render a live chart or trigger logic on bar close. For one-shot history, use /api/v1/candles and /api/v1/candles/latest. For raw per-swap data, use WebSocket: swaps.

Endpoint and auth

Authenticate either via Bearer header (server) or query string (browser) — /ws/ohlcv accepts both, same as /ws/swaps:

Subscribe

After the connection is up the server sends a hello frame:
Then send a subscribe. Both pair_addresses and timeframes are required — the server will reply with {"error": "invalid subscribe: timeframes empty"} (or similar) if either is missing.
Server ack:
This first frame is the one-shot, backward-compatible path: a client that only ever sends it sees zero change from before. pairs is the distinct pool count, subjects is the number of live (pool, timeframe) pairs, and op mirrors status.
A subject is one (pair_address, timeframe) pair — the unit the stream actually fans out on. A subscribe of 3 pools × 2 timeframes is 3 pairs but 6 subjects.

Add / remove / unsubscribe (mid-stream)

Once you’re subscribed you can change the watched symbol set without reconnecting by sending more frames on the same socket. This is what lets a chart or watchlist UI swap the active pool, or add/drop timeframes, in place. Every mutating frame carries an op. Each (pair_address, timeframe) pair it expands to is a subject; the ack’s pairs/timeframes/subjects always report the new total live set after the op — not just the delta.

Add symbols

Ack with the new totals (now 2 pools × the union of timeframes):

Remove symbols

Unsubscribe (clear everything)

Replace the whole set

A later frame with op: "subscribe" (or with no op — absent defaults to subscribe) replaces the entire live set with the new one:
This reset behaviour is the opposite of the swaps WebSocket. On /ws/ohlcv, to widen the set you must use op: "add" — sending another subscribe (or an op-absent frame) discards what you had. The frame’s op field is what the server reads; the legacy type field is ignored.
The replace is atomic: if the new set would exceed the per-connection subject cap, the replace is rejected and your prior subscription stays fully intact.

Frame shape

Limits and errors

Two independent limits apply: Mid-stream errors are non-fatal — the socket stays open and a later valid frame still works. (Only an error on the initial subscribe frame closes the connection, as before.)
  • Bad frame / unknown op → { "error": "invalid subscribe: <detail>" } and the socket stays open. An unknown op comes back as { "error": "invalid subscribe: unknown op: <op>" }.
  • Per-frame pool cap → { "error": "invalid subscribe: too many pair_addresses; max 1000" }.
  • Per-connection subject cap → an add or subscribe-replace that would push the live set past the cap is rejected atomically — no partial apply, and your existing subjects keep delivering:

Minimal TypeScript client

If you’re rendering a live chart, key your local bar store by (pair_address, timeframe, timestamp) and overwrite the entry on every frame for that key — the latest frame is always the freshest snapshot of that bar. is_closed: true means the bar has closed, but a corrected close for the same key can follow — usually within a few seconds, and for up to 10 minutes — so keep overwriting on later closed frames too. If you trigger logic on close, allow for that correction. Repairs made after that are not sent on the stream. When missed trades are backfilled (for example after an ingestion outage), the corrected bars are written to storage and served by /api/v1/candles, but no frame is sent for them. If you need exact history, re-read the affected window from REST: after a reconnect (see Reconnect & backpressure), or when a window you hold is known to have been repaired.

Changing the watched set at runtime

A watchlist or chart UI that switches the active pool sends add / remove on the same open socket — no reconnect. Helpers, and an ack handler that reads back the new live totals:
Use op: 'subscribe' (or an op-absent frame) only when you intend to reset the whole set — it discards the current subscription. To widen, always use op: 'add'. For reconnect strategy, gap-filling against /api/v1/candles, and keepalive guidance, see Reconnect & backpressure.

Programmatic spec

The full message contract for this channel — and the other two WebSocket streams — is published as an AsyncAPI 3.0 document you can feed into client generators, validators, or an LLM.
api_key
type:httpApiKey

?api_key=ohlcv_live_sk_… appended to the connection URL. Browser-friendly; the only option in environments where you can't set headers.

Subscribe / add / remove / unsubscribe
type:object

Op-tagged frame that mutates the live (pool x timeframe) set. The FIRST frame subscribes; later frames on the same socket can add/remove/unsubscribe or subscribe (reset) without reconnecting. op absent = subscribe = REPLACE.

Candle update
type:object

One bar update for a subscribed (pool, timeframe). NOTE: volume_sol is in lamports despite the name (divide by 1e9 for SOL); volume_token is in base units (divide by 10**quote_decimals).

Connect hello
type:object

Sent once on connect with a UUID client_id and the index inception timestamp.

Subscribe / add / remove ack
type:object

Sent after each successful op. status and op echo the op (subscribed/added/removed/unsubscribed). pairs/subjects are the new LIVE TOTALS after the op (not a delta). A subject = one (pool, timeframe) pair.

Stream error
type:object

Validation failure, auth issue, or server-side error. Connection usually stays open after a recoverable error.