# WebSocket API

Reservoir Mastery Exclusive

WebSocket streaming is available exclusively to Reservoir Mastery subscribers ($129/month). Upgrade your plan (opens new window) to access real-time streaming.

# Overview

The OilPriceAPI WebSocket service provides real-time price updates using ActionCable, eliminating the need for constant polling and reducing latency to milliseconds.

# Benefits

  • Instant Updates: Receive price changes as they happen
  • Reduced API Calls: No need to poll the REST API
  • Lower Latency: Sub-second delivery times
  • Efficient: Single persistent connection
  • Reliable: Automatic reconnection handling

# Getting Started

# Connection URL

wss://api.oilpriceapi.com/cable
1

# Authentication

Include your API token in the connection parameters:

const cable = ActionCable.createConsumer('wss://api.oilpriceapi.com/cable', {
  headers: {
    'Authorization': 'Token YOUR_API_KEY'
  }
});
1
2
3
4
5

# JavaScript Implementation

// Install ActionCable
// npm install @rails/actioncable

import { createConsumer } from '@rails/actioncable';

// Create connection
const cable = createConsumer('wss://api.oilpriceapi.com/cable');

// Subscribe to energy prices channel
const subscription = cable.subscriptions.create('EnergyPricesChannel', {
  connected() {
    console.log('Connected to WebSocket');
  },

  disconnected() {
    console.log('Disconnected from WebSocket');
  },

  received(data) {
    console.log('Received:', data);
    
    // Handle different message types
    switch(data.type) {
      case 'price_update':
        handlePriceUpdate(data.data);
        break;
      case 'drilling_intelligence_update':
        handleDrillingUpdate(data.data);
        break;
      case 'alert':
        handleAlert(data.data);
        break;
    }
  }
});

// Handle price updates
function handlePriceUpdate(priceData) {
  console.log(`${priceData.code}: $${priceData.price}`);
  // Update your UI
}

// Unsubscribe when done
// subscription.unsubscribe();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# Using Native WebSocket

class OilPriceWebSocket {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.ws = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
  }

  connect() {
    this.ws = new WebSocket('wss://api.oilpriceapi.com/cable');
    
    this.ws.onopen = () => {
      console.log('WebSocket connected');
      this.reconnectAttempts = 0;
      
      // Send subscription command
      this.ws.send(JSON.stringify({
        command: 'subscribe',
        identifier: JSON.stringify({
          channel: 'EnergyPricesChannel',
          api_key: this.apiKey
        })
      }));
    };

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      
      if (message.type === 'ping') return;
      
      if (message.message) {
        this.handleMessage(message.message);
      }
    };

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

    this.ws.onclose = () => {
      console.log('WebSocket disconnected');
      this.reconnect();
    };
  }

  handleMessage(data) {
    console.log('Price update:', data);
    // Process the price update
  }

  reconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      console.log(`Reconnecting... (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
      setTimeout(() => this.connect(), 5000);
    }
  }

  disconnect() {
    if (this.ws) {
      this.ws.close();
    }
  }
}

// Usage
const ws = new OilPriceWebSocket('YOUR_API_KEY');
ws.connect();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

# Python Implementation

import websocket
import json
import threading

class OilPriceWebSocket:
    def __init__(self, api_key):
        self.api_key = api_key
        self.ws = None
        
    def on_message(self, ws, message):
        data = json.loads(message)
        
        if data.get('type') == 'ping':
            return
            
        if 'message' in data:
            self.handle_price_update(data['message'])
    
    def on_error(self, ws, error):
        print(f"WebSocket error: {error}")
    
    def on_close(self, ws):
        print("WebSocket connection closed")
    
    def on_open(self, ws):
        print("WebSocket connected")
        
        # Subscribe to channel
        subscribe_message = {
            'command': 'subscribe',
            'identifier': json.dumps({
                'channel': 'EnergyPricesChannel',
                'api_key': self.api_key
            })
        }
        ws.send(json.dumps(subscribe_message))
    
    def handle_price_update(self, data):
        if data.get('type') == 'price_update':
            price_data = data['data']
            print(f"{price_data['code']}: ${price_data['price']}")
    
    def connect(self):
        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp(
            "wss://api.oilpriceapi.com/cable",
            on_message=self.on_message,
            on_error=self.on_error,
            on_close=self.on_close,
            on_open=self.on_open
        )
        
        # Run in a separate thread
        wst = threading.Thread(target=self.ws.run_forever)
        wst.daemon = True
        wst.start()

# Usage
client = OilPriceWebSocket('YOUR_API_KEY')
client.connect()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

# Message Types

# Price Update

Sent whenever a commodity price changes:

{
  "type": "price_update",
  "data": {
    "code": "WTI_USD",
    "name": "West Texas Intermediate",
    "price": 75.43,
    "formatted": "$75.43",
    "currency": "USD",
    "unit": "barrel",
    "change": 0.22,
    "change_percent": 0.29,
    "previous_price": 75.21,
    "created_at": "2025-07-18T14:30:00.000Z"
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Drilling Intelligence Update

Sent when new drilling intelligence data is available:

{
  "type": "drilling_intelligence_update",
  "data": {
    "code": "US_RIG_COUNT",
    "name": "US Rig Count",
    "value": 622,
    "previous_value": 619,
    "change": 3,
    "change_percent": 0.48,
    "region": "United States",
    "source": "baker_hughes",
    "created_at": "2025-07-18T18:00:00.000Z"
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Alert Notification

Sent when a configured alert is triggered:

{
  "type": "alert",
  "data": {
    "alert_type": "price_threshold",
    "commodity": "BRENT_CRUDE_USD",
    "condition": "above",
    "threshold": 80.00,
    "current_price": 80.15,
    "message": "Brent Crude has exceeded $80.00",
    "triggered_at": "2025-07-18T15:45:00.000Z"
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

# Connection Status

System messages about connection state:

{
  "type": "welcome",
  "message": "Successfully connected to OilPriceAPI WebSocket"
}
1
2
3
4

# Subscribing to Specific Commodities

You can filter which commodities you receive updates for:

const subscription = cable.subscriptions.create({
  channel: 'EnergyPricesChannel',
  commodities: ['WTI_USD', 'BRENT_CRUDE_USD', 'NATURAL_GAS_USD']
}, {
  received(data) {
    // Only receive updates for specified commodities
  }
});
1
2
3
4
5
6
7
8

# Error Handling

# Connection Errors

subscription.rejected = () => {
  console.error('Subscription rejected. Check your API key and plan.');
};
1
2
3

# Automatic Reconnection

ActionCable handles reconnection automatically. For custom implementations:

let reconnectInterval = 1000; // Start with 1 second

function connect() {
  const ws = new WebSocket('wss://api.oilpriceapi.com/cable');
  
  ws.onclose = () => {
    setTimeout(() => {
      reconnectInterval = Math.min(reconnectInterval * 2, 30000); // Max 30 seconds
      connect();
    }, reconnectInterval);
  };
  
  ws.onopen = () => {
    reconnectInterval = 1000; // Reset on successful connection
  };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Best Practices

# 1. Handle Disconnections Gracefully

Always implement reconnection logic and inform users of connection status.

# 2. Process Messages Efficiently

// Use a queue for high-frequency updates
const priceQueue = [];

subscription.received = (data) => {
  priceQueue.push(data);
};

// Process queue periodically
setInterval(() => {
  if (priceQueue.length > 0) {
    const updates = priceQueue.splice(0, priceQueue.length);
    updateUI(updates);
  }
}, 100); // Update UI every 100ms
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3. Implement Heartbeat

Keep the connection alive during quiet periods:

setInterval(() => {
  if (subscription) {
    subscription.perform('ping');
  }
}, 30000); // Ping every 30 seconds
1
2
3
4
5

# 4. Monitor Connection Health

let lastMessageTime = Date.now();

subscription.received = (data) => {
  lastMessageTime = Date.now();
  // Process message
};

// Check connection health
setInterval(() => {
  if (Date.now() - lastMessageTime > 60000) {
    console.warn('No messages for 60 seconds, connection may be stale');
    // Reconnect if needed
  }
}, 10000);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Rate Limits

WebSocket connections are limited by plan:

  • Reservoir Mastery: Up to 5 concurrent connections per API key
  • Message Rate: No limit on received messages
  • Send Rate: 10 messages per second per connection

# Troubleshooting

# Connection Rejected

  • Verify API key is valid
  • Confirm Reservoir Mastery subscription is active
  • Check if maximum connections reached

# No Messages Received

  • Ensure subscription command was sent
  • Verify commodities are actively trading
  • Check browser console for errors

# Frequent Disconnections

  • Check network stability
  • Verify firewall allows WebSocket connections
  • Consider implementing exponential backoff

# Support

For WebSocket-specific support:

  • Technical docs: https://docs.oilpriceapi.com/websocket/
  • Email: [email protected]
  • Slack: Available for Reservoir Mastery subscribers

Upgrade to Reservoir Mastery (opens new window) to access WebSocket streaming.