WebSocket Integration
Connect directly to StocksEyes WebSocket service for real-time stock market data with minimal latency.
Prerequisites
- Valid StocksEyes API key
- Active internet connection
- Node.js
- React.js
- Flutter
- Node.js 16 or higher
- Install dependency:
npm install ws
- React 17 or higher
- WebSocket is built-in (browser native)
- Flutter SDK 3.0+ / Dart 2.17+
- Add to
pubspec.yaml:
dependencies:
http: ^1.1.0
web_socket_channel: ^2.4.0
Then run: flutter pub get
Quick Start
Flow: Fetch URL → Connect → Subscribe → Receive Ticks → Unsubscribe → Close
Step 1: Fetch WebSocket URL
API Endpoint: GET https://api.stockseyes.com/v1/public/websocket
Response:
{
"url": "ws://***.***.***.***?token=***"
}
- Node.js
- React.js
- Flutter
const https = require('https');
function fetchWebSocketUrl() {
return new Promise((resolve, reject) => {
https.get('https://api.stockseyes.com/v1/public/websocket', {
headers: { 'Authorization': '<API_KEY>' }
}, (res) => {
let body = '';
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
const { url } = JSON.parse(body);
resolve(url);
});
}).on('error', reject);
});
}
async function fetchWebSocketUrl() {
const response = await fetch('https://api.stockseyes.com/v1/public/websocket', {
headers: { 'Authorization': '<API_KEY>' }
});
const { url } = await response.json();
return url;
}
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<String> fetchWebSocketUrl() async {
final response = await http.get(
Uri.parse('https://api.stockseyes.com/v1/public/websocket'),
headers: {'Authorization': '<API_KEY>'},
);
final data = json.decode(response.body);
return data['url'];
}
Step 2: Connect to WebSocket
- Node.js
- React.js
- Flutter
const WebSocket = require('ws');
const wsUrl = await fetchWebSocketUrl();
const ws = new WebSocket(wsUrl);
ws.on('open', () => {
console.log('Connected');
});
const wsUrl = await fetchWebSocketUrl();
const ws = new WebSocket(wsUrl);
ws.onopen = () => {
console.log('Connected');
};
import 'package:web_socket_channel/web_socket_channel.dart';
final wsUrl = await fetchWebSocketUrl();
final channel = WebSocketChannel.connect(Uri.parse(wsUrl));
Step 3: Subscribe to Instruments
- Node.js
- React.js
- Flutter
// Single instrument
ws.send('SUBSCRIBE:738561'); // RELIANCE
// Multiple instruments
ws.send('SUBSCRIBE:738561,2953217,408065');
// Single instrument
ws.send('SUBSCRIBE:738561'); // RELIANCE
// Multiple instruments
ws.send('SUBSCRIBE:738561,2953217,408065');
// Single instrument
channel.sink.add('SUBSCRIBE:738561'); // RELIANCE
// Multiple instruments
channel.sink.add('SUBSCRIBE:738561,2953217,408065');
Step 4: Listen for Data
- Node.js
- React.js
- Flutter
ws.on('message', (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.type === 'ACK') {
console.log(`${msg.action}: [${msg.instruments}]`);
} else if (msg.type === 'TICK') {
const { trading_symbol, last_price, change } = msg.data;
console.log(`${trading_symbol}: ₹${last_price} (${change?.toFixed(2)}%)`);
}
});
ws.on('error', (err) => console.error('Error:', err.message));
ws.on('close', () => console.log('Connection closed'));
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'ACK') {
console.log(`${msg.action}: [${msg.instruments}]`);
} else if (msg.type === 'TICK') {
const { trading_symbol, last_price, change } = msg.data;
console.log(`${trading_symbol}: ₹${last_price} (${change?.toFixed(2)}%)`);
}
};
ws.onerror = (err) => console.error('Error:', err);
ws.onclose = () => console.log('Connection closed');
channel.stream.listen((message) {
final data = json.decode(message);
if (data['type'] == 'ACK') {
print('${data['action']}: ${data['instruments']}');
} else if (data['type'] == 'TICK') {
final tick = data['data'];
print('${tick['trading_symbol']}: ₹${tick['last_price']}');
}
},
onError: (error) => print('Error: $error'),
onDone: () => print('Connection closed'),
);
Step 5: Unsubscribe and Close
- Node.js
- React.js
- Flutter
ws.send('UNSUBSCRIBE:738561');
ws.close();
ws.send('UNSUBSCRIBE:738561');
ws.close();
channel.sink.add('UNSUBSCRIBE:738561');
channel.sink.close();
WebSocket Commands
SUBSCRIBE
Subscribe to receive real-time data for instrument tokens.
Format:
SUBSCRIBE:token1,token2,token3
Example:
SUBSCRIBE:738561
SUBSCRIBE:738561,256265
Response:
{
"type": "ACK",
"action": "Subscribed",
"instruments": ["738561"]
}
UNSUBSCRIBE
Stop receiving data for instrument tokens.
Format:
UNSUBSCRIBE:token1,token2,token3
Example:
UNSUBSCRIBE:738561
Response:
{
"type": "ACK",
"action": "Unsubscribed",
"instruments": ["738561"]
}
Message Formats
ACK Message
Confirmation message sent by server after subscription/unsubscription.
{
"type": "ACK",
"action": "Subscribed",
"instruments": ["738561", "256265"]
}
Fields:
type: Always "ACK"action: "Subscribed" or "Unsubscribed"instruments: Array of instrument tokens
TICK Message
Real-time market data for subscribed instruments.
{
"type": "TICK",
"data": {
"instrument_token": 738561,
"trading_symbol": "RELIANCE",
"last_price": 1487.7,
"volume_traded": 5666888,
"last_traded_quantity": 1,
"average_traded_price": 1494.83,
"total_buy_quantity": 408982,
"total_sell_quantity": 761689,
"ohlc": {
"open": 1500.0,
"high": 1503.1,
"low": 1487.1,
"close": 1504.2
},
"change": -1.096,
"last_trade_time": "2025-10-30T08:48:56.000Z",
"exchange_timestamp": "2025-10-30T08:48:57.000Z",
"depth": {
"buy": [
{"quantity": 100, "price": 1487.5, "orders": 5},
{"quantity": 200, "price": 1487.0, "orders": 8}
],
"sell": [
{"quantity": 150, "price": 1488.0, "orders": 6},
{"quantity": 180, "price": 1488.5, "orders": 7}
]
},
"timestamp": 1761814138048
}
}
Key Fields:
instrument_token: Unique identifier for the instrumenttrading_symbol: Stock symbol (e.g., "RELIANCE")last_price: Current trading pricevolume_traded: Total volume tradedohlc: Open, High, Low, Close priceschange: Percentage change from previous closedepth: Order book depth (5 levels of buy/sell orders)timestamp: Unix timestamp in milliseconds
Complete Example
- Node.js
- React.js
- Flutter
const WebSocket = require('ws');
const https = require('https');
const API_URL = 'https://api.stockseyes.com/v1/public/websocket';
const INSTRUMENTS = [738561, 2953217, 408065]; // RELIANCE, TCS, INFY
// Step 1: Fetch WebSocket URL
function fetchWebSocketUrl() {
return new Promise((resolve, reject) => {
https.get(API_URL, {
headers: { 'Authorization': '<API_KEY>' }
}, (res) => {
let body = '';
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
const { url } = JSON.parse(body);
resolve(url);
});
}).on('error', reject);
});
}
// Step 2-5: Connect, Subscribe, Receive, Close
async function main() {
const wsUrl = await fetchWebSocketUrl();
const ws = new WebSocket(wsUrl);
ws.on('open', () => {
console.log('Connected');
// Step 3: Subscribe
ws.send(`SUBSCRIBE:${INSTRUMENTS.join(',')}`);
});
ws.on('message', (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.type === 'ACK') {
console.log(`${msg.action}: [${msg.instruments}]`);
} else if (msg.type === 'TICK') {
const { trading_symbol, last_price, change } = msg.data;
console.log(`${trading_symbol}: ₹${last_price} (${change?.toFixed(2)}%)`);
}
});
ws.on('error', (err) => console.error('Error:', err.message));
ws.on('close', () => console.log('Connection closed'));
// Cleanup after 30 seconds
setTimeout(() => {
ws.send(`UNSUBSCRIBE:${INSTRUMENTS.join(',')}`);
setTimeout(() => ws.close(), 2000);
}, 30000);
}
main();
import { useState, useEffect, useRef } from 'react';
function useStockEyesWebSocket(instrumentTokens) {
const [ticks, setTicks] = useState({});
const wsRef = useRef(null);
useEffect(() => {
async function connect() {
// Step 1: Fetch WebSocket URL
const response = await fetch('https://api.stockseyes.com/v1/public/websocket', {
headers: { 'Authorization': '<API_KEY>' }
});
const { url } = await response.json();
// Step 2: Connect
const ws = new WebSocket(url);
wsRef.current = ws;
ws.onopen = () => {
// Step 3: Subscribe
ws.send(`SUBSCRIBE:${instrumentTokens.join(',')}`);
};
// Step 4: Listen for data
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'TICK') {
setTicks(prev => ({
...prev,
[msg.data.instrument_token]: msg.data
}));
}
};
ws.onerror = (err) => console.error('WebSocket error:', err);
}
connect();
// Step 5: Cleanup on unmount
return () => {
if (wsRef.current) {
wsRef.current.send(`UNSUBSCRIBE:${instrumentTokens.join(',')}`);
wsRef.current.close();
}
};
}, [instrumentTokens]);
return ticks;
}
// Usage in a component
function StockTicker() {
const ticks = useStockEyesWebSocket([738561, 2953217, 408065]);
return (
<div>
{Object.values(ticks).map(tick => (
<div key={tick.instrument_token}>
{tick.trading_symbol}: ₹{tick.last_price} ({tick.change?.toFixed(2)}%)
</div>
))}
</div>
);
}
import 'package:http/http.dart' as http;
import 'package:web_socket_channel/web_socket_channel.dart';
import 'dart:convert';
class StockEyesWebSocketClient {
WebSocketChannel? _channel;
Future<void> connect() async {
// Step 1: Fetch WebSocket URL
final response = await http.get(
Uri.parse('https://api.stockseyes.com/v1/public/websocket'),
headers: {'Authorization': '<API_KEY>'},
);
final data = json.decode(response.body);
// Step 2: Connect
_channel = WebSocketChannel.connect(Uri.parse(data['url']));
// Step 4: Listen for messages
_channel!.stream.listen(
(message) {
final msg = json.decode(message);
if (msg['type'] == 'ACK') {
print('${msg['action']}: ${msg['instruments']}');
} else if (msg['type'] == 'TICK') {
final tick = msg['data'];
print('${tick['trading_symbol']}: ₹${tick['last_price']}');
}
},
onError: (error) => print('Error: $error'),
onDone: () => print('Connection closed'),
);
}
// Step 3: Subscribe
void subscribe(List<int> tokens) {
_channel?.sink.add('SUBSCRIBE:${tokens.join(',')}');
}
// Step 5: Unsubscribe and close
void unsubscribe(List<int> tokens) {
_channel?.sink.add('UNSUBSCRIBE:${tokens.join(',')}');
}
void close() => _channel?.sink.close();
}
// Usage
void main() async {
final client = StockEyesWebSocketClient();
await client.connect();
client.subscribe([738561, 2953217, 408065]);
await Future.delayed(Duration(seconds: 30));
client.unsubscribe([738561, 2953217, 408065]);
client.close();
}
Best Practices
Connection Management
✅ DO:
- Always close connections when done
- Handle connection errors gracefully
- Implement reconnection logic for production apps
❌ DON'T:
- Leave connections open indefinitely
- Ignore error states
- Create multiple connections for the same data
Subscription Management
✅ DO:
- Subscribe only to instruments you need
- Unsubscribe when data is no longer needed
- Batch multiple subscriptions in one command
❌ DON'T:
- Subscribe to hundreds of instruments at once
- Keep subscriptions active when app is in background
Data Handling
✅ DO:
- Parse JSON safely with try-catch
- Validate data before using
- Use models/classes for type safety
❌ DON'T:
- Assume all fields are present
- Ignore parsing errors
- Use dynamic types everywhere
Common Instrument Tokens
| Symbol | Token | Exchange |
|---|---|---|
| RELIANCE | 738561 | NSE |
| TCS | 2953217 | NSE |
| INFY | 408065 | NSE |
| HDFCBANK | 341249 | NSE |
| ICICIBANK | 1270529 | NSE |
Troubleshooting
Connection Issues
Problem: Connection closes immediately
Solutions:
- Verify API key is correct
- Check if WebSocket URL includes token
- Ensure network connectivity
Problem: "Unauthorized" error
Solutions:
- Verify API key in Authorization header
- Don't modify the URL returned by API
- Token is already included in URL
Data Issues
Problem: Not receiving tick data
Solutions:
- Verify you've sent SUBSCRIBE command
- Check instrument token is valid
- Ensure market is open (for live data)
- Check connection state
Problem: Parsing errors
Solutions:
- Use try-catch around JSON parsing
- Check for null values
- Validate data types before casting
Support
For issues or questions:
- Email: support@stockseyes.com
- Documentation: https://documentation.stockseyes.com
Last updated: 2025-10-30