WebSocket Market Data
Real-time market data streaming over WebSockets. Stream live quotes for selected symbols using symbol-level subscriptions. Available to PRO subscribers.
Overview
WebSocket-based real-time market data streaming with:
- Symbol-level subscriptions for efficient bandwidth usage
- Low-latency quote updates
- Automatic reconnection support
- Premium entitlement required
Note: This feature requires a PRO subscription. Non-PRO users will receive an
ENTITLEMENT_REQUIRED
error.
Connection Endpoint
Connect to our WebSocket server for real-time market data streaming.
WebSocket URL
wss://api.paperinvest.io/v1/ws/market
Connection Example
Connection
import { io } from 'socket.io-client';
// Connect to the namespace via URL; keep Socket.IO path default '/socket.io'
const socket = io('https://api.paperinvest.io/v1/ws/market', {
path: '/socket.io',
transports: ['websocket'],
auth: { token: `Bearer ${YOUR_JWT}` }
});
// Connection event handlers
socket.on('connect', () => {
console.log('WebSocket connected');
});
socket.on('disconnect', (reason) => {
console.log('WebSocket disconnected:', reason);
});
Client Messages
Messages sent from client to server for managing subscriptions.
Subscribe Message
Subscribe to real-time quotes for specific symbols:
Subscribe Message
{
"type": "subscribe",
"symbols": ["AAPL", "MSFT", "GOOGL"],
"channels": ["quote"]
}
Unsubscribe Message
Remove symbols from your active subscriptions:
Unsubscribe Message
{
"type": "unsubscribe",
"symbols": ["AAPL"]
}
Message | Body | Description |
---|---|---|
subscribe | { symbols: string[], channels?: string[] } | Add symbols to subscription list |
unsubscribe | { symbols: string[] } | Remove symbols from subscription list |
Note:
channels
parameter is reserved for future extensions (e.g.,trade
,book
). Currently onlyquote
channel is supported.
Server Events
Events emitted from the server to connected clients.
Event | Payload | Description |
---|---|---|
connected | Connection info | Successful WebSocket connection established |
subscribed | Subscription confirmation | Symbols successfully added to subscription |
unsubscribed | Unsubscribe confirmation | Symbols successfully removed from subscription |
quote | Quote data | Real-time quote update for subscribed symbol |
error | Error details | Error message including entitlement failures |
Event Payloads
Event Payloads
// Connected Event
{
"message": "Connected to market data stream",
"clientId": "ws_1715743859000",
"plan": "pro",
"timestamp": 1715743859000
}
// Quote Event
{
"symbol": "AAPL",
"bid": 175.20,
"ask": 175.30,
"bidSize": 300,
"askSize": 200,
"timestamp": 1715743859000
}
// Error Event
{
"code": "ENTITLEMENT_REQUIRED",
"message": "PRO subscription required for market data streaming"
}
Implementation Examples
Complete examples for implementing WebSocket market data streaming.
Full Implementation
import { io } from 'socket.io-client';
class MarketDataStream {
constructor(token) {
this.token = token;
this.socket = null;
this.subscriptions = new Set();
}
connect() {
this.socket = io('https://api.paperinvest.io', {
path: '/v1/ws/market',
transports: ['websocket'],
auth: { token: `Bearer ${this.token}` }
});
this.socket.on('connected', (info) => {
console.log('Connected to market data:', info);
// Resubscribe to any existing symbols after reconnect
if (this.subscriptions.size > 0) {
this.subscribe(Array.from(this.subscriptions));
}
});
this.socket.on('subscribed', (data) => {
console.log('Subscribed to:', data.symbols);
data.symbols.forEach(s => this.subscriptions.add(s));
});
this.socket.on('quote', (quote) => {
this.handleQuote(quote);
});
this.socket.on('error', (error) => {
console.error('WebSocket error:', error);
if (error.code === 'ENTITLEMENT_REQUIRED') {
console.error('PRO subscription required');
}
});
this.socket.on('disconnect', (reason) => {
console.log('Disconnected:', reason);
// Socket.IO will automatically reconnect
});
}
subscribe(symbols) {
this.socket.emit('subscribe', {
symbols: symbols,
channels: ['quote']
});
}
unsubscribe(symbols) {
this.socket.emit('unsubscribe', { symbols });
symbols.forEach(s => this.subscriptions.delete(s));
}
handleQuote(quote) {
// Process real-time quote update
console.log(`${quote.symbol}: Bid ${quote.bid} @ ${quote.bidSize} - Ask ${quote.ask} @ ${quote.askSize}`);
}
disconnect() {
if (this.socket) {
this.socket.disconnect();
}
}
}
// Usage
const stream = new MarketDataStream('YOUR_JWT_TOKEN');
stream.connect();
stream.subscribe(['AAPL', 'MSFT', 'GOOGL']);
// Later...
// stream.unsubscribe(['AAPL']);
// stream.disconnect();
Requirements
Requirements
Authorization: Bearer <JWT>
Plan: PRO subscription required
Best Practices
Connection Management
- Single Connection: Use one WebSocket connection per application and manage subscriptions dynamically
- Reconnection: Implement automatic reconnection with exponential backoff
- Subscription State: Maintain local subscription state for reconnection recovery
Performance Optimization
- Batch Operations: Group subscribe/unsubscribe operations when possible
- Symbol Validation: Validate symbols client-side before subscribing
- Throttling: Implement client-side throttling for subscription changes
Error Handling
- Graceful Degradation: Handle entitlement and rate limit errors gracefully
- Logging: Log connection events and errors for debugging
- Heartbeat: Monitor connection health with periodic ping/pong