WebSocket is a protocol that allows for real-time, two-way communication between a client and a server. It’s particularly well-suited for technical indicators because it enables instant updates, ensuring traders have the most current data for making timely decisions in fast-paced markets.
NOTE: IN BETA! This feature is new, thus no plans support this feature yet. If you’re interested to try it out, please get in contact with us, and we’ll set you up!
You will need at least a pro or expert plan which supports Web Socket Subscriptions, if you’re not on one of these plans, please get in touch today.
Getting started
To get started, you’ll need to make a connection to one of our socket servers. We provide a server pool per exchange:
wss://ws-<exchange>.taapi.io
Please visit our exchanges page for valid exchanges.
At the moment we have:
- US Stocks:
wss://ws-stocks.taapi.io
- Binance Futures:
wss://ws-binancefutures.taapi.io
- Gate.IO:
wss://ws-gateio.taapi.io
Messages
All messages sent to and from the server must always be in valid JSON format and string serialized. And all messages must have a type
property.
Authentication
Once you’re connected, you have to authenticate with your secret key by sending a message to the server:
{
"type": "auth",
"secret": "MY_SECRET"
}
If you have a valid secret, and your plan allows for socket subscriptions, you should see a response like:
{
"type":"auth",
"success":true,
"message":"Welcome John, you have 10 allowed subscriptions!"
}
Subscribing
To subscribe to updates, you will need to send a subscribe
message. Subscribing to updates means that you will start receiving real-time data.
A subscription is exactly equal to 1 calculation. This might mean the RSI for AAPL on the 5m timeframe, or the EMA(200) for TSLA on the daily.
You can subscribe and unsubscribe to updates as much as you want, as long as you stay within the subscription rate-limits outlined below.
{
"type": "subscribe",
"channel": {
"id": "apple-1m-fast-ema",
"symbol": "AAPL",
"interval": "1m",
"indicator": "ema",
"params": {
"period": 20
}
}
}
{
"type": "subscribed",
"channel": "AAPL-1m-ema-period-20",
"remainingSubscriptions": 9,
"id": "bitcoin-1m-fast-ema"
}
Unsubscribing
To stop the real-time data, and free up a subscription slot, all you have to do is send the same request as when subscribing but simply change the type to ‘unsubscribe’
{
"type": "unsubscribe",
"channel": {
"id": "apple-1m-fast-ema",
"symbol": "AAPL",
"interval": "1m",
"indicator": "ema",
"params": {
"period": 20
}
}
}
You will receive a message of type: 'unsubscribed'
back.
Connections & Rate limits
Connections
Every user is allowed 1 connection
.
Subscribing / unsubscribing
Subscribing and un-subscribing may not be done at a faster rate than 5 times / second
, or use a 200ms
delay in between multiple subscriptions. If exceeded, you will receive a ‘Rate-limits exceeded’ error.
{
"type": "error",
"message": "Rate limits exceeded"
}
Ping / pong
Every 30 seconds the server will send you a ping, you must respond to this ping with a ‘pong’, otherwise your connection will be closed. Most Web Socket clients will actually handle this for you, so you most likely don’t need to worry about it. However, if you keep getting disconnected for some reason, then try responding with a pong()
.
Kicks
If your connection for some reason didn’t close properly and you find yourself locked out, you can send a kick request to reset your own connection.
[GET] https://ws-<exchange>.taapi.io/api/kick?secret=MY_SECRET
{
"success": true,
"message": "User kicked"
}
Examples
NodeJS / Javascript
Below a Crypto example receiving [1d Candle, MACD, EMA200, RSI] for Bitcoin to USDT on various timeframes:
import WebSocket from 'ws';
// Create a WebSocket client instance
const client = new WebSocket('wss://ws-gateio.taapi.io');
client.on('open', (connection) => {
console.log('Connected to server');
// Authenticate with the server
client.send(JSON.stringify({ type: 'auth', secret: "MY_SECRET" }));
});
/* client.on('ping', (encodedMessage) => {
client.pong(); // This is usually handled automatically, enable this if you get disconnected often
}); */
client.on('message', (encodedMessage) => {
const receivedBuffer = Buffer.from(encodedMessage, 'hex');
const message = receivedBuffer.toString('utf8');
const data = JSON.parse(message);
if (data.type === 'auth') {
if (data.success) {
console.log('Authenticated successfully!', data.message);
// Define subscriptions
let subscriptions = [];
subscriptions.push({ type: 'subscribe', channel: {
id: "BTC/USDT-1d-candle",
symbol: "BTC/USDT",
interval: "1d",
indicator: "candle"
}});
subscriptions.push({ type: 'subscribe', channel: {
id: "BTC/USDT-1h-macd",
symbol: "BTC/USDT",
interval: "1h",
indicator: "macd"
}});
subscriptions.push({ type: 'subscribe', channel: {
id: "BTC/USDT-1h-ema-200",
symbol: "BTC/USDT",
interval: "1h",
indicator: "ema",
params: {
period: 200
}
}});
subscriptions.push({ type: 'subscribe', channel: {
id: "LTC/BTC-5m-rsi",
symbol: "LTC/BTC",
interval: "5m",
indicator: "rsi"
}});
// Subscribe respecting the rate-limits of 5 per second
for(let i = 0; i < subscriptions.length; i++) {
setTimeout(() => {
client.send(JSON.stringify(subscriptions[i]));
}, 200 * i);
}
} else {
console.log('Authentication failed', data.message);
}
} else if(data.type === 'update') {
console.log('Received update:', data);
} else {
console.log('Unhandled message:', data);
}
});
// Close the connection
client.on('close', (reasonCode, description) => {
console.log('Connection closed:', reasonCode, description);
});
Let’s try a Stocks example, receiving [1h Candle, StochRSI, EMA50] for AAPL on various timeframes:
import WebSocket from 'ws';
// Create a WebSocket client instance
const client = new WebSocket('wss://ws-stocks.taapi.io');
client.on('open', (connection) => {
console.log('Connected to server');
// Authenticate with the server
client.send(JSON.stringify({ type: 'auth', secret: "MY_SECRET" }));
});
/* client.on('ping', (encodedMessage) => {
client.pong(); // This is usually handled automatically, enable this if you get disconnected often
}); */
client.on('message', (encodedMessage) => {
const receivedBuffer = Buffer.from(encodedMessage, 'hex');
const message = receivedBuffer.toString('utf8');
const data = JSON.parse(message);
if (data.type === 'auth') {
if (data.success) {
console.log('Authenticated successfully!', data.message);
// Define subscriptions
let subscriptions = [];
subscriptions.push({ type: 'subscribe', channel: {
id: "AAPL-1h-candle",
symbol: "AAPL",
interval: "1h",
indicator: "candle"
}});
subscriptions.push({ type: 'subscribe', channel: {
id: "AAPL-15m-stochrsi",
symbol: "AAPL",
interval: "15m",
indicator: "stochrsi"
}});
subscriptions.push({ type: 'subscribe', channel: {
id: "AAPL-1m-ema-50",
symbol: "AAPL",
interval: "1m",
indicator: "ema",
params: {
period: 50
}
}});
// Subscribe respecting the rate-limits of 5 per second
for(let i = 0; i < subscriptions.length; i++) {
setTimeout(() => {
client.send(JSON.stringify(subscriptions[i]));
}, 200 * i);
}
} else {
console.log('Authentication failed', data.message);
}
} else if(data.type === 'update') {
console.log('Received update:', data);
} else {
console.log('Unhandled message:', data);
}
});
// Close the connection
client.on('close', (reasonCode, description) => {
console.log('Connection closed:', reasonCode, description);
});
That’s it
You can now receive real-time indicator values and only receive updates as the market changes. As always, any / all feedback is always welcome.