OS Trading Engine
API Reference
WebSocket API
Connection

WebSocket Connection

Connect to the Nexgent WebSocket API to receive real-time position and price updates.


Overview

The WebSocket API provides real-time updates for:

  • Position changes - When positions are created, updated, or closed
  • Price updates - Live token price feeds for open positions
  • Connection status - Heartbeat/ping-pong for connection health

The WebSocket server runs on the same port as the HTTP API, using the /ws path.


Connection URL

ws://your-instance.com/ws?token=<jwt_token>&agentId=<agent_id>

Or with TLS:

wss://your-instance.com/ws?token=<jwt_token>&agentId=<agent_id>

Query Parameters

ParameterTypeRequiredDescription
tokenstringYesValid JWT access token
agentIdUUIDYesAgent ID to receive updates for

URL Construction

function getWebSocketUrl(apiUrl, token, agentId) {
  // Convert http:// to ws:// or https:// to wss://
  const wsUrl = apiUrl.replace(/^http/, 'ws');
  return `${wsUrl}/ws?token=${encodeURIComponent(token)}&agentId=${encodeURIComponent(agentId)}`;
}
 
// Example
const url = getWebSocketUrl(
  'https://your-instance.com',
  'eyJhbGciOiJIUzI1NiIs...',
  '550e8400-e29b-41d4-a716-446655440000'
);
// wss://your-instance.com/ws?token=eyJhbGc...&agentId=550e8400...

Authentication

WebSocket connections authenticate via JWT token passed in the URL query string.

Authentication Flow

1. Client obtains JWT access token (via /api/v1/auth/login)

2. Client connects to WebSocket with token in URL
   ws://host/ws?token=<jwt>&agentId=<id>

3. Server validates:
   - Token signature and expiration
   - Token type is 'access' (not refresh)
   - Agent belongs to the authenticated user

4. On success: Server sends 'connected' message
   On failure: Server closes connection with error code

Connection Errors

CodeReasonDescription
1008Missing authenticationNo token or agentId provided
1008Authentication failedInvalid or expired token
1008Agent not foundAgent doesn't exist or belongs to different user
1011Internal server errorServer-side error during connection

Connection Lifecycle

Opening Connection

const ws = new WebSocket(url);
 
ws.onopen = () => {
  console.log('WebSocket connection opened');
  // Wait for 'connected' message to confirm authentication
};

Connection Confirmed

After successful authentication, the server sends a connected message:

{
  "type": "connected",
  "data": {
    "agentId": "550e8400-e29b-41d4-a716-446655440000",
    "timestamp": "2025-01-20T10:30:00.000Z"
  }
}

Initial Data

Immediately after connection, the server sends an initial_data message with all current positions:

{
  "type": "initial_data",
  "data": {
    "positions": [...],
    "timestamp": "2025-01-20T10:30:00.000Z"
  }
}

Closing Connection

// Clean close
ws.close(1000, 'User disconnect');
 
// The server will also close connections if:
// - Token expires
// - No pong response to ping within 60 seconds
// - Server shutdown

Keep-Alive (Ping/Pong)

The server sends periodic ping messages every 30 seconds. Clients must respond with pong to maintain the connection.

Server Ping

{
  "type": "ping",
  "timestamp": "2025-01-20T10:30:00.000Z"
}

Client Pong Response

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  
  if (message.type === 'ping') {
    ws.send(JSON.stringify({
      type: 'pong',
      timestamp: new Date().toISOString()
    }));
  }
};

Connection Timeout

ConditionTimeout
No pong response60 seconds (2 ping cycles)
Connection considered staleConnection closed
⚠️

If your client doesn't respond to ping messages, the connection will be closed after ~60 seconds.


One Connection Per Agent

Each agent can have only one active WebSocket connection at a time.

If a new connection is established for an agent that already has a connection:

  1. The existing connection is closed with code 1000 and reason "New connection established"
  2. The new connection becomes active
// If user opens app in a new tab with same agent:
// - Old tab's connection: closed
// - New tab's connection: active

Reconnection Strategy

Implement automatic reconnection for production apps:

class WebSocketManager {
  constructor(url) {
    this.url = url;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
    this.reconnectInterval = 5000; // 5 seconds
  }
 
  connect() {
    this.ws = new WebSocket(this.url);
    
    this.ws.onclose = (event) => {
      // Don't reconnect on clean close
      if (event.code === 1000) return;
      
      // Exponential backoff
      if (this.reconnectAttempts < this.maxReconnectAttempts) {
        const delay = this.reconnectInterval * Math.pow(1.5, this.reconnectAttempts);
        console.log(`Reconnecting in ${delay}ms...`);
        
        setTimeout(() => {
          this.reconnectAttempts++;
          this.connect();
        }, delay);
      } else {
        console.error('Max reconnection attempts reached');
      }
    };
    
    this.ws.onopen = () => {
      this.reconnectAttempts = 0; // Reset on successful connection
    };
  }
 
  disconnect() {
    if (this.ws) {
      this.ws.close(1000, 'Manual disconnect');
    }
  }
}