SDK Code Examples
Practical, copy-pasteable examples for the two operations developers ask about most: paginating through large result sets and handling errors robustly (retries, rate limits, authentication failures, and network errors).
All examples use the Authorization: Token <your-api-key> header convention and the base URL https://api.oilpriceapi.com. Replace YOUR_API_KEY with your real key from the dashboard.
Pagination metadata is returned in response headers:
X-Total-Pages,X-Total-Count, andX-Page. Request a page with thepageandper_pagequery parameters.
Pagination
Walk every page of a paginated endpoint (for example historical prices) until the X-Total-Pages header says there are no more pages.
Python (requests)
import requests
import time
def get_all_pages(endpoint, api_key, per_page=100):
page = 1
all_data = []
while True:
response = requests.get(
f'https://api.oilpriceapi.com{endpoint}',
params={'page': page, 'per_page': per_page},
headers={'Authorization': f'Token {api_key}'},
timeout=30,
)
# Respect rate limits while paginating
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
continue
response.raise_for_status()
payload = response.json()
all_data.extend(payload['data'])
total_pages = int(response.headers.get('X-Total-Pages', 1))
if page >= total_pages:
break
page += 1
return all_data
prices = get_all_pages('/v1/prices/past_day', 'YOUR_API_KEY')
print(f'Fetched {len(prices)} records')
JavaScript (fetch)
async function getAllPages(endpoint, apiKey, perPage = 100) {
let page = 1;
const allData = [];
while (true) {
const url = `https://api.oilpriceapi.com${endpoint}?page=${page}&per_page=${perPage}`;
const response = await fetch(url, {
headers: { Authorization: `Token ${apiKey}` },
});
// Respect rate limits while paginating
if (response.status === 429) {
const retryAfter = Number(response.headers.get('Retry-After') || 60);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
continue;
}
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
const payload = await response.json();
allData.push(...payload.data);
const totalPages = Number(response.headers.get('X-Total-Pages') || 1);
if (page >= totalPages) break;
page += 1;
}
return allData;
}
getAllPages('/v1/prices/past_day', 'YOUR_API_KEY')
.then((rows) => console.log(`Fetched ${rows.length} records`))
.catch((err) => console.error(err));
Ruby (HTTParty)
require 'httparty'
def get_all_pages(endpoint, api_key, per_page: 100)
page = 1
all_data = []
loop do
response = HTTParty.get(
"https://api.oilpriceapi.com#{endpoint}",
query: { page: page, per_page: per_page },
headers: { 'Authorization' => "Token #{api_key}" }
)
# Respect rate limits while paginating
if response.code == 429
retry_after = (response.headers['Retry-After'] || 60).to_i
sleep(retry_after)
next
end
raise "Request failed: #{response.code}" unless response.success?
all_data.concat(response.parsed_response['data'])
total_pages = (response.headers['X-Total-Pages'] || 1).to_i
break if page >= total_pages
page += 1
end
all_data
end
prices = get_all_pages('/v1/prices/past_day', 'YOUR_API_KEY')
puts "Fetched #{prices.length} records"
PHP (cURL)
<?php
function get_all_pages($endpoint, $api_key, $per_page = 100) {
$page = 1;
$all_data = [];
while (true) {
$url = "https://api.oilpriceapi.com{$endpoint}?page={$page}&per_page={$per_page}";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Token {$api_key}",
]);
$response = curl_exec($ch);
// Network error handling
if ($response === false) {
throw new Exception('Network error: ' . curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers_raw = substr($response, 0, $header_size);
$body = substr($response, $header_size);
curl_close($ch);
// Respect rate limits while paginating
if ($status === 429) {
preg_match('/Retry-After:\s*(\d+)/i', $headers_raw, $m);
sleep(isset($m[1]) ? (int) $m[1] : 60);
continue;
}
$payload = json_decode($body, true);
$all_data = array_merge($all_data, $payload['data']);
preg_match('/X-Total-Pages:\s*(\d+)/i', $headers_raw, $tp);
$total_pages = isset($tp[1]) ? (int) $tp[1] : 1;
if ($page >= $total_pages) {
break;
}
$page++;
}
return $all_data;
}
$prices = get_all_pages('/v1/prices/past_day', 'YOUR_API_KEY');
echo 'Fetched ' . count($prices) . " records\n";
Error Handling
Production integrations must handle four failure classes:
| Class | HTTP / Signal | Strategy |
|---|---|---|
| Rate limited | 429 | Wait for Retry-After, then retry |
| Transient server error | 500, 502, 503 | Retry with exponential backoff |
| Authentication failure | 401 | Stop and surface a clear error (do not retry) |
| Network error | timeout / connection reset | Retry a few times, then fail |
Retry logic with exponential backoff
The delay grows on each attempt (2 ** attempt seconds) so a struggling server is not hammered. Authentication failures (401) are not retried.
import requests
import time
class AuthenticationError(Exception):
pass
def request_with_retry(method, url, api_key, max_retries=5, **kwargs):
headers = kwargs.pop('headers', {})
headers['Authorization'] = f'Token {api_key}'
for attempt in range(max_retries):
try:
response = requests.request(
method, url, headers=headers, timeout=30, **kwargs
)
except (requests.ConnectionError, requests.Timeout) as exc:
# Network error: back off and retry
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
continue
# Authentication failure: do not retry
if response.status_code == 401:
raise AuthenticationError('Invalid or missing API key (401)')
# Rate limited: honor Retry-After
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 2 ** attempt))
time.sleep(retry_after)
continue
# Transient server errors: exponential backoff
if response.status_code in (500, 502, 503):
time.sleep(2 ** attempt) # exponential backoff
continue
response.raise_for_status()
return response.json()
raise RuntimeError(f'Request failed after {max_retries} attempts')
data = request_with_retry(
'GET',
'https://api.oilpriceapi.com/v1/prices/latest',
'YOUR_API_KEY',
params={'by_code': 'BRENT_CRUDE_USD'},
)
print(data)
Rate limit handling
When you receive a 429, the Retry-After response header tells you how many seconds to wait before retrying.
async function fetchWithRateLimit(url, apiKey) {
while (true) {
const response = await fetch(url, {
headers: { Authorization: `Token ${apiKey}` },
});
if (response.status === 429) {
const retryAfter = Number(response.headers.get('Retry-After') || 60);
console.warn(`Rate limited. Retrying in ${retryAfter}s`);
await new Promise((r) => setTimeout(r, retryAfter * 1000));
continue;
}
return response.json();
}
}
Authentication failures
A 401 means the API key is missing, malformed, or revoked. Do not retry — fix the credential.
require 'httparty'
response = HTTParty.get(
'https://api.oilpriceapi.com/v1/prices/latest',
headers: { 'Authorization' => "Token #{ENV['OILPRICE_API_KEY']}" }
)
case response.code
when 401
raise 'Authentication failed (401): check your API key'
when 200
puts response.parsed_response
else
raise "Unexpected status: #{response.code}"
end
Network errors
Connection resets and timeouts are transient. Retry a bounded number of times, then surface the error.
<?php
function fetch_with_network_retry($url, $api_key, $max_retries = 3) {
for ($attempt = 0; $attempt < $max_retries; $attempt++) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Token {$api_key}",
]);
$body = curl_exec($ch);
// Network error: curl_errno is non-zero
if (curl_errno($ch)) {
$err = curl_error($ch);
curl_close($ch);
if ($attempt === $max_retries - 1) {
throw new Exception("Network error after retries: {$err}");
}
sleep(2 ** $attempt); // exponential backoff
continue;
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status === 401) {
throw new Exception('Authentication failed (401)');
}
return json_decode($body, true);
}
}