Skip to main content
The data service serves the pair catalog (GET /v2/trading) and broadcasts every change over Socket.IO as RES:DATA. This is the live feed behind client.pair_data_stream() and the Avantis web app: funding, open interest, spreads, market hours, and the rest of the snapshot, in human units. No auth. The server broadcasts to every connected client. You do not emit anything; connect and listen. Both hosts are the same service. The gateway rewrites the /data prefix to / before the backend. Use the standalone origin if you are wiring this up without the SDK; the SDK connects to the gateway unless you set AVANTIS_DATA_API_URL.

Bootstrap, then merge

Socket.IO does not send the current snapshot on connect, and missed diffs are not replayed. On every (re)connect:
  1. GET /v2/trading for the full snapshot.
  2. Deep-merge each RES:DATA payload into that snapshot.
The response is the snapshot itself (no {ok, data} envelope). Top-level shape: pairInfos keys are strings ("1", not 1). Field names are camelCase. See Markets for the load-bearing PairInfo fields.

Handshake

Socket.IO v4 / Engine.IO v4. Default namespace /. Transports: websocket then polling. Path is /socket.io on the standalone host and /data/socket.io on the gateway.
socket.io-client treats the URL path as a namespace, not the Engine.IO path. Connect to the origin and set path explicitly. Do not pass https://prod-api.avantisfi.com/data as the URL — that joins namespace /data and misses the broadcast.
Standalone (recommended for direct integrators):
Gateway:
Python (pip install 'python-socketio[asyncio_client]'; python-socketio discards the URL path, so pass socketio_path):
On the gateway, socketio_path="data/socket.io".

RES:DATA

Server → client, every time the worker publishes a cache diff (incremental pair sync ~1s, market-hours / leverage / spread windows ~1 min, full rebuild ~30 min, plus on-chain OI and funding events). The payload is a deep diff of the snapshot: only changed keys, nested. Unchanged pairs and fields are omitted. Arrays are replaced wholesale.
Deep-merge into the snapshot you bootstrapped. Nested objects merge; scalars and arrays overwrite.
Refetch on connect so a reconnect cannot apply a stale diff on top of a gap. Fields that move on every incremental tick: pairInfos[i].openInterest, coinOI, pairOI, fundingRate, fundingFeePerHourP, marginFee, spreadP, liquidity, and the matching groupInfo / totalOi. Market hours live under pairInfos[i].feed.attributes (isOpen, nextOpen, nextClose, schedule).

SDK

The callback receives the raw RES:DATA dict. The SDK does not merge it into client.markets (that snapshot is HTTP-polled, 5s TTL). Treat the stream as its own live copy, or call markets.snapshot(force=True) when you need the typed PairInfo models refreshed. Runnable sketch: examples/17_streams.py.