OilPriceAPI Documentation
GitHub
GitHub
  • Guides

    • Authentication
    • Testing & Development
    • Error Codes Reference
    • Webhook Signature Verification
    • Production Deployment Checklist
    • Service Level Agreement (SLA)
    • Rate Limiting & Response Headers
    • Data Quality and Validation
    • Troubleshooting Guide
    • Incident Response Guide

Error Codes Reference

Comprehensive guide to all OilPriceAPI error codes, their meanings, and how to handle them.

Error Response Format

All API errors follow this consistent structure:

{
  "status": "error",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please retry after 60 seconds.",
    "details": {
      "limit": 100,
      "remaining": 0,
      "reset_at": "2025-01-23T15:30:00Z",
      "reset_after": 60
    }
  },
  "meta": {
    "request_id": "req_abc123def456",
    "timestamp": "2025-01-23T15:29:00Z"
  }
}

HTTP Status Codes

StatusMeaningCommon Causes
200SuccessRequest processed successfully
400Bad RequestInvalid parameters or malformed request
401UnauthorizedMissing or invalid API key
403ForbiddenValid key but insufficient permissions
404Not FoundEndpoint or resource doesn't exist
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-side issue
502Bad GatewayUpstream service unavailable
503Service UnavailableTemporary maintenance or overload

Error Codes by Category

Authentication Errors (401)

MISSING_API_KEY

Message: "API key is required. Include it in the Authorization header."

{
  "code": "MISSING_API_KEY",
  "message": "API key is required. Include it in the Authorization header."
}

How to fix:

curl "https://api.oilpriceapi.com/v1/prices/latest" \
  -H "Authorization: Token YOUR_API_KEY"  # Add this header

INVALID_API_KEY

Message: "The provided API key is invalid or has been revoked."

{
  "code": "INVALID_API_KEY",
  "message": "The provided API key is invalid or has been revoked."
}

How to fix:

  • Verify key in your dashboard
  • Check for typos or extra spaces
  • Ensure key hasn't been regenerated
  • Use correct prefix (opa_live_ or opa_test_)

EXPIRED_API_KEY

Message: "This API key has expired. Please generate a new one."

{
  "code": "EXPIRED_API_KEY",
  "message": "This API key has expired. Please generate a new one."
}

How to fix:

  • Log into dashboard
  • Generate new API key
  • Update your application configuration

Authorization Errors (403)

INSUFFICIENT_PLAN

Message: "Your current plan doesn't include access to this endpoint."

{
  "code": "INSUFFICIENT_PLAN",
  "message": "Your current plan doesn't include access to this endpoint.",
  "details": {
    "current_plan": "hobby",
    "required_plan": "professional",
    "upgrade_url": "https://oilpriceapi.com/pricing"
  }
}

How to fix:

  • Check endpoint requirements in documentation
  • Upgrade your plan if needed
  • Use alternative endpoints available in your tier

QUOTA_EXCEEDED

Message: "Monthly request quota exceeded."

{
  "code": "QUOTA_EXCEEDED",
  "message": "Monthly request quota exceeded.",
  "details": {
    "quota": 10000,
    "used": 10000,
    "reset_date": "2025-02-01T00:00:00Z"
  }
}

How to fix:

  • Wait for monthly reset
  • Upgrade to higher tier
  • Optimize API usage (caching, batching)

IP_NOT_WHITELISTED

Message: "Request from this IP address is not allowed."

{
  "code": "IP_NOT_WHITELISTED",
  "message": "Request from this IP address is not allowed.",
  "details": {
    "your_ip": "192.168.1.1",
    "whitelisted_ips": ["10.0.0.1", "10.0.0.2"]
  }
}

How to fix:

  • Add IP to whitelist in dashboard
  • Use API from approved locations
  • Consider VPN if working remotely

Validation Errors (400)

INVALID_COMMODITY

Message: "Invalid commodity code provided."

{
  "code": "INVALID_COMMODITY",
  "message": "Invalid commodity code provided.",
  "details": {
    "provided": "INVALID_CODE",
    "valid_codes": ["WTI_USD", "BRENT_CRUDE_USD", "NATURAL_GAS_USD"],
    "see_all": "https://api.oilpriceapi.com/v1/commodities"
  }
}

How to fix:

# Use valid commodity codes
valid_codes = ['WTI_USD', 'BRENT_CRUDE_USD', 'NATURAL_GAS_USD']
response = requests.get(
    f'https://api.oilpriceapi.com/v1/prices/latest?by_code={valid_codes[0]}'
)

INVALID_DATE_RANGE

Message: "Invalid date range. Start date must be before end date."

{
  "code": "INVALID_DATE_RANGE",
  "message": "Invalid date range. Start date must be before end date.",
  "details": {
    "start": "2025-02-01",
    "end": "2025-01-01",
    "max_range_days": 365
  }
}

How to fix:

// Ensure proper date ordering
const start = '2025-01-01';
const end = '2025-02-01';
const url = `https://api.oilpriceapi.com/v1/prices?start=${start}&end=${end}`;

INVALID_PARAMETER

Message: "Invalid parameter value."

{
  "code": "INVALID_PARAMETER",
  "message": "Invalid parameter value.",
  "details": {
    "parameter": "interval",
    "provided": "2h",
    "valid_values": ["raw", "1h", "hourly", "1d", "daily", "1w", "weekly", "1m", "monthly"]
  }
}

How to fix:

  • Use only documented parameter values
  • Check spelling and case sensitivity
  • Remove unsupported parameters

MISSING_REQUIRED_PARAMETER

Message: "Required parameter is missing."

{
  "code": "MISSING_REQUIRED_PARAMETER",
  "message": "Required parameter is missing.",
  "details": {
    "parameter": "by_code",
    "description": "Commodity code is required for this endpoint"
  }
}

How to fix:

# Add required parameter
curl "https://api.oilpriceapi.com/v1/prices/latest?by_code=WTI_USD"
#                                                    ^^^^^^^^^^^^^^^^ Add this

Rate Limiting Errors (429)

RATE_LIMIT_EXCEEDED

Message: "Rate limit exceeded."

{
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded. Please retry after 60 seconds.",
  "details": {
    "limit": 60,
    "window": "1 minute",
    "remaining": 0,
    "reset_at": "2025-01-23T15:30:00Z",
    "reset_after": 45
  }
}

How to fix:

import time
import requests

def make_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)

        if response.status_code == 429:
            reset_after = int(response.headers.get('X-RateLimit-Reset-After', 60))
            print(f"Rate limited. Waiting {reset_after} seconds...")
            time.sleep(reset_after)
            continue

        return response

    raise Exception("Max retries exceeded")

Resource Errors (404)

ENDPOINT_NOT_FOUND

Message: "The requested endpoint does not exist."

{
  "code": "ENDPOINT_NOT_FOUND",
  "message": "The requested endpoint does not exist.",
  "details": {
    "requested": "/v1/prices/invalid",
    "available": ["/v1/prices/latest", "/v1/prices/past_day", "/v1/prices/past_week"]
  }
}

How to fix:

  • Check documentation for correct endpoint paths
  • Verify API version (v1)
  • Remove trailing slashes

COMMODITY_NOT_FOUND

Message: "The requested commodity does not exist."

{
  "code": "COMMODITY_NOT_FOUND",
  "message": "The requested commodity does not exist.",
  "details": {
    "requested": "UNKNOWN_USD",
    "suggestion": "Did you mean WTI_USD?"
  }
}

Server Errors (500+)

INTERNAL_ERROR

Message: "An internal server error occurred."

{
  "code": "INTERNAL_ERROR",
  "message": "An internal server error occurred. Please try again later.",
  "details": {
    "request_id": "req_abc123",
    "support_email": "[email protected]"
  }
}

How to fix:

  • Retry with exponential backoff
  • Report persistent issues with request_id
  • Check status page for known issues

DATA_SOURCE_ERROR

Message: "Unable to fetch data from upstream source."

{
  "code": "DATA_SOURCE_ERROR",
  "message": "Unable to fetch data from upstream source.",
  "details": {
    "source": "primary_feed",
    "fallback_available": true,
    "retry_after": 30
  }
}

How to fix:

  • Retry after suggested time
  • System will use fallback sources automatically
  • Monitor status page for updates

SERVICE_UNAVAILABLE

Message: "Service temporarily unavailable."

{
  "code": "SERVICE_UNAVAILABLE",
  "message": "Service temporarily unavailable for maintenance.",
  "details": {
    "maintenance_window": "2025-01-23T02:00:00Z to 2025-01-23T02:30:00Z",
    "status_page": "https://status.oilpriceapi.com"
  }
}

Error Handling Best Practices

1. Implement Retry Logic

async function apiRequest(url, options, maxRetries = 3) {
  let lastError;

  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, options);

      if (response.ok) {
        return await response.json();
      }

      const error = await response.json();

      // Don't retry client errors
      if (response.status >= 400 && response.status < 500) {
        if (response.status !== 429) {  // Except rate limits
          throw new Error(error.error.message);
        }
      }

      // Wait before retry
      const retryAfter = response.headers.get('Retry-After') || (i + 1) * 1000;
      await new Promise(resolve => setTimeout(resolve, retryAfter));

      lastError = error;
    } catch (err) {
      lastError = err;
      // Network error - always retry
      await new Promise(resolve => setTimeout(resolve, (i + 1) * 1000));
    }
  }

  throw lastError;
}

2. Parse Error Details

def handle_api_error(response):
    """Extract and handle API errors properly"""
    if response.status_code == 200:
        return response.json()

    try:
        error_data = response.json()
        error_code = error_data.get('error', {}).get('code')
        error_message = error_data.get('error', {}).get('message')
        error_details = error_data.get('error', {}).get('details', {})

        if error_code == 'RATE_LIMIT_EXCEEDED':
            # Wait and retry
            reset_after = error_details.get('reset_after', 60)
            time.sleep(reset_after)
            return None  # Signal retry

        elif error_code == 'INSUFFICIENT_PLAN':
            # Log and notify about plan upgrade
            upgrade_url = error_details.get('upgrade_url')
            logging.error(f"Plan upgrade needed: {upgrade_url}")

        elif error_code == 'INVALID_COMMODITY':
            # Use fallback commodity
            valid_codes = error_details.get('valid_codes', [])
            if valid_codes:
                return use_fallback_commodity(valid_codes[0])

    except json.JSONDecodeError:
        # Non-JSON error response
        logging.error(f"API error {response.status_code}: {response.text}")

    raise APIError(response.status_code, error_code, error_message)

3. Log Errors for Monitoring

function logApiError(error, context) {
  const errorLog = {
    timestamp: new Date().toISOString(),
    request_id: error.meta?.request_id,
    error_code: error.error?.code,
    message: error.error?.message,
    status: error.status,
    context: context,
    details: error.error?.details
  };

  // Send to monitoring service
  console.error('API Error:', errorLog);

  // Send to analytics
  if (window.analytics) {
    window.analytics.track('API Error', errorLog);
  }
}

4. Graceful Degradation

def get_price_with_fallback(commodity_code):
    """Get price with fallback strategies"""

    # Try primary API
    try:
        return fetch_from_api(commodity_code)
    except APIError as e:
        if e.code == 'QUOTA_EXCEEDED':
            # Use cached data if quota exceeded
            return get_cached_price(commodity_code)

        elif e.code == 'COMMODITY_NOT_FOUND':
            # Try alternative commodity codes
            alternatives = {
                'WTI': 'WTI_USD',
                'BRENT': 'BRENT_CRUDE_USD',
                'GAS': 'NATURAL_GAS_USD'
            }
            if commodity_code in alternatives:
                return fetch_from_api(alternatives[commodity_code])

        elif e.code in ['INTERNAL_ERROR', 'SERVICE_UNAVAILABLE']:
            # Use last known good value
            return get_last_known_price(commodity_code)

        # Re-raise if no fallback available
        raise

Testing Error Handling

# Test your error handling
def test_error_handling():
    test_cases = [
        # Missing API key
        {'headers': {}, 'expected_code': 'MISSING_API_KEY'},

        # Invalid API key
        {'headers': {'Authorization': 'Token invalid'},
         'expected_code': 'INVALID_API_KEY'},

        # Invalid commodity
        {'params': {'by_code': 'INVALID'},
         'expected_code': 'INVALID_COMMODITY'},

        # Invalid date range
        {'params': {'start': '2025-02-01', 'end': '2025-01-01'},
         'expected_code': 'INVALID_DATE_RANGE'}
    ]

    for test in test_cases:
        response = make_test_request(**test)
        assert response.get('error', {}).get('code') == test['expected_code']

Quick Reference Table

Error CodeHTTP StatusRetry?Action
MISSING_API_KEY401NoAdd API key
INVALID_API_KEY401NoCheck/regenerate key
INSUFFICIENT_PLAN403NoUpgrade plan
QUOTA_EXCEEDED403After resetWait or upgrade
RATE_LIMIT_EXCEEDED429YesWait and retry
INVALID_COMMODITY400NoFix commodity code
INVALID_PARAMETER400NoFix parameter
INTERNAL_ERROR500YesRetry with backoff
SERVICE_UNAVAILABLE503YesWait and retry

Support

For persistent errors or issues not covered here:

  • Email: [email protected]
  • Include: Error code, request_id, timestamp
  • Response time: 3 business days
Prev
Testing & Development
Next
Webhook Signature Verification