Designing a Developer SDK for Energy API: Patterns for Idiomatic Clients, Pagination, Retries, and Versioning

Designing a Developer SDK for Energy API: Patterns for Idiomatic Clients, Pagination, Retries, and Versioning

Energy market data is notoriously fragmented. Electricity day-ahead auctions live on one site, intraday curves on another, gas benchmarks elsewhere, and carbon prices in a different portal altogether. Each provider ships unique schemas, units, clocks, holiday rules, and publishing cadences. As a developer, you need to make sense of it all, normalize symbol names, handle non-publishing days, and backfill gaps—before you can even draw a chart or compute a KPI.

This post is a deep, developer-first guide to designing an idiomatic SDK for Energy API, a unified REST interface for wholesale energy market data across electricity, natural gas, crude oil, coal, carbon allowances, and grid carbon intensity. We’ll discuss concrete SDK patterns for idiomatic clients, pagination through time windows, robust retries with backoff, and versioning strategies—so you can move from proof-of-concept to production with confidence. We’ll pair the design guidance with practical endpoint walkthroughs, complete JSON examples, and real-world use cases like PVPC retail cost estimation, price monitors for TTF vs. Henry Hub, electricity intraday dashboards, and ESG carbon intensity visualizations.

If you’ve ever stitched together EIA, FRED, OMIE, ENTSO-E, and ESIOS feeds, you know how easy it is to burn weeks on plumbing. A well-crafted SDK turns that integration tax into a few calls. Let’s build an approach that lets your teams ship features in hours, not weeks of ETL.

Why Energy API

Energy API replaces a patchwork of official sources with one normalized REST surface. In practice, this removes entire classes of integration risk. Here are the developer-centric advantages you feel immediately:

  • One schema for many commodities: Electricity, gas, oil, coal, carbon (ETS), and grid carbon intensity all share the same JSON shape for core endpoints. Your UI components, alerting logic, and data pipelines become commodity-agnostic. For example, /latest and /timeseries accept multiple symbols across categories in a single call—no custom adapters per provider.
  • Deterministic date handling: Historical lookups return the most recent value before a non-publishing day. Your graphs don’t fall apart on weekends or holidays; your backfills stay consistent without source-specific exceptions.
  • Intraday electricity curves where available: Build 15-minute or hourly curves for auction symbols directly, without scraping. OMIE day-ahead, PVPC retail curves, and regional electricity symbols are normalized, discoverable, and ready to chart.
  • Official-source aggregation without format drift: Energy API keeps a consistent canonical symbol set and metadata while fetching from trusted sources (e.g., OMIE, ENTSO-E, EIA, FRED, ESIOS). You target one interface; the service takes care of provider-specific cadence, late publications, and nomenclature quirks.

Put simply: you focus on insights and product logic; Energy API handles heterogeneity. That’s a material acceleration for data engineers, energy desks, fintech teams, utilities, and ESG products who want reliability more than they want to reinvent ETL.

Quick Start

The base URL for v1 is:

https://energy-api.com/api/v1

Authentication is via a query parameter. In your requests, include an api_key parameter. Here’s a first call that fetches the most recent values for Brent crude, TTF gas, and EU ETS allowances in one response:

curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=BRENT_CRUDE,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"

A representative JSON response:

{
"success": true,
"date": "2026-06-11",
"base": "MIXED",
"rates": {
"BRENT_CRUDE": 74.82,
"TTF_GAS": 38.15,
"EUA_CO2": 67.40
},
"dates": {
"BRENT_CRUDE": "2026-06-11",
"TTF_GAS": "2026-06-11",
"EUA_CO2": "2026-06-11"
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}

Key fields:

  • success: True indicates a valid data payload.
  • date: A canonical “as-of” date for the payload. Where multiple symbols are requested, it can represent the predominant market date; use the per-symbol dates map for precision.
  • rates: Numeric values keyed by symbol. These are the latest known prices.
  • dates: The market date for each symbol’s latest price—useful when different markets publish at different times.
  • currencies: Currency code per symbol. Electricity and gas in EUR, oil in USD, etc. Your client can label charts and perform conversions if needed.

Notice how multiple commodities share one response. That’s a unifying principle of Energy API that your SDK should embrace: batch symbols across categories whenever your UX or analytics permit it.

Core Endpoints

Below, we’ll cover a set of endpoints that matter most for production SDKs: discovery via /symbols, latest snapshots via /latest, time-windowed retrieval via /timeseries, intraday electricity curves via /electricity/hourly, and analytics-oriented views like /ohlc and /fluctuation. We’ll also mention category helpers and utility endpoints that improve reliability and observability.

1) GET /symbols — Discoverability and SDK Symbol Types

Purpose: Provide the canonical symbol list, categories, currencies, frequencies, and provider hints. Use it to generate typed enums in your SDK (e.g., Symbol.TTF_GAS) and to support search/auto-complete in UIs.

Key params:

  • base: Filter by currency code (optional).
  • category: gas | electricity | oil | coal | carbon_intensity (optional).
  • provider: fred | omie | eex (optional).

Example:

curl -G https://energy-api.com/api/v1/symbols \
--data-urlencode "category=gas" \
--data-urlencode "api_key=YOUR_API_KEY"

Sample JSON:

{
"success": true,
"count": 3,
"symbols": [
{
"symbol": "TTF_GAS",
"name": "TTF Natural Gas Day-Ahead",
"category": "gas",
"country_code": "EU",
"currency_code": "EUR",
"frequency": "daily",
"description": "TTF day-ahead price published by EEX."
}
]
}

SDK guidance:

  • Generate or cache symbol metadata and expose ergonomic lookups. For example, client.symbols.byCategory("electricity") to populate dropdowns.
  • Surface currency_code and frequency in your typed models for validation and UI hints. For instance, block intraday requests for a symbol whose frequency is “daily.”

2) GET /latest — Cross-Commodity Snapshots

Purpose: Fetch the most recent prices for one or multiple symbols across categories. Your SDK should accept either a list of typed symbols or a comma-separated string, normalize it, and return a structured result with per-symbol metadata.

Key params:

  • symbols: Comma-separated list (required).
  • base: Optional filter.
  • category: Optional filter by commodity category.

Example:

curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=BRENT_CRUDE,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"

Field tips:

  • rates: Use it for quick panels and top-of-dashboard tiles.
  • dates: Drive UI badges like “Updated: YYYY-MM-DD” per symbol.
  • currencies: Label axes or perform conversions in data pipelines.

3) GET /historical — Point-in-Time Retrieval with Non-Publishing Handling

Purpose: Obtain prices for a specific date, with automatic fallback to the latest available prior date. Perfect for backfills when a requested day is a weekend/holiday.

Key params:

  • date: YYYY-MM-DD (required).
  • symbols: Comma-separated list (required).
  • base: Optional.

Example:

curl -G https://energy-api.com/api/v1/historical \
--data-urlencode "date=2025-09-15" \
--data-urlencode "symbols=BRENT_CRUDE,TTF_GAS" \
--data-urlencode "api_key=YOUR_API_KEY"

Typical JSON:

{
"success": true,
"date": "2025-09-15",
"base": "MIXED",
"rates": {
"BRENT_CRUDE": 71.45,
"TTF_GAS": 36.20
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR"
}
}

SDK considerations:

  • Your client can expose an option like nearest=true (client-side behavior) to make it explicit that the service returns the latest available value on or before the date. Document this in your SDK’s method docstrings.

4) GET /timeseries — Pagination by Time Window

Purpose: Retrieve historical series between two dates, keyed by date. Ideal for charting, regressions, or model features. Although the API returns a complete window, your SDK should implement time-window pagination to gracefully handle long horizons (e.g., split 10-year windows into multiple calls).

Key params:

  • start: YYYY-MM-DD (required).
  • end: YYYY-MM-DD (required).
  • symbols: Comma-separated list (required).
  • base: Optional.

Example:

curl -G https://energy-api.com/api/v1/timeseries \
--data-urlencode "start=2025-01-01" \
--data-urlencode "end=2025-03-31" \
--data-urlencode "symbols=BRENT_CRUDE,TTF_GAS" \
--data-urlencode "api_key=YOUR_API_KEY"

Sample JSON:

{
"success": true,
"base": "MIXED",
"start_date": "2025-01-01",
"end_date": "2025-03-31",
"rates": {
"BRENT_CRUDE": {
"2025-01-02": 76.30,
"2025-01-03": 75.90
},
"TTF_GAS": {
"2025-01-02": 46.80,
"2025-01-03": 47.10
}
},
"frequencies": {
"BRENT_CRUDE": "daily",
"TTF_GAS": "daily"
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR"
}
}

Field notes:

  • rates: A nested dictionary of symbol → date → value. Charting is straightforward. For sparse days, you can either forward-fill or interpolate as your analytic requires.
  • frequencies: Validate that you’re not treating a daily series like an intraday one.
  • currencies: Useful when mixing EUR and USD series in the same visualization; expose an SDK utility for conversion if your app needs unified bases.

SDK pagination by time window:

  • Define a configurable “page size” as a date span (e.g., 180 days). For a large range (e.g., 2016-01-01 to 2026-09-01), generate segments like 2016-01-01..2016-06-29, 2016-06-30..2016-12-26, etc., ensuring contiguous non-overlapping windows.
  • Between calls, sleep with exponential backoff if you encounter transient errors (e.g., 429 or upstream delays surfaced as 404 for that publication day).
  • Merge partial results symbol-wise, deduplicating on date keys when window edges overlap by a day for safety.

5) GET /electricity/hourly — Intraday Curves

Purpose: Return full intraday curves (15-minute or hourly) for a given electricity symbol on a date. This is essential for flexible tariff analysis, retail price estimators, and grid-aware optimizations. Your SDK should normalize intervals into a common “start_time, end_time, price” tuple shape for charting, even if different symbols have different native cadences.

Key params:

  • symbol: Electricity symbol (required).
  • date: YYYY-MM-DD (required).

Example:

curl -G https://energy-api.com/api/v1/electricity/hourly \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "date=2026-06-11" \
--data-urlencode "api_key=YOUR_API_KEY"

Interpreting intraday data:

  • Align to ISO timestamps in your SDK output and include an explicit timezone indicator. If the response provides local-market time, your SDK can help convert to UTC for storage while preserving local-time labels for display.
  • When mixing with daily prices, offer utilities to compute daily averages, min/max, and peak/off-peak splits directly in your client.

6) GET /ohlc — Aggregated Candles

Purpose: Produce weekly, monthly, or quarterly candles for volatility and trend analysis. Many analytics use OHLC structures rather than raw daily points. Your SDK can expose typed candle frames (open, high, low, close, data_points) ready for direct plotting.

Key params:

  • symbols: Comma-separated list (required).
  • period: weekly | monthly | quarterly (default monthly).
  • start, end: Optional date bounds.
  • base: Optional.

Design tips:

  • When users request candles for mixed-frequency symbols, fetch, aggregate, and return separate keys per symbol as provided by the service. Keep symbols atomic in your SDK output to avoid conflation.
  • Expose helper methods like to_dataframe() or to_dicts() for immediate analytics consumption.

7) GET /fluctuation — Start/End, Absolute, Percent Change

Purpose: Rapid deltas for dashboards and alerts. Great for “last week vs. this week” or “month-to-date vs. last month” tiles without client-side math. The service returns start_value, end_value, change, and change_pct per symbol.

Key params:

  • start: YYYY-MM-DD (required).
  • end: YYYY-MM-DD (required).
  • symbols: Comma-separated list (required).
  • base: Optional.

SDK usage:

  • Offer helper formatters for percent-change with correct rounding and sign handling, e.g., +3.8%, -2.1%.
  • Combine with notification modules to set threshold alerts on change_pct.

8) Category Endpoints — Convenience Aggregates

Category endpoints encapsulate frequent baskets so you don’t have to specify multiple symbols repeatedly:

  • GET /electricity/latest — Latest prices for all electricity symbols, params include country filter.
  • GET /electricity/pvpc — Hourly PVPC retail reference prices for Spain by date. Great for consumer-facing cost breakdowns.
  • GET /gas/latest — One call to get TTF_GAS (EU, EUR/MWh) and HENRY_HUB (US, USD/MMBtu).
  • GET /emissions/latest — EU ETS EUA_CO2 price.
  • GET /coal/latest — COAL_ROTTERDAM (API2) and COAL_NEWCASTLE.
  • GET /carbon-intensity — Grid carbon intensity per country in gCO2eq/kWh. Ideal for ESG dashboards or carbon-aware scheduling.

SDK ergonomics:

  • Model these as domain-specific modules (client.electricity.latest(), client.gas.latest(), etc.) to reduce cognitive overhead in app code.

9) GET /forecast — Next Day-Ahead for Auction Symbols

Purpose: Deterministic “next published day-ahead price” retrieval for auction-sourced electricity symbols. It’s not a predictive model—it returns already-published auction results for the next delivery day. Your SDK should clearly label this as a published future-day lookup and gracefully handle 404 for non-auction symbols.

Key params:

  • symbol: Required.

SDK suggestion:

  • Expose a typed error or a None-return for non-auction symbols so callers can cleanly branch logic (e.g., fallback to /latest or /electricity/hourly).

10) POST /cost-estimate — Simple Monthly Wholesale Electricity Cost

Purpose: Multiply latest price by monthly consumption (kWh/month) for either a specific symbol or a country. Useful for instant retail-style what-if calculators, disclaiming taxes/network charges and hourly usage profiles. Your SDK should accept either symbol or country, but require exactly one.

Key body params:

  • symbol OR country (one required).
  • kwh_per_month (required).

Implementation tip:

  • Validate exclusivity: if symbol is provided, country must be None, and vice versa. Return a clear client-side validation error before hitting the network.

11) GET /status — Provider Pipeline Health

Purpose: Surface last fetch timestamps per provider. Your SDK can integrate this with health dashboards or circuit-breaker decisions. If a provider is delayed, your client can temporarily omit dependent features or switch to backup displays.

Design pattern:

  • Cache /status for a short interval (e.g., 60 seconds) and expose a health summary API for app layers (client.health.providers()).

Complete JSON Examples and Field Walkthroughs

Below are several full JSON examples to anchor what your SDK should expect and how to map them into typed results.

Example A: /latest for mixed symbols

{
"success": true,
"date": "2026-06-11",
"base": "MIXED",
"rates": {
"BRENT_CRUDE": 74.82,
"TTF_GAS": 38.15,
"EUA_CO2": 67.40
},
"dates": {
"BRENT_CRUDE": "2026-06-11",
"TTF_GAS": "2026-06-11",
"EUA_CO2": "2026-06-11"
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}

How to use:

  • Merge this with your symbol metadata so your UI can show proper labels (“Brent Crude (USD/barrel)”) and units.
  • If your SDK offers currency conversion utilities, detect the “MIXED” base and optionally convert to a unified display currency for consistent dashboards.

Example B: /timeseries for two symbols

{
"success": true,
"base": "MIXED",
"start_date": "2025-01-01",
"end_date": "2025-03-31",
"rates": {
"BRENT_CRUDE": {
"2025-01-02": 76.30,
"2025-01-03": 75.90,
"2025-01-06": 76.20
},
"TTF_GAS": {
"2025-01-02": 46.80,
"2025-01-03": 47.10,
"2025-01-06": 46.60
}
},
"frequencies": {
"BRENT_CRUDE": "daily",
"TTF_GAS": "daily"
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR"
}
}

How to use:

  • Build a chart series per symbol keyed by date. Decide how to treat missing days—forward-fill for cumulative analytics or leave gaps for raw truth.
  • If your app compares symbols directly, use an SDK helper to align currencies and possibly normalize (z-score, index at 100) to illustrate relative moves.

Example C: /symbols filtered by electricity

{
"success": true,
"count": 4,
"symbols": [
{
"symbol": "OMIE_ES_DA",
"name": "OMIE Spain Day-Ahead",
"category": "electricity",
"country_code": "ES",
"currency_code": "EUR",
"frequency": "daily",
"description": "Day-ahead auction price for Spain."
},
{
"symbol": "EPEX_DE_DA",
"name": "EPEX Germany Day-Ahead",
"category": "electricity",
"country_code": "DE",
"currency_code": "EUR",
"frequency": "daily",
"description": "Day-ahead auction price for Germany."
},
{
"symbol": "PVPC_ES_2TD",
"name": "Spain PVPC Retail 2-Period",
"category": "electricity",
"country_code": "ES",
"currency_code": "EUR",
"frequency": "hourly",
"description": "Spanish PVPC retail reference prices."
},
{
"symbol": "AEMO_NSW1",
"name": "AEMO NSW1 Spot",
"category": "electricity",
"country_code": "AU",
"currency_code": "AUD",
"frequency": "hourly",
"description": "Australian National Electricity Market - NSW region."
}
]
}

How to use:

  • Populate a symbol picker with metadata. Limit the date granularity UI based on frequency.
  • Offer “related symbols” suggestions by country_code.

Example D: Hypothetical /electricity/hourly shape

{
"success": true,
"symbol": "OMIE_ES_DA",
"date": "2026-06-11",
"timezone": "Europe/Madrid",
"granularity": "hourly",
"points": [
{ "start": "2026-06-11T00:00:00+02:00", "end": "2026-06-11T01:00:00+02:00", "price": 64.21 },
{ "start": "2026-06-11T01:00:00+02:00", "end": "2026-06-11T02:00:00+02:00", "price": 61.77 }
],
"currency": "EUR",
"unit": "MWh"
}

How to use:

  • Render heatmaps or 24-hour line charts. The timezone key ensures right labeling during DST transitions.
  • Provide SDK utilities to compute daily average, peak 5 hours, off-peak average, and cost-per-kWh conversions for retailers.

Designing an Idiomatic SDK: Patterns for Clients, Pagination, Retries, and Versioning

An excellent SDK feels native in the target language, makes safe-by-default choices, and gracefully handles the messy edges of real-world data pipelines. Here are the core design pillars for an Energy API client.

Idiomatic client surface

  • Typed enums and metadata: Generate Symbol types from /symbols at build-time or first-run cache. Provide helper namespaces: Gas.TTF_GAS, Electricity.OMIE_ES_DA, Carbon.EUA_CO2.
  • Category modules: client.gas.latest(), client.electricity.hourly(symbol, date), client.carbon.intensity(country). Names mirror domain tasks, not raw URLs.
  • Method overloads: Accept both strings and Symbol enums for developer convenience. Normalize internally and validate early.
  • Consistent return types: Wrap payloads in typed data classes (e.g., LatestResponse, TimeSeriesResponse) with methods like to_dict(), to_dataframe(), to_timeseries() to reduce adapter code in apps.

Pagination through time windows

  • Segmented requests: Expose get_timeseries_paged(symbols, start, end, window_days=180) that yields pages or returns a merged result. Avoid memory blowups by streaming pages for very long ranges.
  • Deduplication: If you overlap by one day between pages to guard against inclusive/exclusive boundary issues, ensure deduplication by (symbol, date).
  • Resumability: Accept a checkpoint callback (on_page(page_info)) so long-running backfills can resume from the last successful segment if interrupted.

Retries, backoff, and circuit breakers

  • Error taxonomy: Handle 401 (auth) by surfacing a clear configuration error to callers. Treat 404 as no data for given symbols or date—do not retry unless the caller explicitly wants a “retry on late publications” policy. For 422, surface validation hints. For 429, implement exponential backoff with jitter.
  • Exponential backoff: Start at 250–500ms and double up to a ceiling (e.g., 8–16s), with decorrelated jitter to avoid thundering herds.
  • Circuit breaker: If multiple calls fail for the same provider (visible via /status or from repeated 404 on a specific symbol/date during known maintenance windows), temporarily open a circuit to prevent useless retries and degrade features gracefully.

Versioning and compatibility

  • Explicit base URL versioning: Hardcode https://energy-api.com/api/v1 in your client config. Expose a version field for logging and instantiation.
  • Forward compatibility: Tolerate extra fields in JSON. Parse strictly for known keys but keep unknown fields in an “extras” map for debugging and forward analysis.
  • Semantic changelog: Surface client.version and service_version in logs so you can correlate behavior when upgrading.

Observability and diagnostics

  • Request/response logging: Toggle-able structured logs (symbol list, date bounds, durations, status codes). Redact sensitive values from logs.
  • Metrics: Counters for requests by endpoint, histograms for latency, gauges for page sizes. Your SDK can expose hooks so apps can plug into their observability stack.
  • Trace context: Accept a correlation_id in client options and propagate it as a header or query param if your ops practices call for it.

Data governance and correctness

  • Units and currencies: Always return unit and currency_code from metadata in your typed structures. Offer optional conversion helpers and warn on mixed-currency math without explicit conversion.
  • Timezones: Normalize to ISO 8601. Keep the service-provided timezone in intraday payloads and offer UTC conversions with clear semantics.
  • Data completeness: Provide validators (e.g., expect_daily_business_days=True) to flag suspicious gaps that might indicate a publishing delay versus a real market holiday.

Code Examples: cURL, Python, and JavaScript

cURL — Mixed Latest Snapshot

curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=BRENT_CRUDE,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"

Python — Idiomatic Client with Paging, Retries, and Field Mapping

import time
import requests
from datetime import date, timedelta

BASE_URL = "https://energy-api.com/api/v1"

class EnergyApiError(Exception):
pass

class RateLimitError(EnergyApiError):
pass

class ValidationError(EnergyApiError):
pass

def get(url, params, max_retries=5, backoff=0.5):
for attempt in range(max_retries):
r = requests.get(url, params=params, timeout=30)
if r.status_code == 200:
data = r.json()
if not data.get("success", False):
raise EnergyApiError(data.get("error", "Unknown error"))
return data
elif r.status_code == 422:
raise ValidationError(r.text)
elif r.status_code == 429:
# Exponential backoff with jitter
sleep_s = backoff * (2 ** attempt)
time.sleep(sleep_s + (sleep_s * 0.2))
continue
elif r.status_code == 404:
# No data for given symbols/date; surface clearly
raise EnergyApiError("No data for the requested symbols/date (404).")
elif r.status_code == 401:
raise EnergyApiError("Authentication error (401).")
else:
# Retry on transient 5xx
if 500 <= r.status_code < 600 and attempt < max_retries - 1:
time.sleep(backoff * (2 ** attempt))
continue
raise EnergyApiError(f"HTTP {r.status_code}: {r.text}")
raise RateLimitError("Exceeded retry attempts due to rate limiting or transient errors.")

def latest(api_key, symbols):
url = f"{BASE_URL}/latest"
params = {"symbols": ",".join(symbols), "api_key": api_key}
return get(url, params)

def timeseries_paged(api_key, symbols, start, end, window_days=180):
start_d = date.fromisoformat(start)
end_d = date.fromisoformat(end)
current = start_d
while current <= end_d:
window_end = min(current + timedelta(days=window_days - 1), end_d)
url = f"{BASE_URL}/timeseries"
params = {
"start": current.isoformat(),
"end": window_end.isoformat(),
"symbols": ",".join(symbols),
"api_key": api_key
}
yield get(url, params)
current = window_end + timedelta(days=1)

if __name__ == "__main__":
api_key = "YOUR_API_KEY"
symbols = ["BRENT_CRUDE", "TTF_GAS", "EUA_CO2"]
snap = latest(api_key, symbols)
print("Latest snapshot:", snap["rates"])

# Paged timeseries over a long horizon
for page in timeseries_paged(api_key, ["TTF_GAS"], "2023-01-01", "2024-12-31", window_days=120):
print("Page window:", page["start_date"], "to", page["end_date"], "points:", len(page["rates"]["TTF_GAS"]))

JavaScript — Fetch Intraday Electricity Curve and Compute Daily Average

async function fetchJson(url, params) {
const usp = new URLSearchParams(params);
const res = await fetch(`${url}?${usp.toString()}`, { method: "GET" });
if (!res.ok) {
const text = await res.text();
throw new Error(`HTTP ${res.status}: ${text}`);
}
const data = await res.json();
if (!data.success) throw new Error(data.error || "Unknown error");
return data;
}

async function intradayAverage(apiKey, symbol, dateStr) {
const url = "https://energy-api.com/api/v1/electricity/hourly";
const data = await fetchJson(url, { symbol, date: dateStr, api_key: apiKey });

const points = data.points || [];
if (points.length === 0) return null;

// Weighted average in case of 15-min granularity
let totalCost = 0;
let totalHours = 0;
for (const p of points) {
const start = new Date(p.start);
const end = new Date(p.end);
const hours = (end - start) / 3600000.0;
totalCost += p.price * hours;
totalHours += hours;
}
return totalCost / totalHours;
}

(async () => {
const avg = await intradayAverage("YOUR_API_KEY", "OMIE_ES_DA", "2026-06-11");
console.log("Daily average price:", avg);
})();

Error Handling, Validation, and Resilience

Design your SDK to make good practices the default:

  • Status codes:
    • 401 — Authentication issue; surface a clear configuration error.
    • 404 — No data for symbols/date; don’t auto-retry unless you have a reason (e.g., known late publication and a caller opt-in).
    • 422 — Validation error; include param name and value in your error message if available.
    • 429 — Back off with exponential jitter; consider a global rate limiter in the client.
  • Error shape: {"success": false, "error": "Human-readable message."}. Always check success before reading payloads.
  • Validation guards: Enforce parameter rules in client methods (e.g., POST /cost-estimate requires exactly one of symbol or country).
  • Health checks: Query GET /status to detect provider delays; use this to mute noisy alerts or pause background fetches temporarily.

Real-World Use Cases

1) Price alert system for gas and oil spreads

Traders and analysts monitor spreads between TTF_GAS and HENRY_HUB, or Brent vs. WTI, triggering alerts when moves exceed a threshold. Build a lightweight worker that calls GET /latest with symbols=[TTF_GAS, HENRY_HUB, BRENT_CRUDE, WTI_CRUDE], computes pairwise differentials, and posts to your notification system. For context windows, use GET /timeseries to compute rolling z-scores and filter noise. Endpoints used: /latest, /timeseries, optionally /fluctuation for 24-hour percent change tiles.

2) ESG dashboard with grid carbon intensity overlays

Sustainability teams build internal dashboards correlating production schedules with grid carbon intensity (gCO2eq/kWh). With GET /carbon-intensity, pull CARBON_INT_DE or CARBON_INT_EU values and overlay them on electricity price curves from GET /electricity/hourly for regions like OMIE_ES_DA or EPEX_DE_DA. Use /timeseries for historical correlations and to generate weekly carbon-aware scheduling suggestions. Endpoints used: /carbon-intensity, /electricity/hourly, /timeseries.

3) Consumer-facing electricity cost calculator

Fintech or retail energy apps often expose “What will my monthly cost be at today’s wholesale?” calculators. Use POST /cost-estimate with country=ES and kwh_per_month derived from user inputs, or symbol=OMIE_ES_DA for more control. For more granular education, fetch GET /electricity/pvpc and show hourly cost breakdowns with peak/off-peak differentials. Endpoints used: /cost-estimate, /electricity/pvpc, /electricity/hourly.

FAQ

How often does the TTF gas price update?

TTF_GAS is delivered as a daily series reflecting official market publications. The latest endpoint always returns the most recent available value, and historical requests automatically fall back to the latest prior publishing day if your requested date is a weekend or holiday. For intraday needs, combine daily TTF with electricity intraday curves to round out your dashboards.

Can I query multiple commodities in one call?

Yes. That’s a core advantage of Energy API. Endpoints like /latest and /timeseries accept multiple symbols across categories (e.g., BRENT_CRUDE, TTF_GAS, EUA_CO2) and return a unified schema. Your SDK can exploit this to populate cross-asset dashboards and analytics without juggling heterogeneous APIs.

Can I get historical energy prices going back 5 years?

Use GET /timeseries with a long start/end range, or implement SDK pagination by date windows to iterate through extended horizons. The response includes per-symbol frequencies and currencies so you can validate assumptions and unify units. Combine with /ohlc to downsample history into weekly or monthly candles for performance.

Does the API support grid carbon intensity for multiple countries?

Yes. GET /carbon-intensity returns grid carbon intensity in gCO2eq/kWh by country, allowing you to compare regions or overlay emissions with electricity price signals. It’s particularly useful in ESG reporting and carbon-aware load shifting scenarios.

How should I handle non-publishing days in charts?

The service returns the last available value before a non-publishing day for historical retrievals. In your SDK, expose options to visualize gaps explicitly or to forward-fill (for KPI continuity). For OHLC views, rely on GET /ohlc to compute robust period aggregations regardless of calendar quirks.

Conclusion + CTA

The fastest path from zero to production energy data is to avoid bespoke scrapers and normalize-once interfaces. With Energy API, you can query electricity, gas, oil, coal, carbon, and grid carbon intensity through one REST surface. A well-designed SDK makes this even more powerful: idiomatic clients, safe-by-default parameter validation, resilient retries and backoff, time-window pagination, and clean typed models that map directly to charts and analytics. You spend time on insights and product value—not glue code.

Whether you’re building a trading P&L view, an ESG dashboard, or a consumer-facing cost calculator, the combination of standardized endpoints and strong SDK design eliminates entire classes of integration risk. Start by shipping quick wins—/latest tiles, /timeseries charts, and /electricity/hourly heatmaps—then layer in advanced analytics with /ohlc and /fluctuation. Keep your app healthy with /status-driven circuit breakers, and scale confidently with paging utilities across long historical windows.

Explore the unified surface at Energy API and put these SDK patterns to work today. Build your first cross-commodity dashboard, test intraday curves, and wire up robust error handling and pagination. When you’re ready to move from prototype to production, you’ll already have the foundations in place. Try Energy API for free and start shipping energy intelligence in hours, not weeks.

Ready to get started?

Get your API key and start querying energy commodity prices in minutes.

Get API Key

Related posts