Designing a Contract-First OpenAPI Spec for Energy API Integrations: Best Practices for Versioning, Mocking, and Consumer-Driven Contracts

Designing a Contract-First OpenAPI Spec for Energy API Integrations: Best Practices for Versioning, Mocking, and Consumer-Driven Contracts

If you build energy data products, you already know the hard part isn’t code—it’s contracts. Different providers ship different file formats, symbols, time zones, and publishing cadences. Integrating OMIE for Spain’s day-ahead auctions, ENTSO-E for cross-border flows, EIA/FRED for oil and gas, ESIOS for Spanish PVPC, and various carbon sources means five (or more) separate contracts to stabilize. That creates a surface area of breakage across dates, currencies, missing datapoints, and “mostly documented” edge cases.

This post shows how to turn the problem inside out: design your integration contract-first with a single OpenAPI specification that normalizes wholesale energy data behind one REST surface. We’ll use the unified interface provided by Energy API—a normalized REST API for electricity, natural gas, crude oil, coal, carbon allowances, and grid carbon intensity—to illustrate versioning strategies, mocking, and consumer‑driven contracts (CDCs) that keep your systems honest as they scale.

You’ll see how to model symbols consistently, validate date ranges and currencies, and enforce reliable contracts across 16 endpoints: spot/latest, historical snapshots, range timeseries, OHLC candles, intraday electricity curves, day-ahead forecasts, category shortcuts, cost estimation, fluctuation analysis, and provider health checks. We’ll include a practical OpenAPI-first playbook—versioning patterns, mock servers, test harnesses—and we’ll ground it with production-grade examples using the Energy API endpoints and JSON shapes you can ship today.

Why Energy API

Building a unified energy data layer in-house looks deceptively simple until a symbol silently drifts, an auction calendar shifts, or a CSV adds a column. Energy API abstracts that complexity with a single, normalized JSON schema across commodities and providers, so you can ship features in hours—not weeks of custom ETL and brittle screen-scraping.

  • One normalized REST surface replaces OMIE, ENTSO-E, EIA/FRED, ESIOS, and more. Instead of juggling multiple contracts, you speak one language: symbol, date(s), and base currency filters. That directly reduces integration risk and testing overhead.
  • A single schema across electricity, gas, oil, coal, carbon, and carbon intensity. Your analytics and alerting pipelines don’t branch on commodity edge cases. You can query mixed symbols (e.g., TTF_GAS, BRENT_CRUDE, EUA_CO2) in one call and still get consistent field names and error shapes.
  • 16 endpoints that map cleanly to business needs: live spot, historical snapshots, timeseries windows for charting, OHLC for volatility, intraday electricity curves, forecasted day-ahead auctions, category shortcuts, cost estimation, and fluctuation analysis. The surface is broad but cohesive.
  • Proven sources and coverage, curated and normalized. Energy API sources from OMIE, ENTSO-E, EIA/FRED, ESIOS, and recognized datasets, saving you from parsing irregular CSVs, retrying failed scrapes, and reconciling time zones and naming conventions.

For developers, the big win is contract stability: you can codify and test against one OpenAPI document that captures the semantic guarantees of your system. The endpoints are versioned under /api/v1, responses include consistent success flags, currencies, and rate dictionaries, and errors use a predictable JSON shape that your middleware can handle uniformly.

Quick Start

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

Grab the most recent value for multiple commodities in a single call. Querying mixed categories in one request is a differentiator—you can stitch cross‑commodity dashboards and alerts without juggling separate services.

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"

Example 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: Boolean guard for error handling upstream; treat false as an exception path with a stable error shape.
  • date: Unified reporting date for the response context; when querying multiple symbols, you’ll also get per‑symbol dates in the dates map to reflect different publication times.
  • rates: Symbol to numeric value. The contract guarantees numbers, not strings—no downstream parsing surprises.
  • currencies: Symbol to currency code mapping that lets your UI add currency badges or run conversions.
  • dates: Symbol to ISO date string for the specific last‑published value.

Contract‑First OpenAPI Design for Energy Integrations

A contract-first OpenAPI approach means you specify the behavior of your integration before writing glue code. With energy data, this pays for itself because you can encode and test nuanced rules that vary across providers but collapse into one uniform interface in your domain. Below is a blueprint to author a robust OpenAPI 3.1 spec for your Energy API integration.

Scope and model design

  • Consolidate common structs under components/schemas: PriceResponse, ErrorResponse, TimeseriesResponse, OhlcCandle, ElectricityCurvePoint, and FluctuationItem. Keep field names stable across categories.
  • Symbols as enums with descriptions: e.g., TTF_GAS, HENRY_HUB, BRENT_CRUDE, WTI_CRUDE, OMIE_ES_DA, EPEX_DE_DA, PVPC_ES_2TD, AEMO_NSW1, EUA_CO2, COAL_ROTTERDAM, COAL_NEWCASTLE, CARBON_INT_EU, CARBON_INT_DE. Add x-tags like x-category: gas|oil|electricity|coal|carbon|carbon_intensity to help clients filter.
  • Date handling: All endpoints that accept dates must require YYYY-MM-DD with format: date. For intraday curves, the date refers to the delivery day in local market time; encode this in descriptions to avoid ambiguity.
  • Currencies: currencies is a map keyed by symbol. Avoid top‑level base currency conversions in the spec unless you control FX inputs; instead, implement a base param that acts as a filter or, where supported, a conversion rule specified in the endpoint description.

Versioning strategy

  • Path versioning: Keep the v1 in the path (/api/v1) and commit to semantic versioning for the OpenAPI file itself. Backwards‑compatible changes (adding optional fields, new symbols) increment minor; breaking changes (field rename, shape changes) require a major path version (e.g., /api/v2).
  • Deprecations: Use the deprecations section in your changelog, and annotate endpoints with deprecated: true plus a clear description and sunset date. In clients, surface these as warnings in CI.
  • Examples as contracts: For every endpoint, ship at least one example object that exercises edge cases (e.g., missing intraday points due to holidays, non‑publishing dates returning the previous business day).

Mocking and validation

  • Mock server: Use a spec‑driven mock like Stoplight Prism or similar to host a mocked Energy API upstream while you build. Your CI can run contract tests against the mock before hitting production.
  • CDC (Consumer‑Driven Contracts): If you maintain downstream services that query Energy API, define Pact (or similar) tests to assert the requests and minimal fields you rely on. This guards against accidental assumptions in client code as symbols and categories grow.
  • Property‑based testing: Validate your OpenAPI examples with JSON Schema validators and run Schemathesis against your spec to fuzz parameter combinations (date windows, comma‑separated symbols).

Error contracts

  • Standardized error envelope: success=false, error=human‑readable message. Your OpenAPI must enumerate common 4xx/5xx with a shared ErrorResponse to simplify middleware and observability.
  • Validation: 422 for malformed dates, missing required parameters (e.g., symbol missing for electricity/hourly), or unsupported values. Be explicit in your schema and examples.
  • Not found: 404 for unknown symbols or forecasts for non‑auction symbols.

With the contract in place, you can generate type‑safe clients, mock servers, test harnesses, and even documentation that aligns your energy data semantics across teams without re‑reading provider PDFs.

Core Endpoints You’ll Use First

Below are key endpoints you’ll likely wire up early. Each example demonstrates the request pattern, shape, and how to map it to your use case. Remember: you can query multiple commodities in one call when that makes sense—huge leverage for cross‑commodity dashboards.

1) Discover Symbols — GET /symbols

Use /symbols to discover active symbols, their categories, countries, currencies, and publishing frequencies. This helps you drive a config‑driven UI (dropdowns, filters) or bootstrap ETL catalogs automatically.

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

Example JSON response:

{
"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."
},
{
"symbol": "HENRY_HUB",
"name": "Henry Hub Natural Gas",
"category": "gas",
"country_code": "US",
"currency_code": "USD",
"frequency": "daily",
"description": "US benchmark natural gas spot price."
},
{
"symbol": "EUA_CO2",
"name": "EU ETS Carbon Allowance",
"category": "carbon",
"country_code": "EU",
"currency_code": "EUR",
"frequency": "daily",
"description": "EU ETS allowance price per metric tonne CO2e."
}
]
}

Field highlights:

  • count: Use for pagination logic or sanity checks.
  • frequency: daily, hourly, or quarterly/monthly support helps pick the right visualization granularity.
  • description: Embed in UI tooltips or documentation—no extra copywriting needed.

2) Latest Mixed Symbols — GET /latest

Fetch live spot values for multiple symbols with one request. Use this for dashboards, alerting triggers, or to seed day‑zero cache warmers at service start.

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"

Design tip: In your OpenAPI spec, model symbols as a CSV string with pattern: ^[A-Z0-9_]+(,[A-Z0-9_]+)*$ and provide an enum list in the description. Keep dates and currencies as separate maps; this discourages clients from guessing currency by category.

3) Historical Snapshot — GET /historical

Get values for a specific date for multiple symbols. If the date is a non‑publishing day, the most recent prior value is returned. This is ideal for end‑of‑month snapshots or period‑end valuation processes.

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"

Response fields mirror /latest but are locked to a given date context, de‑risking accounting flows where deterministic valuation dates are critical.

4) Timeseries Window — GET /timeseries

Pull historical windows for charting and trend analysis with per‑day values keyed by date. This is a core building block for performance analysis, moving averages, and volatility features.

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"

Example JSON response:

{
"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"
}
}

What to do with it:

  • rates: A nested map keyed by symbol, then date. Your OpenAPI should define additionalProperties: number with format: double for inner values. This makes typed SDKs efficient and predictable.
  • frequencies: Encode series granularity per symbol so consumers can resample correctly in charting libraries without hard‑coding assumptions.
  • start_date/end_date: Assert inclusive boundaries in your tests; when an upstream provider skips a holiday, you still get a tight window without sparse trailing keys.

5) OHLC Candles — GET /ohlc

Query weekly, monthly, or quarterly OHLC candles for candlestick charts and volatility analysis. Useful for traders and analytics teams synthesizing longer‑horizon views.

curl -G https://energy-api.com/api/v1/ohlc \
--data-urlencode "symbols=BRENT_CRUDE,WTI_CRUDE" \
--data-urlencode "period=monthly" \
--data-urlencode "start=2024-01-01" \
--data-urlencode "end=2024-12-31" \
--data-urlencode "api_key=YOUR_API_KEY"

Example JSON response:

{
"success": true,
"period": "monthly",
"series": {
"BRENT_CRUDE": [
{ "period": "2024-01", "open": 77.10, "high": 81.50, "low": 74.90, "close": 80.20, "data_points": 22 },
{ "period": "2024-02", "open": 80.25, "high": 83.90, "low": 78.10, "close": 82.75, "data_points": 20 }
],
"WTI_CRUDE": [
{ "period": "2024-01", "open": 71.40, "high": 75.30, "low": 69.80, "close": 74.10, "data_points": 22 }
]
},
"currencies": {
"BRENT_CRUDE": "USD",
"WTI_CRUDE": "USD"
}
}

Design notes:

  • Each symbol maps to an array of candles; include data_points to signal how many raw observations were aggregated—handy for QA or detecting sparse months.
  • period accepts weekly|monthly|quarterly. Model as an enum and require clients to opt in; there’s no silent default change risk later.

6) Fluctuation — GET /fluctuation

Summarize movement across a window with start_value, end_value, change, and change_pct per symbol. Perfect for headlines, daily recaps, and risk digests.

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

Example JSON response:

{
"success": true,
"start_date": "2025-05-01",
"end_date": "2025-05-31",
"results": {
"EUA_CO2": { "start_value": 71.20, "end_value": 67.40, "change": -3.80, "change_pct": -5.34 },
"TTF_GAS": { "start_value": 40.10, "end_value": 38.15, "change": -1.95, "change_pct": -4.86 },
"BRENT_CRUDE": { "start_value": 76.00, "end_value": 74.82, "change": -1.18, "change_pct": -1.55 }
},
"currencies": {
"EUA_CO2": "EUR",
"TTF_GAS": "EUR",
"BRENT_CRUDE": "USD"
}
}

Tip: Define change_pct as number with a clear description indicating units (percentage points, not basis points). This clarity avoids surprises in BI tools that expect 0–100 vs 0–1 scaling.

Electricity-specialized Endpoints

Electricity markets add time-of-day complexity: intraday resolution, auctions, and grid intensity. Energy API provides electricity‑native endpoints that keep the contract stable, whether you’re integrating Spain’s OMIE day‑ahead or Germany’s EPEX results.

7) Latest Electricity — GET /electricity/latest

Fetch latest prices for all electricity symbols, optionally filtered by country. Use to build regional dashboards or to compare day‑ahead results across bidding zones.

curl -G https://energy-api.com/api/v1/electricity/latest \
--data-urlencode "country=ES" \
--data-urlencode "api_key=YOUR_API_KEY"

Response includes a map of electricity symbols to values, plus currencies. Filter by ISO country codes to match UI segments.

8) Intraday Electricity Curve — GET /electricity/hourly

Retrieve a full intraday curve (15‑minute or hourly depending on the source) for one electricity symbol on a given date. This powers bill simulators, load matching, and time‑of‑use optimization.

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"

Example JSON response:

{
"success": true,
"symbol": "OMIE_ES_DA",
"date": "2026-06-11",
"granularity": "hourly",
"points": [
{ "time": "00:00", "value": 62.10 },
{ "time": "01:00", "value": 58.30 },
{ "time": "02:00", "value": 55.80 }
],
"currency": "EUR",
"timezone": "Europe/Madrid"
}

Field highlights:

  • granularity: hourly or 15min per source. Use this to resample or align with customer usage profiles.
  • timezone: Crucial for settlement alignment and correct display in UI; do not assume UTC for electricity curves.
  • points: time is local market time; value is price in currency. Model time as string with a strict pattern: ^([01]\d|2[0-3]):[0-5]\d$.

9) Spanish PVPC — GET /electricity/pvpc

Retrieve hourly PVPC retail reference prices for Spain. Perfect for retail bill calculators and consumer advisory apps.

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

The response mirrors the intraday curve shape but is specific to PVPC. Use this endpoint to overlay wholesale vs retail references in UI.

14) Day-Ahead Forecast — GET /forecast

This returns the next published day‑ahead price for auction‑sourced electricity symbols. It’s deterministic (published auction results), not a predictive model. Querying non‑auction symbols returns 404 by contract.

curl -G https://energy-api.com/api/v1/forecast \
--data-urlencode "symbol=EPEX_DE_DA" \
--data-urlencode "api_key=YOUR_API_KEY"

Use this to pre‑load UIs with “next day” views and to send timely notifications when auction results land, without polling a dozen upstream portals.

Category Shortcuts and Domain Utilities

Energy API offers convenient category endpoints that bundle common symbol sets in a single call, plus utilities for cost estimation, grid carbon intensity, and provider status observability.

10) Gas Latest — GET /gas/latest

Fetch TTF_GAS (EU) and HENRY_HUB (US) together. Ideal for dashboards that compare EU vs US gas benchmarks side‑by‑side.

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

11) Emissions Latest — GET /emissions/latest

Get EUA_CO2 in one call. Useful to compute marginal emissions costs or to overlay carbon pricing on power portfolio views.

curl -G https://energy-api.com/api/v1/emissions/latest \
--data-urlencode "api_key=YOUR_API_KEY"

12) Coal Latest — GET /coal/latest

Retrieve COAL_ROTTERDAM (API2) and COAL_NEWCASTLE. Include this in cross‑fuel stack analyses and hedging dashboards.

curl -G https://energy-api.com/api/v1/coal/latest \
--data-urlencode "api_key=YOUR_API_KEY"

13) Carbon Intensity — GET /carbon-intensity

Grid carbon intensity (gCO2eq/kWh) by country. Map this to ESG dashboards, carbon‑aware scheduling, or Scope 2 reporting workflows.

curl -G https://energy-api.com/api/v1/carbon-intensity \
--data-urlencode "country=DE" \
--data-urlencode "api_key=YOUR_API_KEY"

Example JSON response:

{
"success": true,
"country": "DE",
"date": "2026-06-11",
"intensity": 382,
"unit": "gCO2eq/kWh",
"source": "ENTSO-E/Ember"
}

Design note: Unit is explicit; do not infer. If you store intensity alongside prices, keep units in the record to avoid misunderstandings in cross‑team contexts.

15) Cost Estimate — POST /cost-estimate

A simple monthly wholesale electricity cost estimator: latest price × kWh/month. This is a practical UX tool when users provide monthly consumption. It excludes taxes, network charges, and hourly usage profiles, so label results accordingly.

curl -X POST https://energy-api.com/api/v1/cost-estimate \
-H "Content-Type: application/json" \
-d '{
"symbol": "OMIE_ES_DA",
"kwh_per_month": 350
}'

Expect a compact JSON with the symbol, input kWh, applied price, currency, and computed estimate. If both symbol and country are omitted, or kwh_per_month is missing, the server returns 422.

16) Provider Status — GET /status

Operational visibility matters in energy pipelines. Use /status to display the last fetch status per data provider and to decide whether to degrade gracefully or fall back to cached data in your application.

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

Example JSON response:

{
"success": true,
"providers": [
{ "name": "OMIE", "last_fetch": "2026-06-11T12:05:00Z", "status": "ok", "message": "Auction results updated." },
{ "name": "ENTSO-E", "last_fetch": "2026-06-11T12:02:10Z", "status": "ok", "message": "Intraday data synchronized." },
{ "name": "EIA", "last_fetch": "2026-06-10T21:40:02Z", "status": "ok", "message": "" },
{ "name": "FRED", "last_fetch": "2026-06-11T09:00:00Z", "status": "delayed", "message": "Source latency detected; retrying." },
{ "name": "ESIOS", "last_fetch": "2026-06-11T11:59:59Z", "status": "ok", "message": "" }
]
}

Use cases:

  • Health checks: Show green/yellow/red badges in your admin panel.
  • Circuit breakers: If a provider shows delayed, switch to last‑known‑good cache for reads and surface a UI banner.

End-to-End Error Handling and Resiliency

Contracts are only as good as their failure modes. Energy API returns structured error responses enabling deterministic behavior in clients. Build your policy once and reuse everywhere.

  • 401: Missing or invalid credentials. Surface a single, non‑verbose message to end users; log details server‑side only.
  • 404: No data for given symbols or date. Downgrade gracefully in UI (“No data for 2025‑12‑25; showing previous business day”) or in code by checking historical fallback logic first.
  • 422: Validation error—missing parameters, invalid format (e.g., malformed YYYY‑MM‑DD), unsupported symbol. Tie this to form validation and schema‑driven clients to prevent round trips.
  • 429: Rate limit exceeded. Implement exponential backoff with jitter; in batch jobs, spread symbol queries across windows and leverage multi‑symbol endpoints to reduce call count.

Error response shape:

{
"success": false,
"error": "Human-readable message."
}

Observability and reliability practices:

  • Client retries: Exponential backoff for transient network errors; no retries for 4xx except 429 with a cap and respect for Retry‑After if present.
  • Health gates: Consult /status before heavy workloads. If a provider is delayed, switch to cached aggregates and mark outputs “stale” in UI copy.
  • Timeout budgets: Keep endpoint‑specific timeouts lower for intraday electricity (users feel lag quickly) and higher for broad historical pulls.
  • Idempotency: Reads are idempotent by definition; for POST /cost-estimate, guard client‑side to avoid duplicate UI actions even though the computation is pure.

Versioning, Deprecation, and Change Management

Your OpenAPI file is your living contract. Treat it with semantic rigor to keep downstream services stable across upgrades.

  • Semantic versioning: Keep an OpenAPI x-api-version like 1.12.3 that increments on additive changes (new optional fields, new symbols). Breaking changes trigger a new path prefix (/api/v2).
  • Explicit deprecations: Annotate deprecated fields with a description that includes the removal date. Provide examples for both old and new patterns side‑by‑side for at least one release cycle.
  • Example‑driven communication: Include a docs page that shows “then vs now” for any field that changes semantics (e.g., units, timezones, rounding). In contract files, ship examples that fail if clients assume prior behavior.
  • Consumer‑driven verification: Use Pact (or equivalent) to ensure your applications only rely on fields you control. When Energy API adds a field, your pact won’t fail; when your client expects a field that is later deprecated, you’ll get a failing test ahead of rollout.

Mocking for safety:

  • Spin up a spec‑backed mock server that returns curated examples for /latest, /timeseries, /electricity/hourly, and /ohlc. Write integration tests that assert graph shapes, not just status codes.
  • Fuzz test query parameters: Use a tool that exercises ranges (invalid dates, inverted start/end, duplicate symbols) to ensure your request builders never produce invalid 422s in production.

Practical Client Examples

Here are minimal client snippets you can adapt. They’re intentionally thin wrappers—generate robust SDKs from the OpenAPI once your contract is stable.

JavaScript (fetch): Latest mixed symbols

async function getLatest(symbolsCsv) {
const url = new URL("https://energy-api.com/api/v1/latest");
url.searchParams.set("symbols", symbolsCsv);
url.searchParams.set("api_key", "YOUR_API_KEY");

const res = await fetch(url.toString(), { method: "GET" });
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(`Energy API error: ${res.status} ${err.error || res.statusText}`);
}
const data = await res.json();
// Example: attach currency badges for UI
return Object.entries(data.rates).map(([symbol, value]) => ({
symbol,
value,
currency: data.currencies[symbol],
asOf: data.dates[symbol] || data.date
}));
}

getLatest("BRENT_CRUDE,TTF_GAS,EUA_CO2").then(console.log).catch(console.error);

Python: Timeseries with simple moving average

import requests
from statistics import mean

def get_timeseries(symbols, start, end):
url = "https://energy-api.com/api/v1/timeseries"
params = {"symbols": ",".join(symbols), "start": start, "end": end, "api_key": "YOUR_API_KEY"}
r = requests.get(url, params=params, timeout=30)
r.raise_for_status()
return r.json()

def sma(values, window):
out = []
for i in range(len(values)):
if i + 1 < window:
out.append(None)
else:
out.append(round(mean(values[i+1-window:i+1]), 4))
return out

data = get_timeseries(["BRENT_CRUDE", "TTF_GAS"], "2025-01-01", "2025-03-31")
brent_dates = sorted(data["rates"]["BRENT_CRUDE"].keys())
brent_values = [data["rates"]["BRENT_CRUDE"][d] for d in brent_dates]
brent_sma_10 = sma(brent_values, 10)

print(list(zip(brent_dates, brent_values, brent_sma_10))[:15])

Real‑World Use Cases

Price alerting and cross‑commodity views

Traders and analysts need to see moves across fuel stacks at once. Use GET /latest with mixed symbols (e.g., TTF_GAS, BRENT_CRUDE, EUA_CO2) to trigger alerts when thresholds are crossed or spreads widen. The consistent schema and currency map let you compute normalized spreads or percentage changes reliably.

ESG dashboard with grid intensity overlays

Sustainability and ESG teams combine prices with carbon intensity. Use GET /carbon-intensity to display gCO2eq/kWh by country and overlay costs via /electricity/hourly for time‑of‑use optimization. Integrate /emissions/latest for EUA_CO2 to track the implied carbon cost alongside wholesale electricity prices in one UX.

Customer cost calculator and bill education

Energy retail and fintech apps can demystify bills by showing how wholesale trends affect monthly costs. Use POST /cost-estimate with symbol=OMIE_ES_DA and user‑provided kWh/month to generate a transparent estimate. Enhance this with GET /electricity/pvpc to compare retail reference prices and explain divergences.

All Available Endpoints at a Glance

  • GET /symbols — Discover active symbols, metadata, frequency, and descriptions; filter by category/provider.
  • GET /latest — Most recent price for one or more symbols; supports cross‑commodity queries.
  • GET /historical — Prices for all symbols on a specific past date; auto‑fallback to previous business day if needed.
  • GET /timeseries — Historical series by date range; per‑symbol frequencies and currencies included.
  • GET /fluctuation — Start/end, absolute change, and percentage change over a period per symbol.
  • GET /ohlc — Weekly, monthly, or quarterly OHLC candles with data_points per period for QA.
  • GET /electricity/latest — Latest electricity prices, filterable by country.
  • GET /electricity/hourly — Full intraday curve (15‑min or hourly) for an electricity symbol and date.
  • GET /electricity/pvpc — Hourly Spanish PVPC retail reference prices by date.
  • GET /gas/latest — TTF_GAS and HENRY_HUB in one call.
  • GET /emissions/latest — EUA_CO2 in one call.
  • GET /coal/latest — COAL_ROTTERDAM and COAL_NEWCASTLE in one call.
  • GET /carbon-intensity — Grid carbon intensity (gCO2eq/kWh) by country.
  • GET /forecast — Next published day‑ahead price for auction‑sourced electricity symbols; 404 otherwise.
  • POST /cost-estimate — Compute monthly wholesale electricity cost from a symbol or country and kWh/month.
  • GET /status — Last fetch status per data provider for operational visibility.

Interpreting Responses and Using Them Safely

A few practical patterns improve correctness and UX:

  • Currencies: Always read currencies per symbol rather than inferring by category; use explicit currency formatting in UI.
  • Dates and time zones: Treat date in /latest as a response context and use dates[symbol] for symbol‑specific staleness. For intraday electricity, use timezone from the payload for charts and schedule alignment.
  • Sparse data: Holidays or auctions may reduce point counts. Use data_points in /ohlc and check empty hours in /electricity/hourly. Visualize gaps intentionally (dashed lines or “no auction” badges).
  • Mixed calls: Prefer multi‑symbol queries for atomic snapshots. This yields consistent as‑of contexts and fewer round trips.
  • Validation: In your OpenAPI, constrain parameters (pattern for symbols CSV, format: date for date fields, enum for period). Validate on the client before calling to reduce 422s.

FAQ

How often does the TTF gas price update?

TTF_GAS is published on a daily cadence from its source and surfaces via GET /latest and GET /timeseries. For intraday alerting, pair daily series with GET /fluctuation windows or use provider /status to detect lags and adjust refresh cycles.

Can I get historical energy prices going back 5 years?

Yes—use GET /timeseries with start and end to pull multi‑year windows for symbols like BRENT_CRUDE, TTF_GAS, EUA_CO2, and more. If a symbol’s earliest available date is later than your requested start, the series will begin at the first available date.

Does the API support multiple commodities in one call?

Yes—mix categories like gas, oil, and carbon in a single GET /latest or GET /historical request (e.g., BRENT_CRUDE, TTF_GAS, EUA_CO2). You will also receive per‑symbol currencies and publication dates for accurate downstream handling.

How should I handle non‑publishing days and holidays?

GET /historical returns the most recent value before the given date if no data was published on that day. For timeseries, simply render gaps as missing keys—do not synthesize values unless you explicitly resample using your own business rules.

What’s the best way to test my integration without live data?

Adopt a contract‑first workflow: generate mock servers from your OpenAPI spec and load example responses for /latest, /timeseries, /electricity/hourly, and /ohlc. Combine this with consumer‑driven contracts to ensure your client assumptions remain valid as new symbols and fields are added.

Conclusion + CTA

Energy data integration is a contract problem first, a code problem second. By modeling your needs contract‑first with a well‑structured OpenAPI and using a unified data surface, you remove the sharp edges of mixing OMIE, ENTSO‑E, EIA/FRED, ESIOS, and other sources. The result is faster delivery, cleaner UIs, more reliable analytics pipelines, and fewer production surprises when calendars or formats change.

With Energy API, you get a normalized schema across electricity, gas, oil, coal, carbon allowances, and grid carbon intensity—plus breadth of endpoints that map to real business workflows: snapshots, ranges, intraday curves, candles, forecasts, cost estimates, and provider health. Design your integration once, codify it in OpenAPI, validate with mocks and CDCs, and ship with confidence.

If you’re ready to replace ad‑hoc scrapers and CSV wrangling with one consistent contract, start building with the endpoints above and wire them into your CI from day one. Try Energy API for free and use the contract‑first patterns in this post to get from idea to production‑ready energy data in record time.

Ready to get started?

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

Get API Key

Related posts