Roxom.com

Account Updates

Copy page

Subscribe to authenticated WebSocket channels for real-time order, balance, and position updates.

Overview

Receive real-time updates for your account activity through authenticated WebSocket connections. After connecting with valid API credentials, subscribe to the private channels you need (orders, balance, positions).

Available private streams

Stream types overview

ChannelDescriptionAuto-EnabledAuthentication
ordersOrder status changes and fills❌ No (subscribe)Required
balanceAccount balance updates❌ No (subscribe)Required
positionsPosition changes and PnL❌ No (subscribe)Required
accountAccount-level notifications❌ No (subscribe)Required

Quick start

Authenticated connection setup

// Generate RSA signature for WebSocket connection
// Payload for WebSocket connection is always: "GET:/ws"
const signature = generateRSASignature(privateKey, 'GET:/ws');

const ws = new WebSocket('wss://ws.roxom.com/ws', [], {
  headers: {
    'X-API-Key': 'your-api-key',
    'X-API-Signature': signature
  }
});

ws.onopen = () => {
  ws.send(JSON.stringify({
    op: 'subscribe',
    args: [ { channel: 'orders' }, { channel: 'positions' }, { channel: 'balance' } ]
  }));
};

ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
  
  if (data.event === 'subscribe') return; // subscription ack
  if (data.data && data.data.type === 'order') handleOrderUpdate(data.data);
  if (data.data && data.data.type === 'position') handlePositionUpdate(data.data);
  if (data.data && data.data.type === 'balance') handleBalanceUpdate(data.data);
};

RSA signature generation

The WebSocket connection requires an RSA signature of the payload GET:/ws using your private key:

function generateRSASignature(privateKey, payload = 'GET:/ws') {
  const crypto = require('crypto');
  const sign = crypto.createSign('SHA256');
  sign.update(payload);
  return sign.sign(privateKey, 'base64');
}

// Example usage
const fs = require('fs');
const privateKey = fs.readFileSync('path/to/your/private-key.pem', 'utf8');
const signature = generateRSASignature(privateKey);

Python RSA signature generation

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
import base64

def generate_rsa_signature(private_key_path: str, payload: str = 'GET:/ws') -> str:
    # Load private key
    with open(private_key_path, 'rb') as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None
        )
    
    # Sign the payload
    signature = private_key.sign(
        payload.encode('utf-8'),
        padding.PKCS1v15(),
        hashes.SHA256()
    )
    
    # Return base64 encoded signature
    return base64.b64encode(signature).decode('utf-8')

# Example usage
signature = generate_rsa_signature('path/to/your/private-key.pem')

Go RSA signature generation

package main

import (
    "crypto"
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "io/ioutil"
)

func generateRSASignature(privateKeyPath string, payload string) (string, error) {
    // Default payload for WebSocket connection
    if payload == "" {
        payload = "GET:/ws"
    }
    
    // Load private key
    keyData, err := ioutil.ReadFile(privateKeyPath)
    if err != nil {
        return "", err
    }
    
    block, _ := pem.Decode(keyData)
    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        return "", err
    }
    
    // Hash the payload
    hash := sha256.Sum256([]byte(payload))
    
    // Sign the hash
    signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
    if err != nil {
        return "", err
    }
    
    // Return base64 encoded signature
    return base64.StdEncoding.EncodeToString(signature), nil
}

Message format

All account update messages follow a consistent structure:

{
  "type": "order|balance|position|account",
  "data": {
    "accountId": "01234567-89ab-7def-8123-456789abcdef",
    // Type-specific data fields
    "timestamp": 1640995200000000000
  }
}

Common use cases

Order Management Systems

Monitor order fills, cancellations, and rejections in real-time to maintain accurate order state and trigger appropriate business logic.

Risk Management

Track position changes and unrealized P&L to implement stop-loss mechanisms and position size limits.

Portfolio Monitoring

Real-time balance updates enable dynamic portfolio rebalancing and cash management strategies.

Algorithmic Trading

Use order and position updates to trigger next steps in multi-leg trading strategies and complex order workflows.

Error handling

Authentication Failed

Cause: Invalid API credentials or signature

Solution:

  • Verify API key is correct and active
  • Check RSA signature generation using correct payload ("GET:/ws")
  • Ensure private key matches the public key associated with your API key
Connection Timeout

Cause: Network or server connectivity issues

Solution:

  • Implement reconnection logic with exponential backoff
  • Monitor connection health with heartbeat
  • Handle reconnection state recovery
Rate Limiting

Cause: Too many connection attempts

Solution:

  • Use single connection per application
  • Implement connection pooling
  • Add delays between reconnection attempts

Best practices

State Management
  • Maintain local copies of order and position state
  • Handle message ordering and potential duplicates
  • Implement proper state reconciliation on reconnection
  • Use message timestamps for event sequencing
Performance Optimization
  • Process updates asynchronously to avoid blocking
  • Batch UI updates for high-frequency streams
  • Implement efficient data structures for tracking
  • Monitor memory usage for long-running connections
Reliability
  • Implement comprehensive error handling
  • Log all account events for audit trails
  • Use heartbeat monitoring for connection health
  • Plan for graceful degradation during outages

Authentication requirements

To access private account streams, you need:

  1. Valid API Credentials: Active API key with appropriate permissions
  2. Proper Signature: RSA signature of the payload "GET:/ws" using your private key
  3. Correct Headers: Both X-API-Key and X-API-Signature headers included

See the Authentication Guide for detailed setup instructions.

Next steps

Last modified on