Data Freshness & Update Frequency
Understanding when and how data updates is critical for building reliable integrations. This guide explains update frequencies, timestamp behavior, and how to detect stale data.
Overview
- All timestamps are UTC in ISO 8601 format (e.g.,
2026-02-02T14:35:00Z) - Update frequency varies by commodity type and data source
- Timestamps update on every refresh cycle, even if the price hasn't changed
Timestamp Behavior
Does the timestamp update when the price doesn't change?
Yes. The created_at timestamp reflects when data was last refreshed, not when the price last changed. This is intentional - it lets you verify the API is actively polling data sources.
Example Response:
{
"code": "BRENT_CRUDE",
"price": 76.42,
"currency": "USD",
"unit": "barrel",
"created_at": "2026-02-02T14:35:00Z"
}
The created_at timestamp means "this price was confirmed accurate at 14:35 UTC" - not "the price changed at 14:35."
How to detect actual price changes
To detect when prices actually change, you have several options:
- Compare consecutive
pricevalues in your application - Use webhooks - only triggered on actual price changes
- Check the
change_24hfield in analytics endpoints for price movement
Update Frequency by Category
High-Frequency Data (5-15 minute updates)
| Commodity | Frequency | Trading Hours | Notes |
|---|---|---|---|
| WTI Crude | 5 min | 24/5 | Multiple sources (ICE, NYMEX, IG) |
| Brent Crude | 5 min | 24/5 | ICE Futures + backup sources |
| ICE Gasoil | 5 min | 01:00-23:00 UTC | ICE Futures Europe |
| Natural Gas (Henry Hub) | 5 min | Trading hours | NYMEX futures |
| UK Natural Gas | 15 min | Trading hours | IG Markets |
| Gold | 1 min | 24/5 | Multiple sources |
| Silver | 1 min | 24/5 | Multiple sources |
| EU Carbon (EUA) | 15 min | 05:00-17:00 UTC Mon-Fri | ICE Futures |
Daily Data (1x per day)
| Commodity | Update Time | Notes |
|---|---|---|
| Dubai Crude | 15:00 UTC weekdays | Platts MOC assessment |
| Newcastle Coal | End of day | Market close prices |
| Uranium Spot | Mondays 15:00 UTC | Weekly spot market |
Weekly Data
| Commodity | Update Day | Update Time | Source |
|---|---|---|---|
| US Diesel (all regions) | Monday | 02:00 UTC | EIA |
| US Gasoline | Monday | 02:00 UTC | EIA |
| Coal Spot (CAPP, PRB, Illinois) | Tuesday | 02:00 UTC | EIA |
| Rig Counts | Friday | 18:30 UTC | Baker Hughes |
| Natural Gas Storage | Thursday | 14:35 UTC | EIA |
| Oil Inventories | Wednesday | 14:35 UTC | EIA WPSR |
Monthly Data
| Data Type | Update Day | Source |
|---|---|---|
| DUC Wells | ~15th | EIA DPR |
| OPEC Production | ~15th | OPEC MOMR |
| Price Forecasts | 1st | EIA STEO |
Detecting Stale Data
Freshness Thresholds
Use these guidelines to determine if data might be stale:
| Commodity Type | Stale If Older Than | During |
|---|---|---|
| Crude oil, futures | 15 minutes | Trading hours |
| Natural gas | 30 minutes | Trading hours |
| Precious metals | 5 minutes | 24/5 |
| Weekly data (diesel, coal) | 8 days | Any time |
| Monthly data | 35 days | Any time |
Checking Freshness in Code
from datetime import datetime, timedelta, timezone
def is_stale(created_at_str, max_age_minutes):
"""Check if data is stale based on timestamp."""
created_at = datetime.fromisoformat(created_at_str.replace('Z', '+00:00'))
age = datetime.now(timezone.utc) - created_at
return age > timedelta(minutes=max_age_minutes)
# Example: Check if crude oil data is stale (>15 min old)
if is_stale(response['created_at'], max_age_minutes=15):
print("Warning: Data may be stale")
Weekend and Holiday Behavior
- Weekends: Futures markets are closed. Expect no updates from Saturday to Sunday.
- US Holidays: US-sourced data (EIA) may be delayed by 1-2 days.
- UK Holidays: UK gas data may show last known price.
- Market Holidays: Exchange-specific holidays affect futures data.
Response Headers for Freshness
Every API response includes headers to help monitor data currency:
| Header | Description | Example |
|---|---|---|
X-Data-Timestamp | When the price was last updated | 2026-02-02T14:35:00Z |
X-Data-Source | Primary source for this data point | ice_futures |
X-Cache | Whether response was cached | HIT or MISS |
Handling Missing or Delayed Data
Why data might be missing
- Source outage: Data provider experiencing issues
- Market closed: No trading activity (weekends, holidays)
- Network issues: Temporary connectivity problems
What we do automatically
- Failover: If primary source fails, backup sources activate within 5 minutes
- Monitoring: Our team is alerted to source issues 24/7
- Carry-forward: For some daily commodities, last known price is preserved with original timestamp
What you should do
- Check timestamps: Always verify
created_atis recent enough for your use case - Handle nulls: Missing data returns
null- your code should handle this gracefully - Use fallbacks: Consider caching recent prices as a fallback
- Subscribe to status: Follow @oilpricehourly for service updates
API Endpoints for Freshness Monitoring
Check Latest Timestamp
GET /v1/prices/latest?by_code=BRENT_CRUDE
The created_at field in the response shows when data was last refreshed.
Bulk Freshness Check
GET /v1/prices/latest
Returns latest prices for all commodities - useful for monitoring freshness across your portfolio.
Contact
For questions about data freshness or to report stale data:
- Email: [email protected]
- Response Time: Same business day for freshness concerns