OilPriceAPI Documentation
GitHub
GitHub
  • Getting Started

    • Quick Start Guide - OilPriceAPI
    • Making Requests
    • Handling Responses

Handling Responses

Learn how to parse and work with API responses from OilPriceAPI.

Response Format

All API responses follow a consistent JSON structure:

Success Response

{
  "status": "success",
  "data": {
    // Response data here
  },
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2025-01-10T15:30:00.000Z"
  }
}

Error Response

{
  "status": "fail",
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {}
  }
}

Response Status Codes

Status CodeDescription
200 OKRequest successful
400 Bad RequestInvalid parameters or request format
401 UnauthorizedInvalid or missing API key
404 Not FoundResource not found
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorServer error (rare)

Parsing Price Data

Single Commodity Response

// Response from /v1/prices/latest?by_code=WTI_USD
{
  "status": "success",
  "data": {
    "prices": {
      "WTI_USD": {
        "value": 78.45,
        "currency": "USD",
        "unit": "barrel",
        "timestamp": "2025-01-10T15:30:00.000Z",
        "change_24h": 1.23,
        "change_percentage_24h": 1.59
      }
    }
  }
}

// Parsing in JavaScript
const response = await fetch(url, options);
const result = await response.json();

if (result.status === 'success') {
  const wtiPrice = result.data.prices.WTI_USD;
  console.log(`WTI: $${wtiPrice.value} per ${wtiPrice.unit}`);
  console.log(`24h change: ${wtiPrice.change_percentage_24h}%`);
}

Multiple Commodities Response

# Response from /v1/prices/latest?by_code=WTI_USD,BRENT_CRUDE_USD
response = {
  "status": "success",
  "data": {
    "prices": {
      "WTI_USD": {
        "value": 78.45,
        "currency": "USD",
        "unit": "barrel",
        "timestamp": "2025-01-10T15:30:00.000Z"
      },
      "BRENT_CRUDE_USD": {
        "value": 82.30,
        "currency": "USD",
        "unit": "barrel",
        "timestamp": "2025-01-10T15:30:00.000Z"
      }
    }
  }
}

# Parsing in Python
import requests

response = requests.get(url, headers=headers)
data = response.json()

if data['status'] == 'success':
    for commodity_code, price_data in data['data']['prices'].items():
        print(f"{commodity_code}: ${price_data['value']}")

Working with Historical Data

Historical Response Structure

{
  "status": "success",
  "data": {
    "commodity": "WTI_USD",
    "currency": "USD",
    "unit": "barrel",
    "prices": [
      {
        "date": "2025-01-10",
        "value": 78.45,
        "open": 77.20,
        "high": 79.10,
        "low": 76.90,
        "close": 78.45,
        "volume": 425000
      },
      {
        "date": "2025-01-09",
        "value": 77.22,
        "open": 76.50,
        "high": 77.80,
        "low": 76.10,
        "close": 77.22,
        "volume": 398000
      }
    ],
    "meta": {
      "total_records": 10,
      "start_date": "2025-01-01",
      "end_date": "2025-01-10"
    }
  }
}

Processing Historical Data

// JavaScript - Calculate average price
function calculateAverage(historicalData) {
  const prices = historicalData.data.prices;
  const sum = prices.reduce((acc, day) => acc + day.value, 0);
  return sum / prices.length;
}

// Find price trends
function analyzeTrend(historicalData) {
  const prices = historicalData.data.prices;
  const firstPrice = prices[0].value;
  const lastPrice = prices[prices.length - 1].value;
  const change = lastPrice - firstPrice;
  const changePercent = (change / firstPrice) * 100;
  
  return {
    trend: change > 0 ? 'upward' : 'downward',
    changeAmount: change,
    changePercent: changePercent.toFixed(2)
  };
}
# Python - Create DataFrame for analysis
import pandas as pd
import json

def process_historical_data(response_data):
    """Convert API response to pandas DataFrame"""
    prices = response_data['data']['prices']
    df = pd.DataFrame(prices)
    df['date'] = pd.to_datetime(df['date'])
    df.set_index('date', inplace=True)
    
    # Calculate moving averages
    df['ma_5'] = df['value'].rolling(window=5).mean()
    df['ma_10'] = df['value'].rolling(window=10).mean()
    
    return df

# Usage
response = requests.get(url, headers=headers)
data = response.json()
df = process_historical_data(data)
print(df.describe())

Error Handling

Common Error Codes

const ERROR_HANDLERS = {
  'INVALID_API_KEY': () => {
    console.error('Check your API key configuration');
    // Redirect to settings or show configuration help
  },
  
  'RATE_LIMIT_EXCEEDED': (error) => {
    console.error(`Rate limit hit. Resets at: ${new Date(error.reset_at)}`);
    // Implement backoff or queue requests
  },
  
  'COMMODITY_NOT_FOUND': (error) => {
    console.error(`Invalid commodity code: ${error.details.code}`);
    // Show list of valid codes
  },
  
  'INVALID_DATE_RANGE': (error) => {
    console.error('Date range issue:', error.message);
    // Validate date inputs
  }
};

async function makeAPICall(url, options) {
  try {
    const response = await fetch(url, options);
    const data = await response.json();
    
    if (data.status === 'fail') {
      const handler = ERROR_HANDLERS[data.error.code];
      if (handler) {
        handler(data.error);
      } else {
        console.error('API Error:', data.error.message);
      }
      return null;
    }
    
    return data;
  } catch (err) {
    console.error('Network error:', err);
    return null;
  }
}

Retry Logic

import time
from typing import Optional, Dict, Any

class APIClient:
    def __init__(self, api_key: str, max_retries: int = 3):
        self.api_key = api_key
        self.max_retries = max_retries
    
    def make_request(self, endpoint: str, params: Dict[str, Any]) -> Optional[Dict]:
        """Make API request with automatic retry on failure"""
        
        for attempt in range(self.max_retries):
            try:
                response = requests.get(
                    f"https://api.oilpriceapi.com/v1{endpoint}",
                    params=params,
                    headers={'Authorization': f'Token {self.api_key}'},
                    timeout=10
                )
                
                if response.status_code == 429:
                    # Rate limited - wait before retry
                    retry_after = int(response.headers.get('Retry-After', 60))
                    if attempt < self.max_retries - 1:
                        time.sleep(retry_after)
                        continue
                
                response.raise_for_status()
                return response.json()
                
            except requests.exceptions.RequestException as e:
                if attempt == self.max_retries - 1:
                    print(f"Failed after {self.max_retries} attempts: {e}")
                    return None
                    
                # Exponential backoff
                wait_time = 2 ** attempt
                time.sleep(wait_time)
        
        return None

Response Headers

Important headers included in responses:

X-RateLimit-Limit: 10000           # Monthly limit
X-RateLimit-Remaining: 9876        # Requests remaining
X-RateLimit-Reset: 1735689600      # Unix timestamp when limit resets
X-Request-Id: req_abc123def        # Unique request ID for support
X-Response-Time: 45                # Response time in milliseconds

Monitoring Usage

class UsageMonitor {
  constructor() {
    this.usage = {
      limit: null,
      remaining: null,
      resetAt: null
    };
  }
  
  updateFromHeaders(headers) {
    this.usage.limit = parseInt(headers.get('x-ratelimit-limit'));
    this.usage.remaining = parseInt(headers.get('x-ratelimit-remaining'));
    this.usage.resetAt = new Date(parseInt(headers.get('x-ratelimit-reset')) * 1000);
    
    this.checkUsage();
  }
  
  checkUsage() {
    const percentUsed = ((this.usage.limit - this.usage.remaining) / this.usage.limit) * 100;
    
    if (percentUsed > 90) {
      console.warn(`API usage at ${percentUsed.toFixed(1)}%`);
      this.sendUsageAlert();
    }
  }
  
  getDaysUntilReset() {
    const now = new Date();
    const msUntilReset = this.usage.resetAt - now;
    return Math.ceil(msUntilReset / (1000 * 60 * 60 * 24));
  }
}

Data Transformation

Format for Display

function formatPriceDisplay(priceData) {
  const formatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: priceData.currency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });
  
  return {
    formatted: formatter.format(priceData.value),
    unit: priceData.unit,
    change: priceData.change_24h > 0 ? '↑' : '↓',
    changeColor: priceData.change_24h > 0 ? 'green' : 'red',
    changeText: `${priceData.change_24h > 0 ? '+' : ''}${priceData.change_percentage_24h}%`
  };
}

// Usage
const display = formatPriceDisplay(result.data.prices.WTI_USD);
console.log(`${display.formatted}/${display.unit} ${display.changeText}`);
// Output: $78.45/barrel +1.59%

Export to CSV

import csv
from datetime import datetime

def export_to_csv(historical_data, filename):
    """Export historical price data to CSV"""
    
    prices = historical_data['data']['prices']
    commodity = historical_data['data']['commodity']
    
    with open(filename, 'w', newline='') as csvfile:
        fieldnames = ['date', 'open', 'high', 'low', 'close', 'volume']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        
        # Write header with commodity info
        csvfile.write(f"# {commodity} Historical Prices\n")
        csvfile.write(f"# Generated: {datetime.now().isoformat()}\n")
        
        writer.writeheader()
        for price in prices:
            writer.writerow({
                'date': price['date'],
                'open': price.get('open', price['value']),
                'high': price.get('high', price['value']),
                'low': price.get('low', price['value']),
                'close': price.get('close', price['value']),
                'volume': price.get('volume', 0)
            })
    
    print(f"Exported {len(prices)} records to {filename}")

WebSocket Responses (Premium)

For real-time updates via WebSocket:

// WebSocket message format
{
  "type": "price_update",
  "data": {
    "commodity": "WTI_USD",
    "price": 78.52,
    "previous": 78.45,
    "change": 0.07,
    "timestamp": "2025-01-10T15:31:00.000Z"
  }
}

// Handling WebSocket messages
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  
  if (message.type === 'price_update') {
    updatePriceDisplay(message.data);
    
    // Check for significant changes
    if (Math.abs(message.data.change) > 1.0) {
      notifySignificantChange(message.data);
    }
  }
};

Next Steps

  • Explore the API Reference for detailed endpoint documentation
  • Learn about Marine Fuels specialty endpoints
  • Set up WebSocket connections for real-time updates (Premium)
Prev
Making Requests