WebSocket API

Real-time streaming forex data via WebSocket connections.

Requires Individual or Business Plan

WebSocket streaming is available on paid plans only.

WebSocket URL
wss://stream.pulse-markets.com/v1/ws

Connection

Connect to the WebSocket server and authenticate using your API credentials.

JavaScript Example

javascript
const ws = new WebSocket('wss://stream.pulse-markets.com/v1/ws');

ws.onopen = () => {
  // Authenticate first
  ws.send(JSON.stringify({
    action: 'auth',
    api_key: 'fx_your_api_key',
    api_secret: 'fxs_your_secret'
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
};

ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

ws.onclose = () => {
  console.log('Connection closed');
};

Authentication

Send an authentication message immediately after connecting:

json
{
  "action": "auth",
  "api_key": "fx_your_api_key",
  "api_secret": "fxs_your_secret"
}

Auth Success Response

json
{
  "event": "authenticated",
  "message": "Successfully authenticated",
  "user_id": 12345,
  "plan": "individual",
  "max_subscriptions": 10
}

Subscribing to Symbols

After authentication, subscribe to receive real-time quotes:

Subscribe Request

json
{
  "action": "subscribe",
  "symbols": ["EUR/USD", "GBP/USD", "USD/JPY"]
}

Subscribe Response

json
{
  "event": "subscribed",
  "symbols": ["EUR/USD", "GBP/USD", "USD/JPY"],
  "count": 3
}

Receiving Quotes

Once subscribed, you'll receive real-time tick data:

json
{
  "event": "quote",
  "data": {
    "symbol": "EUR/USD",
    "bid": 1.08542,
    "ask": 1.08545,
    "spread": 0.00003,
    "timestamp": "2025-01-15T14:30:00.125Z"
  }
}

Unsubscribing

json
{
  "action": "unsubscribe",
  "symbols": ["EUR/USD"]
}

Heartbeat / Ping

Send periodic pings to keep the connection alive:

json
// Client sends:
{ "action": "ping" }

// Server responds:
{ "event": "pong", "timestamp": "2025-01-15T14:30:00Z" }

Complete Example

javascript
class ForexWebSocket {
  constructor(apiKey, apiSecret) {
    this.apiKey = apiKey;
    this.apiSecret = apiSecret;
    this.ws = null;
    this.authenticated = false;
    this.reconnectAttempts = 0;
  }

  connect() {
    this.ws = new WebSocket('wss://stream.pulse-markets.com/v1/ws');

    this.ws.onopen = () => {
      console.log('Connected, authenticating...');
      this.authenticate();
    };

    this.ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      this.handleMessage(data);
    };

    this.ws.onclose = () => {
      this.authenticated = false;
      this.scheduleReconnect();
    };

    // Send ping every 30 seconds
    this.pingInterval = setInterval(() => {
      if (this.ws?.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify({ action: 'ping' }));
      }
    }, 30000);
  }

  authenticate() {
    this.ws.send(JSON.stringify({
      action: 'auth',
      api_key: this.apiKey,
      api_secret: this.apiSecret
    }));
  }

  subscribe(symbols) {
    if (!this.authenticated) {
      console.error('Not authenticated');
      return;
    }
    this.ws.send(JSON.stringify({
      action: 'subscribe',
      symbols: symbols
    }));
  }

  handleMessage(data) {
    switch (data.event) {
      case 'authenticated':
        this.authenticated = true;
        this.reconnectAttempts = 0;
        console.log('Authenticated successfully');
        break;
      case 'quote':
        this.onQuote(data.data);
        break;
      case 'error':
        console.error('Error:', data.message);
        break;
    }
  }

  onQuote(quote) {
    // Override this method to handle quotes
    console.log(`${quote.symbol}: ${quote.bid} / ${quote.ask}`);
  }

  scheduleReconnect() {
    const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
    this.reconnectAttempts++;
    setTimeout(() => this.connect(), delay);
  }

  disconnect() {
    clearInterval(this.pingInterval);
    this.ws?.close();
  }
}

// Usage
const client = new ForexWebSocket('fx_your_key', 'fxs_your_secret');
client.onQuote = (quote) => {
  document.getElementById('price').textContent = quote.bid;
};
client.connect();

// After authentication
setTimeout(() => {
  client.subscribe(['EUR/USD', 'GBP/USD']);
}, 1000);

Connection Limits

Plan Connections Subscriptions
Free Not available -
Individual 2 concurrent 10 symbols
Business 10 concurrent 50 symbols