# 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
# Authentication
Include your API token in the connection parameters:
const cable = ActionCable.createConsumer('wss://api.oilpriceapi.com/cable', {
headers: {
'Authorization': 'Token YOUR_API_KEY'
}
});
2
3
4
5
# JavaScript Implementation
# Using ActionCable (Recommended)
// 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();
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();
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()
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"
}
}
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"
}
}
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"
}
}
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"
}
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
}
});
2
3
4
5
6
7
8
# Error Handling
# Connection Errors
subscription.rejected = () => {
console.error('Subscription rejected. Check your API key and plan.');
};
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
};
}
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
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
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);
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.