Please note
This endpoint has been deprecated in favor of a new version. Please refer to the documentation for Streaming Prices (v3). All users of this endpoint (Version 2) must move to v3.
Introduction
Subscribe to live asset updates on the Atom platform with a simple WebSocket connection. The timeliness of data will ultimately depend on the asset class; however, for U.S. equities, we provide real-time, up-to-the-second level 1 trade data.
Messages sent to and received from the server always include a messageType
. From a user's perspective, outbound Sub
and Unsub
messages also include assets, and inbound Trades
include price data. The server will send messageType: error
if it receives malformed messages or unknown assets.
The streaming service URL is:
wss://platform-streaming.atom.finance?api_key=<key>
Please note
We recommend subscribing in chunks of 100 assets or fewer per connection for performance reasons, and the absolute maximum is 200. There is no limit to the number of websocket connections you can make.
Subscribing and unsubscribing assets
Upon connection, you can stream prices for a list of assets by providing messageType: Sub
and assets: Asset Object[]
.
{
"messageType": "Sub",
"assets":
[
{
"value": "ZZZ",
"identifier": "ticker",
"assetType": "equity",
"market": "CAN",
},
{
"value": "BTC",
"identifier": "ticker",
"assetType": "crypto",
},
{
"value": "BBG000N9MNX3",
"identifier": "figi"
},
{
"value": "US0378331005",
"identifier": "isin"
}
]
}
The following shows the shape of the response for a price update. The payload will include messageType: Trades
and Trades
, an array of price data.
{
"messageType": "Trades",
"Trades":
[
{
"atomAssetId": "e56b20fb-8abd-44f6-a719-9a88f4e13c47",
"ticker": "AAPL",
"name": "Apple Inc",
"market": "USA",
"assetType": "equity",
"price": 175.06,
"bid": 165,
"ask": 178,
"changePercent": -0.0189419412687738,
"change": -3.3799999999999955,
"extendedPrice": 175.19,
"extendedChangePercent": 0.0007426025362733402,
"extendedChange": 0.12999999999999545,
"marketStatus": "AfterHours",
"latestTradeTimestamp": 1649188800828,
"openPrice": null,
"intradayHigh": 178.36,
"intradayLow": 174.43,
"closePrice": null,
"intradayVolume": 70883594,
"figi": "BBG000B9XRY4",
"isin": "US0378331005",
"feed": "CBOE_ONE"
},
]
}
{
"messageType": "Trades",
"Trades":
[
{
"ticker": "BTC",
"name": "Bitcoin",
"atomAssetId": 92834701298347102938471,
"price": 94.77,
"change24hours": -4.060000000000002,
"change24hoursPercent": -0.04108064352929275,
"marketStatus": "Open",
"volume24hours": 1154474823.272791
},
]
}
To cancel subscriptions, send a message with messageType: Unsub
and assets: Asset Object[]
, and the list of assets you wish to unsubscribe.
{
"messageType": "Unsub",
"assets":
[
{
"value": "ZZZ",
"identifier": "ticker",
"assetType": "equity",
"market": "CAN",
},
{
"value": "BTC",
"identifier": "ticker",
"assetType": "crypto",
}
]
}
Connection status
To keep the connection alive, your WebSocket client must send a Ping
message every 10 seconds:
{
"messageType": "Ping"
}
The server will acknowledge each Ping
with a Pong
:
{
"messageType": "Pong"
}
Sample code
The following code establishes a WebSocket connection with our server. It subscribes to price streaming for a few assets, unsubscribes, and pings the server every 10 seconds in order to persist the client's connection.
Note: a UI solution wouldn't require an API key for a user that's logged in.
// This is a Node.js script that requires the ws library, which can be installed
// with `npm install ws.`
const WebSocket = require("ws");
const riverWebServerURL = `wss://platform-streaming.atom.finance?api_key=<key>`;
let socket;
let timer;
const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
};
let subAssets = [
{
value: "ZZZ",
identifier: "ticker",
assetType: "equity",
market: "CAN",
},
{
value: "BTC",
identifier: "ticker",
assetType: "crypto",
},
//TSLA
{
value: "BBG000N9MNX3",
identifier: "figi",
},
//AAPL
{
value: "US0378331005",
identifier: "isin",
},
];
const unsubAssets = [
{
value: "BTC",
identifier: "ticker",
assetType: "crypto",
},
//AAPL
{
value: "US0378331005",
identifier: "isin",
},
];
const connectStreaming = (nthTry = 1) => {
socket = new WebSocket(riverWebServerURL);
socket.onmessage = (msg) => {
try {
const data = JSON.parse(msg.data);
switch (data.messageType) {
case 'Pong':
console.log("Received Pong");
return;
case 'Trades':
for (const element of data.trades) {
console.log("Latest trade for ticker:", element.ticker, element);
}
return;
}
} catch (e) {
console.error(e);
}
};
socket.onopen = async (msg) => {
try {
//subscribe assets;
console.log("Subscribing assets");
socket.send(
JSON.stringify({
messageType: 'Sub',
assets: subAssets,
})
);
//process trade data
await sleep(5000);
//unsubscribe assets no longer in use
console.log("Unsubscribing some assets");
socket.send(
JSON.stringify({
messageType: 'Unsub',
assets: unsubAssets,
})
);
//make sure you ping sever every 10s
timer = setInterval(async () => {
socket.send(JSON.stringify({ messageType: 'Ping' }));
}, 10000);
await sleep(10000);
//unsubscribe assets
console.log("Unsubscribing remaining assets");
socket.send(
JSON.stringify({
messageType: 'Unsub',
assets: subAssets,
})
);
await sleep(1000);
socket.close();
} catch (e) {
console.error(e);
}
};
socket.onclose = () => {
clearInterval(timer);
console.log("Disconnecting");
};
};
connectStreaming()