Skip to main content

WebSocket Integration

Connect directly to StocksEyes WebSocket service for real-time stock market data with minimal latency. This guide provides complete implementation details for Flutter applications.

Prerequisites

  • Flutter SDK 3.0 or higher
  • Dart 2.17 or higher
  • Valid StocksEyes API key
  • Active internet connection

Installation

Add the following dependencies to your pubspec.yaml:

dependencies:
flutter:
sdk: flutter
http: ^1.1.0 # For HTTP API calls
web_socket_channel: ^2.4.0 # For WebSocket connection

Install packages:

flutter pub get

Quick Start

Step 1: Fetch WebSocket URL

First, obtain the WebSocket URL with authentication token from the API:

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'];
}

API Endpoint: GET https://api.stockseyes.com/v1/public/websocket

Response:

{
"url": "ws://***.***.***.***?token=***"
}

Step 2: Connect to WebSocket

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

Subscribe to receive real-time data for specific instrument tokens:

// Subscribe to single instrument
channel.sink.add('SUBSCRIBE:738561'); // RELIANCE

// Subscribe to multiple instruments
channel.sink.add('SUBSCRIBE:738561,256265,408065');

Step 4: Listen for Data

channel.stream.listen((message) {
final data = json.decode(message);

if (data['type'] == 'ACK') {
print('Subscription confirmed: ${data['instruments']}');
} else if (data['type'] == 'TICK') {
print('Price update: ${data['data']['trading_symbol']} - ₹${data['data']['last_price']}');
}
});

Step 5: Unsubscribe and Close

// Unsubscribe from instruments
channel.sink.add('UNSUBSCRIBE:738561');

// Close connection
channel.sink.close();

WebSocket Commands

SUBSCRIBE

Subscribe to receive real-time data for instrument tokens.

Format:

SUBSCRIBE:token1,token2,token3

Example:

channel.sink.add('SUBSCRIBE:738561');        // Single
channel.sink.add('SUBSCRIBE:738561,256265'); // Multiple

Response:

{
"type": "ACK",
"action": "Subscribed",
"instruments": ["738561"]
}

UNSUBSCRIBE

Stop receiving data for instrument tokens.

Format:

UNSUBSCRIBE:token1,token2,token3

Example:

channel.sink.add('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 instrument
  • trading_symbol: Stock symbol (e.g., "RELIANCE")
  • last_price: Current trading price
  • volume_traded: Total volume traded
  • ohlc: Open, High, Low, Close prices
  • change: Percentage change from previous close
  • depth: Order book depth (5 levels of buy/sell orders)
  • timestamp: Unix timestamp in milliseconds

Complete Example

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 {
// 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);
final wsUrl = data['url'];

// Connect to WebSocket
_channel = WebSocketChannel.connect(Uri.parse(wsUrl));

// Listen for messages
_channel!.stream.listen(
(message) {
final data = json.decode(message);
_handleMessage(data);
},
onError: (error) => print('Error: $error'),
onDone: () => print('Connection closed'),
);
}

void _handleMessage(Map<String, dynamic> data) {
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']}');
}
}

void subscribe(List<int> tokens) {
final command = 'SUBSCRIBE:${tokens.join(',')}';
_channel?.sink.add(command);
}

void unsubscribe(List<int> tokens) {
final command = 'UNSUBSCRIBE:${tokens.join(',')}';
_channel?.sink.add(command);
}

void close() {
_channel?.sink.close();
}
}

// Usage
void main() async {
final client = StockEyesWebSocketClient();
await client.connect();

// Subscribe to RELIANCE
client.subscribe([738561]);

// Wait for data...
await Future.delayed(Duration(seconds: 30));

// Cleanup
client.unsubscribe([738561]);
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

SymbolTokenExchange
RELIANCE738561NSE
TCS2953217NSE
INFY408065NSE
HDFCBANK341249NSE
ICICIBANK1270529NSE

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:


Last updated: 2025-10-30