WebSocket
A JSON-RPC 2.0 transport framed over a persistent WebSocket for the shared market-data catalog. It takes the same method and params as HTTP and Yellowstone and returns the same data. One socket queries; another streams live inserts, updates, and deletes.
Endpoint
There are two sockets: a query (rpc) socket for one-shot requests and a subscription socket for live streams. The method selects what you query or stream.
wss://rpc.raptor.trade # query socket (rpc)
wss://sub.raptor.trade # subscription socket
# both take ?token=$RAPTOR_TOKENAuthentication
Browsers cannot set custom headers on a WebSocket handshake, so both sockets take your token as a token query parameter. Unlike HTTP (an Authorization: Bearer header) and Yellowstone (an x-token gRPC metadata header), WebSocket carries it in the URL - see WebSocket Authentication.
The contract
Every frame is a JSON-RPC 2.0 message with a method path string identical to HTTP and Yellowstone (e.g. solana::market::ohlcv) and a params object holding the selectors. A query response is always a JSON array - one entry per request - and each entry's result holds the array of data, the same shape as HTTP. A subscribe returns an ack carrying a subscription id, then pushes id-less notifications whose result holds inserts, updates, and deletes as full data. See Subscription for the full connect → subscribe → unsubscribe lifecycle.
Rows render exactly as they do over HTTP and Yellowstone: numbers are strings, DateTime and Duration are ISO strings, blobs are 0x hex, a missing value (none) is JSON null, and only booleans stay native. Each data point carries an id alongside its columns.
Query
A request on the query socket returns the matching data - the same one-shot query you can run over HTTP. The raw frame and the TypeScript SDK:
{
"jsonrpc": "2.0",
"id": 1,
"method": "solana::market::ohlcv",
"params": {
"base": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"window": "1m",
"limit": 10
}
}The response envelope is identical to HTTP - the array, with data under result:
[
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": 1024,
"base": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"quote": "So11111111111111111111111111111111111111112",
"timestamp": "2026-06-01T02:16:22.000000000Z",
"window_duration": "PT1M",
"open": "0.00001901",
"high": "0.00001955",
"low": "0.00001888",
"close": "0.00001942",
"base_volume": "48210.7531",
"quote_volume": "48210.7531",
"open_usd": "0.000019",
"high_usd": "0.000019",
"low_usd": "0.000019",
"close_usd": "0.000019",
"volume_usd": "48210.7531",
"data_points": "37",
"window_start": "2026-06-01T02:16:22.000000000Z",
"window_end": "2026-06-01T02:16:22.000000000Z"
}
]
}
]Subscribe
A subscribe on the subscription socket delivers a hydration snapshot as the first notification, followed by live changes. Tune delivery with hydrate and throttle. The raw frame and the TypeScript SDK:
{
"jsonrpc": "2.0",
"id": 1,
"method": "solana::market::ohlcv",
"params": {
"base": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"window": "1m",
"hydrate": 50,
"throttle": "1s"
}
}Each push is an id-less notification carrying the changed data:
[
{
"jsonrpc": "2.0",
"method": "solana::market::ohlcv",
"result": {
"subscription": 42,
"inserts": [
{
"id": 1024,
"base": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"quote": "So11111111111111111111111111111111111111112",
"timestamp": "2026-06-01T02:16:22.000000000Z",
"window_duration": "PT1M",
"open": "0.00001901",
"high": "0.00001955",
"low": "0.00001888",
"close": "0.00001942",
"base_volume": "48210.7531",
"quote_volume": "48210.7531",
"open_usd": "0.000019",
"high_usd": "0.000019",
"low_usd": "0.000019",
"close_usd": "0.000019",
"volume_usd": "48210.7531",
"data_points": "37",
"window_start": "2026-06-01T02:16:22.000000000Z",
"window_end": "2026-06-01T02:16:22.000000000Z"
}
],
"updates": [],
"deletes": []
}
}
]SDK
The @raptortrade/client SDK manages the handshakes, framing, batching, and live subscriptions over a single connection - see the WebSocket SDK.
