API Documentation
Complete guide to Turboline's REST API and WebSocket streaming. Built for developers, understandable by everyone.
Backend Setup
Before using the API, you need to set up and run the TurboStream backend server. Follow these steps to configure your environment.
Prerequisites
- Go 1.21 or higher
- MongoDB (local or cloud instance)
- At least one LLM provider API key (OpenAI, Anthropic, Azure, etc.)
Environment Configuration
Create a .env.local file in your TurboStream project root with the following variables:
# Server Configuration
BACKEND_HOST=0.0.0.0
BACKEND_PORT=7210
# Note: Port is customizable - change to any available port
CORS_ORIGIN=http://localhost:7200
REQUEST_TIMEOUT_MS=15000
# Authentication & Security
JWT_SECRET=your-secure-jwt-secret-change-me
ENCRYPTION_KEY=your-secure-encryption-key-change-me
# MongoDB
MONGODB_URI=mongodb://localhost:27017
MONGODB_DB_NAME=turbostream
# ============================================
# LLM Provider Configuration (BYOM)
# ============================================
# Set DEFAULT_AI_PROVIDER to: azure-openai, openai, anthropic, gemini, mistral, grok, or ollama
DEFAULT_AI_PROVIDER=openai
# OpenAI (Recommended for getting started)
OPENAI_API_KEY=sk-your-openai-api-key
OPENAI_MODEL=gpt-4o
# Azure OpenAI (Enterprise)
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
AZURE_OPENAI_API_KEY=your-azure-api-key
AZURE_OPENAI_API_VERSION=2024-02-15-preview
AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4o
# Anthropic (Claude)
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
ANTHROPIC_MODEL=claude-3-5-sonnet-20241022
# Google AI (Gemini)
GOOGLE_API_KEY=your-google-api-key
GOOGLE_MODEL=gemini-1.5-flash
# Mistral
MISTRAL_API_KEY=your-mistral-api-key
MISTRAL_MODEL=mistral-large-latest
# xAI (Grok)
XAI_API_KEY=xai-your-grok-api-key
XAI_MODEL=grok-beta
# Ollama (Local LLM - no API key needed)
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama3.2
# LLM Settings
LLM_MAX_TOKENS=1024
LLM_TEMPERATURE=0.7
LLM_CONTEXT_LIMIT=50
# Token Limits (optional)
TOKEN_QUOTA_PER_MONTH=1000000💡 Bring Your Own Model (BYOM):
TurboStream supports multiple LLM providers. You only need to configure ONE provider to get started. Set your DEFAULT_AI_PROVIDER and provide the corresponding API key.
Starting the Server
# Navigate to TurboStream directory
cd /path/to/turbostream
# Build the server
go build -o turbostream ./cmd/server
# Run the server
./turbostream✓ MongoDB connected
✓ OpenAI enabled (model: gpt-4o)
✓ 1 LLM provider(s) available: [openai]
✓ Started topic LLM scheduler for feed 65f789...
🚀 Go backend listening on 0.0.0.0:7210 (CORS: http://localhost:7200)⚠️ Port Configuration: The default port is 7210 but you can change it in your .env.local file by updating BACKEND_PORT. Make sure to update the base URL in all API requests if you change the port.
Verify Installation
Test that your server is running correctly:
curl http://localhost:7210/health{
"status": "ok",
"timestamp": "2026-01-30T12:00:00Z"
}Getting Started
Now that your backend is running, let's create an account and start using the API.
Step 1: Create an Account
/api/auth/registerCreate a new user account
{
"email": "[email protected]",
"password": "SecurePassword123!",
"name": "Your Name"
}{
"message": "User registered successfully",
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsIn....",
"user": {
"_id": "65f123abc456def789ghijkl",
"email": "[email protected]",
"name": "Your Name",
"createdAt": "2026-01-30T19:54:10.63Z",
"tokenUsage": {
"currentMonth": "2026-01",
"tokensUsed": 0,
"limit": 1000000,
"lastResetDate": "2026-01-30T19:54:10.63Z",
"overdraftAllowed": true
},
"twoFactorEnabled": false
}
}💡 Tip: Save the token from the response. You'll need it for all authenticated API requests.
What You Can Do
Connect to Feeds
Stream real-time data from any WebSocket source or create your own custom feeds.
LLM Intelligence
Get AI-powered analysis and insights on your streaming data automatically or on-demand.
Topic Routing
Separate intelligence by topic (e.g., BTC-USD, ETH-USD) with isolated context and memory.
Real-Time WebSocket
Consume data and intelligence via WebSocket for instant updates with zero polling.
Authentication
Turboline uses JWT (JSON Web Tokens) for authentication. Include your token in the Authorization header for all protected endpoints.
Login to Get Your Token
/api/auth/loginAuthenticate and receive a JWT token
{
"email": "[email protected]",
"password": "SecurePassword123!"
}{
"message": "Login successful",
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsIn....",
"user": {
"_id": "65f123abc456def789ghijkl",
"email": "[email protected]",
"name": "Your Name",
"createdAt": "2026-01-30T19:54:10.63Z",
"tokenUsage": {
"currentMonth": "2026-01",
"tokensUsed": 0,
"limit": 1000000,
"lastResetDate": "2026-01-30T19:54:10.63Z",
"overdraftAllowed": true
},
"twoFactorEnabled": false
}
}💡 Tip: Save the token from the response. You'll need it for all authenticated API requests.
Using Your Token
Add your JWT token to the Authorization header with the Bearer prefix:
curl -X GET "http://localhost:7210/api/auth/me" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
fetch('http://localhost:7210/api/auth/me', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(data => console.log(data));Get Your Profile
/api/auth/meGet authenticated user's profile and token usage
🔒 Requires Authentication{
"success": true,
"user": {
"_id": "65f123abc456def789ghijkl",
"email": "[email protected]",
"name": "Your Name",
"createdAt": "2026-01-30T19:54:10.63Z",
"lastLogin": "2026-01-30T20:59:32.192Z",
"tokenUsage": {
"currentMonth": "2026-01",
"tokensUsed": 15234,
"limit": 1000000,
"lastResetDate": "2026-01-30T19:54:10.63Z",
"overdraftAllowed": true
},
"twoFactorEnabled": false
}
}⚠️ Security: Never expose your JWT token in client-side code or commit it to version control. Tokens expire after 7 days and must be refreshed by logging in again.
Feed Management
Feeds are WebSocket data sources that stream real-time information. Create custom feeds or subscribe to public marketplace feeds.
Browse Public Feeds
/api/marketplace/feedsList all public feeds (no auth required)
/api/marketplace/feeds/popular?limit=10Get most subscribed feeds
/api/marketplace/feeds/search?q=crypto&category=financeSearch feeds by keyword and category
{
"count": 1,
"data": [
{
"_id": "697d10f5824ee2ba77fcad87",
"name": "Coinbase",
"description": "Real-time price updates for Coinbase Pro trading pairs. Track price, volume, and 24h statistics.",
"url": "wss://ws-feed.exchange.coinbase.com",
"category": "finance",
"isActive": true,
"isVerified": false,
"isPublic": true,
"feedType": "user",
"userId": "697d0c62824ee2ba77fcad84",
"ownerName": "Manas Mudbari",
"connectionType": "websocket",
"connectionMessages": [
"{ \"type\": \"subscribe\", \"product_ids\": [ \"BTC-USD\", \"ETH-USD\", \"SOL-USD\"], \"channels\": [ \"ticker\" ] }"
],
"reconnectionEnabled": true,
"subscriberCount": 2,
"tags": null,
"enableTopicRouting": false,
"createdAt": "2026-01-30T20:13:41.199Z",
"updatedAt": "2026-01-30T20:13:41.199Z"
}
],
"success": true
}Create a Custom Feed
/api/marketplace/feedsCreate a new feed
🔒 Requires Authentication{
"name": "My Custom Feed",
"description": "Description of what this feed provides",
"url": "wss://example.com/stream",
"category": "technology",
"isPublic": false,
"connectionType": "websocket"
}💡 Need WebSocket Examples?
Check out our WebSocket Examples Directory for ready-to-use feed configurations including Binance, Coinbase, Kraken, and more.
{
"name": "Multi-Instrument Market Data",
"description": "Real-time prices for multiple trading pairs",
"url": "wss://stream.binance.com:9443/ws/!ticker@arr",
"category": "finance",
"isPublic": true,
"connectionType": "websocket",
"enableTopicRouting": true,
"topicField": "s",
"connectionMessages": [
"{\"method\":\"SUBSCRIBE\",\"params\":[\"btcusdt@ticker\",\"ethusdt@ticker\"],\"id\":1}"
]
}💡 Topic Routing:
enableTopicRouting: true- Activates per-topic intelligence modetopicField: "s"- Replace "s" with the actual field name from your feed data that contains the topic identifierconnectionMessages- Use\\"to escape quotes in JSON strings (as shown in the Request Body above)- Each topic gets: Isolated LLM context + memory + continuous analysis
ConnectionMessages Converter
Struggling with escaping quotes? Paste your WebSocket subscription message and we'll convert it to the correct format for connectionMessages.
Enter the JSON message your WebSocket provider expects for subscription
{
"data": {
"_id": "65f789abc123...",
"name": "My Custom Feed",
"description": "Description of what this feed provides",
"url": "wss://example.com/stream",
"category": "technology",
"isActive": true,
"isVerified": false,
"isPublic": false,
"feedType": "user",
"userId": "65f123def456...",
"ownerName": "Your Name",
"connectionType": "websocket",
"connectionMessages": [],
"reconnectionEnabled": true,
"subscriberCount": 0,
"tags": null,
"enableTopicRouting": false,
"createdAt": "2026-01-30T10:00:00Z",
"updatedAt": "2026-01-30T10:00:00Z"
},
"success": true
}Subscribe to a Feed
/api/marketplace/subscribe/:feedIdSubscribe to receive data from a feed
🔒 Requires Authenticationcurl -X POST "http://localhost:7210/api/marketplace/subscribe/65f789..." \
-H "Authorization: Bearer YOUR_TOKEN"{
"message": "Subscribed",
"subscription": {
"_id": "65f999abc123...",
"userId": "65f123def456...",
"feedId": "65f789abc123...",
"subscribedAt": "2026-01-30T10:05:00Z",
"isActive": true
},
"success": true
}Manage Your Subscriptions
/api/marketplace/subscriptionsList all your active subscriptions
🔒 Requires Authentication/api/marketplace/unsubscribe/:feedIdUnsubscribe from a feed
🔒 Requires AuthenticationManage Topic Prompts
/api/marketplace/feeds/:idUpdate feed properties including topic-specific prompts
🔒 Requires Authentication{
"topicPrompts": {
"BTCUSDT": {
"systemPrompt": "You are a Bitcoin market analyst.",
"question": "What are the key price movements?"
},
"ETHUSDT": {
"systemPrompt": "You are an Ethereum market analyst.",
"question": "Analyze the current trend."
}
}
}{
"success": true,
"data": {
"_id": "65f789abc123...",
"name": "Binance Crypto Prices",
"topicPrompts": {
"BTCUSDT": {
"systemPrompt": "You are a Bitcoin market analyst.",
"question": "What are the key price movements?"
},
"ETHUSDT": {
"systemPrompt": "You are an Ethereum market analyst.",
"question": "Analyze the current trend."
}
}
}
}/api/marketplace/feeds/:id/ai-promptUpdate the default AI prompt for a feed
🔒 Requires Authentication{
"defaultAIPrompt": "You are a financial analyst specializing in cryptocurrency markets."
}{
"success": true,
"data": {
"_id": "65f789abc123...",
"name": "My Feed",
"defaultAIPrompt": "You are a financial analyst specializing in cryptocurrency markets."
}
}Topic Routing
Split a single data feed into multiple intelligence streams. Each topic (e.g., BTC-USD, ETH-USD) gets its own AI analysis, memory, and subscribers.
Two Independent Settings
1. Connection Messages
What you send TO the feed provider to subscribe
Controls what data you receive
2. Topic Field
What you extract FROM incoming messages to organize data
Controls how data is routed and analyzed
💡 Key Insight: Connection messages and topic field are separate. The connection message tells the provider what to send you. The topic field tells TurboStream how to organize what you receive.
Topic Field Syntax
The topicField extracts a routing key from incoming data. Use TurboStream's simple syntax to navigate your data structure.
| Pattern | What It Does | Use When |
|---|---|---|
"symbol" | Gets a top-level field | Field is at root of data |
"data.origin" | Gets a nested field | Field is inside an object |
"[3]" | Gets item at position 3 | Data is an array (4th item) |
"path[0]" | Gets first item in array | Field contains an array |
"path[-1]" | Gets last item in array | Array length varies |
"data.path[-1]" | Gets last item of nested array | Combining nested + array access |
📌 Note: This is TurboStream's custom syntax (similar to Python/jq). Array positions start at 0. Only [-1] is supported for negative indexing (last element).
TopicField Generator
Not sure what pattern to use? Paste your WebSocket JSON response and the value you want to extract, and we'll generate the topicField pattern for you.
Enter a field name (like "path" or "symbol") or an exact value to find
Example 1: Simple Field (Cryptocurrency)
{
"name": "Coinbase Crypto Prices",
"url": "wss://ws-feed.exchange.coinbase.com",
"enableTopicRouting": true,
"topicField": "product_id", // Extract the "product_id" field from each message
"connectionMessages": [
"{\"type\":\"subscribe\",\"product_ids\":[\"BTC-USD\",\"ETH-USD\"],\"channels\":[\"ticker\"]}"
]
}{
"type": "ticker",
"sequence": 93483876225,
"product_id": "BTC-USD", // ← This becomes the topic
"price": "42150.50",
"open_24h": "41500.00",
"volume_24h": "25643.12345678",
"low_24h": "41200.00",
"high_24h": "42500.00",
"best_bid": "42150.49",
"best_ask": "42150.51",
"side": "buy",
"time": "2026-02-09T15:33:13.483677Z",
"trade_id": 769630264,
"last_size": "0.001"
}
{
"type": "ticker",
"sequence": 93483876226,
"product_id": "ETH-USD", // ← This becomes a different topic
"price": "2035.8",
"open_24h": "2107.39",
"volume_24h": "174471.54258318",
"low_24h": "2006.88",
"high_24h": "2150",
"best_bid": "2035.79",
"best_ask": "2035.96",
"side": "buy",
"time": "2026-02-09T15:33:13.483677Z",
"trade_id": 769630264,
"last_size": "0.001"
}✅ What Happens:
- • TurboStream extracts
"BTC-USD"and"ETH-USD"from the"product_id"field - • Creates separate AI analysis for Bitcoin and Ethereum
- • Clients can subscribe to just the topics they care about
Example 2: Nested Array (Internet Routing)
{
"name": "BGP Route Updates",
"url": "wss://ris-live.ripe.net/v1/ws/",
"enableTopicRouting": true,
"topicField": "data.path[-1]", // Get last item from nested array
"connectionMessages": [
"{\"type\":\"ris_subscribe\",\"data\":{\"origin\":\"2856\"}}"
]
}{
"data": {
"path": [41722, 12389, 1299, 174, 40138],
// ↑ Last element = origin network
"type": "UPDATE"
}
}
// TurboStream extracts: 40138Example 3: Root Array (Trading Data)
{
"name": "Kraken Trades",
"url": "wss://ws.kraken.com",
"enableTopicRouting": true,
"topicField": "[3]", // Get item at position 3 from root array
"connectionMessages": [
"{\"event\":\"subscribe\",\"pair\":[\"XBT/USD\"],\"subscription\":{\"name\":\"trade\"}}"
]
}[
119930881, // [0] Channel ID
[[...]], // [1] Trade data
"trade", // [2] Event type
"XBT/USD" // [3] ← Trading pair (topic)
]
// TurboStream extracts: "XBT/USD"💡 Summary: The topic field can extract data from anywhere in the message structure. Each provider formats data differently - just tell TurboStream where to look.
LLM Intelligence
Get AI-powered insights on your streaming data. Choose between manual queries or continuous automatic analysis.
Output Modes
Manual Mode
Query the LLM on-demand via API. You control when to ask questions.
- ✓ Full control over prompts
- ✓ Cost-efficient (pay per query)
- ✓ Custom system prompts
Auto Mode (Topic Routing)
Continuous LLM analysis for each topic. Automated intelligence streaming.
- ✓ Real-time insights every 10s
- ✓ Per-topic intelligence
- ✓ No manual queries needed
Manual Query (REST API)
/api/llm/queryAsk a question about feed data
🔒 Requires Authentication{
"feedId": "65f789...",
"question": "What are the main trends in the data?",
"provider": "openai",
"systemPrompt": "You are a financial analyst..."
}{
"answer": "Based on the recent data, I observe three main trends:\n\n1. **Upward Price Movement**: Bitcoin has increased 3.5% over the last 50 entries...\n\n2. **Increased Volatility**: The price range has widened...\n\n3. **Volume Surge**: Trading volume spiked by 25%...",
"provider": "openai",
"feedId": "65f789...",
"tokensUsed": 450,
"durationMs": 1250
}Streaming Query
/api/llm/query/streamStream LLM response token-by-token
🔒 Requires Authenticationconst response = await fetch('/api/llm/query/stream', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
feedId: '65f789...',
question: 'Analyze the recent price action'
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
process.stdout.write(chunk);
}Auto Mode Configuration
When you enable enableTopicRouting on a feed, automatic LLM analysis is activated for each topic.
Analysis Intervals
10 seconds50 entriesLast 3 Q&A pairs"Provide a brief analysis..."Configuring Analysis Interval
You can customize the analysis interval for topic-routed feeds via environment variables or by modifying feed settings.
# In your .env.local file
LLM_QUERY_INTERVAL_SECONDS=10
# Options: 5, 10, 30, 60 (seconds)
# This sets the default for all topic-routed feeds/api/marketplace/feeds/:feedIdUpdate feed settings including custom interval
🔒 Requires Authenticationcurl -X PUT "http://localhost:7210/api/marketplace/feeds/65f789..." \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"queryInterval": 30
}'
# queryInterval: Analysis interval in seconds (5, 10, 30, 60)
# This overrides the global default for this specific feed⚠️ Note: Shorter intervals (5-10s) provide faster insights but consume more LLM tokens. Longer intervals (30-60s) are more cost-effective but updates are less frequent. Choose based on your use case and token budget.
Available LLM Providers
/api/llm/providersGet list of configured LLM providers
{
"enabled": true,
"providers": ["openai", "anthropic", "gemini", "azure-openai"]
}



API Keys for Third Party App Integration
API keys allow your applications, scripts, and services to connect to TurboStream's WebSocket API without user login credentials. Perfect for third party integrations, automated systems, backend services, and IoT devices.
What's the Difference?
JWT Tokens - For user accounts. Used with the web dashboard and REST API. Requires login with email/password.
API Keys - For automated systems. No login needed. Each key has specific permissions (scopes) to control what it can do.
What are Scopes?
Scopes control what an API key can do. This keeps your system secure by giving each key only the permissions it needs.
websocket:subscribeAccess raw feed data streams. Can subscribe to feeds and receive data updates.
Use for: Data ingestion pipelines, monitoring dashboards
websocket:llmAccess AI-powered analysis. Can query the LLM and receive intelligent insights.
Use for: AI chatbots, automated trading analysis
websocket:topicSubscribe to topic-specific intelligence. Perfect for multi-instrument data.
Use for: Per-asset analysis, multi-channel monitoring
websocket:*Full access to all WebSocket operations. Has all permissions above.
Use for: Admin tools, full-featured applications
💡 Best Practice: Only grant the scopes your application needs. For example, if you only need to read data, use websocket:subscribe instead of websocket:*. This follows the principle of least privilege.
Creating an API Key
First, you need to be logged in with your JWT token (from login). API keys can only be created by authenticated users.
/api/auth/api-keysCreate a new API key with specific scopes
🔒 Requires Authentication{
"name": "My Trading Bot",
"scopes": ["websocket:subscribe", "websocket:llm"]
}📝 Naming Tips:
- Use descriptive names like "Production Trading Bot" or "Dev Dashboard"
- Include environment: "Staging API Key" vs "Production API Key"
- Names must be unique for each user
const response = await fetch('http://localhost:7210/api/auth/api-keys', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_JWT_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'My Trading Bot',
scopes: ['websocket:subscribe', 'websocket:llm']
})
});
const data = await response.json();
console.log('API Key:', data.key);
// SAVE THIS KEY! You won't see it again{
"success": true,
"message": "API key created successfully. Store this key securely - it will not be shown again.",
"apiKey": {
"_id": "65f999abc123...",
"name": "My Trading Bot",
"prefix": "ts_live_",
"lastChars": "8dF2aC9b",
"scopes": ["websocket:subscribe", "websocket:llm"],
"createdAt": "2026-02-02T10:00:00Z"
},
"key": "ts_live_a7Kx9mP2nQ5wR8yT4vB6cD1eF3gH0jL5_8dF2aC9b"
}⚠️ CRITICAL: Save Your Key Immediately!
The full API key (starting with ts_live_) is shown ONLY ONCE when created. If you lose it, you'll need to revoke and create a new one. Store it in a secure location like a password manager or environment variable.
List Your API Keys
See all your active API keys. The full key value is never shown, only the last 8 characters for identification.
/api/auth/api-keysList all your active API keys
🔒 Requires Authentication{
"success": true,
"apiKeys": [
{
"_id": "65f999abc123...",
"name": "My Trading Bot",
"prefix": "ts_live_",
"lastChars": "8dF2aC9b",
"scopes": ["websocket:subscribe", "websocket:llm"],
"isActive": true,
"createdAt": "2026-02-02T10:00:00Z",
"lastUsedAt": "2026-02-02T15:30:00Z"
},
{
"_id": "65f888def456...",
"name": "Dashboard Monitor",
"prefix": "ts_live_",
"lastChars": "xY9zAb3c",
"scopes": ["websocket:subscribe"],
"isActive": true,
"createdAt": "2026-01-28T08:00:00Z",
"lastUsedAt": "2026-02-02T16:00:00Z"
}
]
}💡 What You See: The lastChars field shows the last 8 characters of your key. Use this to identify which key is which. The lastUsedAt field shows when the key was last used to authenticate.
Revoke an API Key
If an API key is compromised or no longer needed, revoke it immediately. Revoked keys cannot authenticate.
/api/auth/api-keys/:idRevoke an API key by its ID
🔒 Requires Authenticationcurl -X DELETE "http://localhost:7210/api/auth/api-keys/65f999abc123..." \
-H "Authorization: Bearer YOUR_JWT_TOKEN"{
"success": true,
"message": "API key revoked successfully"
}⚠️ Instant Effect: When you revoke a key, it stops working immediately. Any application using that key will be unable to authenticate. Make sure to update your applications with a new key before revoking the old one.
WebSocket API
Consume real-time data and LLM intelligence via WebSocket. Zero polling, instant updates.
Authentication with API Keys
For third party app integration, you can authenticate using an API key instead of a JWT token. This is perfect for automated systems, backend services, and IoT devices.
ws://localhost:7210/ws
# For production
wss://api.turboline.ai/ws💡 Note: You must first create an API key through the REST API (see API Keys section above). The key will start with ts_live_.
const ws = new WebSocket('ws://localhost:7210/ws');
ws.onopen = () => {
console.log('✓ Connected to TurboStream');
// Authenticate with API key
ws.send(JSON.stringify({
type: 'authenticate',
payload: {
apiKey: 'ts_live_a7Kx9mP2nQ5wR8yT4vB6cD1eF3gH0jL5_8dF2aC9b'
}
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'authenticated') {
console.log('✓ Authenticated with API key');
console.log('Auth type:', msg.payload.authType); // "apikey"
console.log('User ID:', msg.payload.userId);
// Now you can subscribe to feeds
ws.send(JSON.stringify({
type: 'subscribe-feed',
payload: {
userId: msg.payload.userId,
feedId: 'YOUR_FEED_ID'
}
}));
} else if (msg.type === 'auth_error') {
console.error('Authentication failed:', msg.payload.error);
}
};⚠️ Scope Restrictions: API keys are limited to the scopes they were created with. If your key doesn't have the required scope (e.g., trying to subscribe to LLM without websocket:llm), you'll receive an error: "insufficient permissions"
Subscribe to Topic Intelligence
For multi-topic feeds, subscribe to specific topics to receive their LLM analysis.
// Subscribe to BTC-USD intelligence
ws.send(JSON.stringify({
type: 'subscribe-topic',
payload: {
userId: 'user-123',
feedId: '65f789...',
topic: 'BTCUSDT'
}
}));{
"type": "subscription-success",
"payload": {
"feedId": "65f789...",
"topic": "BTCUSDT",
"type": "topic"
}
}Receive LLM Intelligence
{
"type": "llm-intelligence",
"payload": {
"feedId": "65f789...",
"topic": "BTCUSDT",
"analysis": "Bitcoin is showing strong bullish momentum with a 2.1% price increase over the last 10 minutes. Volume has increased by 35%, indicating strong buying pressure. Key resistance at $42,500 is being tested. The trend appears sustainable based on current market depth.",
"provider": "openai",
"timestamp": "2026-01-30T15:45:30.123Z"
}
}ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'llm-intelligence') {
const { topic, analysis, provider, timestamp } = msg.payload;
console.log('[' + topic + '] ' + analysis);
// Update your UI
updateDashboard(topic, analysis);
}
};Subscribe to Raw Feed Data
For non-topic feeds, subscribe to receive raw streaming data.
ws.send(JSON.stringify({
type: 'subscribe-feed',
payload: {
userId: 'user-123',
feedId: '65f456...'
}
}));{
"type": "feed-data",
"payload": {
"feedId": "65f456...",
"feedName": "Weather Updates",
"eventName": "weather",
"data": {
"temperature": 72.5,
"humidity": 65,
"conditions": "Partly Cloudy"
},
"timestamp": "2026-01-30T15:45:31.456Z"
}
}Message Types Reference
register-user→ ClientRegister your connection
subscribe-topic→ ClientSubscribe to topic intelligence
subscribe-feed→ ClientSubscribe to raw feed data
llm-intelligence← ServerReceive LLM analysis for a topic
feed-data← ServerReceive raw feed data
subscription-success← ServerConfirmation of subscription
⚠️ Important: Topic-routed feeds do NOT broadcast raw data. You'll only receive llm-intelligence messages for topics you've subscribed to.
Complete Examples
End-to-end examples putting it all together.
Cryptocurrency Price Intelligence - Complete Example
const WebSocket = require('ws');
// Connect to WebSocket
const ws = new WebSocket('ws://localhost:7210/ws');
ws.on('open', () => {
console.log('✓ Connected');
// Register
ws.send(JSON.stringify({
type: 'register-user',
payload: { userId: 'trader-123' }
}));
// Subscribe to BTC intelligence
ws.send(JSON.stringify({
type: 'subscribe-topic',
payload: {
userId: 'trader-123',
feedId: 'YOUR_FEED_ID',
topic: 'BTCUSDT'
}
}));
// Subscribe to ETH intelligence
ws.send(JSON.stringify({
type: 'subscribe-topic',
payload: {
userId: 'trader-123',
feedId: 'YOUR_FEED_ID',
topic: 'ETHUSDT'
}
}));
});
ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.type === 'llm-intelligence') {
console.log('[' + msg.payload.topic + ']');
console.log(msg.payload.analysis);
console.log('---');
}
});✅ Expected Output:
✓ Connected [BTCUSDT] Bitcoin is showing strong bullish momentum with a 2.1% price increase... --- [ETHUSDT] Ethereum is tracking Bitcoin's movement with a 1.8% gain. Volume indicates... --- [BTCUSDT] Continued upward pressure on Bitcoin. The $42,500 resistance level... ---
🎯 Need Help?
For support, reach out to [email protected]