Dashboard Building
Build a real-time energy price dashboard backed by OilPriceAPI: fetch all prices efficiently, cache them, choose sensible update intervals, and render charts.
Problem
You want to display live oil, gas, and energy commodity prices on an internal or customer-facing dashboard. A naive implementation calls the API once per widget on every page load, which:
- Burns through your rate limit and request quota.
- Adds latency to every render.
- Hammers the API with redundant requests for data that only changes every few minutes.
The goal is a dashboard that feels instant, stays fresh, and uses a minimal number of API calls.
Solution Architecture
Put a small caching layer between your dashboard and OilPriceAPI:
Browser ──> Your backend (cache) ──> OilPriceAPI /prices/latest
^ |
└─ polls ───────┘ (served from cache, refreshed on an interval)
- Single batch fetch. Pull every commodity you need with one call to the "all prices" endpoint instead of one call per ticker.
- Server-side cache. Store the latest response in memory (or Redis) with a short TTL.
- Scheduled refresh. A background job refreshes the cache on a fixed interval; the browser reads from your cache, never directly from OilPriceAPI.
Code Implementation
Fetching all prices efficiently
Request every commodity in a single call rather than looping per symbol:
curl -H "Authorization: Token YOUR_API_KEY" \
"https://api.oilpriceapi.com/v1/prices/latest?by_type=spot_price"
Caching strategies
A read-through cache with a short TTL keeps the dashboard snappy while bounding your API usage. Spot prices update roughly every few minutes, so a 60-second TTL is a good default.
import time
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.oilpriceapi.com/v1"
CACHE_TTL_SECONDS = 60
_cache = {"data": None, "fetched_at": 0}
def get_latest_prices():
"""Return cached prices, refreshing only when the TTL has expired."""
now = time.time()
if _cache["data"] is None or now - _cache["fetched_at"] > CACHE_TTL_SECONDS:
resp = requests.get(
f"{BASE_URL}/prices/latest",
headers={"Authorization": f"Token {API_KEY}"},
params={"by_type": "spot_price"},
timeout=10,
)
resp.raise_for_status()
_cache["data"] = resp.json()
_cache["fetched_at"] = now
return _cache["data"]
Update intervals
Match your refresh interval to how often the underlying data changes. Polling faster than the data updates wastes quota without improving freshness.
| Data type | Typical change frequency | Suggested refresh |
|---|---|---|
| Spot prices | Every few minutes | 60 seconds |
| Daily settlements | Once per day | 15–30 minutes |
| Historical/EOD | Once per day | On demand |
Chart integration
Feed the cached payload into any charting library. Below is a minimal Chart.js example that renders a sparkline of recent values.
async function renderChart() {
const res = await fetch("/api/dashboard/prices"); // your cached endpoint
const { prices } = await res.json();
new Chart(document.getElementById("brent"), {
type: "line",
data: {
labels: prices.map((p) => p.created_at),
datasets: [
{
label: "Brent Crude (USD/bbl)",
data: prices.map((p) => p.price),
},
],
},
options: { responsive: true, scales: { y: { beginAtZero: false } } },
});
}
Best Practices
- Serve the dashboard from your cached endpoint, never directly from the browser to OilPriceAPI (this also keeps your API key off the client).
- Use one batch request for all tickers instead of N per-ticker requests.
- Send
If-None-Match/ETagwhere supported to avoid transferring unchanged payloads. - Show a "last updated" timestamp so users know how fresh the data is.
- Degrade gracefully: if a refresh fails, keep serving the last good cache entry rather than showing an error.
Common Pitfalls
- Polling faster than the data changes. A 1-second refresh on data that updates every 5 minutes just wastes quota.
- Caching per request instead of per process. A cache that lives inside a single request handler never gets a hit. Use a shared store (module-level, Redis, or memcached).
- Exposing your API key in frontend code. Always proxy through your backend.
- No error fallback. A transient API hiccup should not blank out the whole dashboard — serve stale-but-valid data and retry in the background.