Operationalizing Anomaly Detection for Grid Operations: Using Energy API to Catch Metering and Telemetry Irregularities
Grid operations live and die by data fidelity. If your metering or telemetry feeds drift, duplicate, stall, or spike at the wrong moment, automated dispatch breaks, loss factors go sideways, and balancing costs quietly balloon. The paradox is familiar to every SCADA, EMS/DMS, and trading-ops engineer: we must detect anomalies early enough to act, but with enough certainty to avoid generating alert fatigue. Doing this well requires robust baselines that reflect not just your meters, but the market context that explains when “weird” is actually normal — for example, a day-ahead price shock, an intraday shape inversion, or an emissions shift during a low-wind event.
In this post, we’ll operationalize anomaly detection for grid operations using a unified energy data surface. Instead of piecing together spot prices from one portal, intraday curves from another, and grid carbon intensity from a third, we’ll rely on a single normalized interface from Energy API. We’ll show how to establish baseline curves, detect outliers in meter/telemetry series, correlate those outliers with market movements, and automatically escalate issues that can’t be explained by market context. You’ll see concrete cURL, Python, and JavaScript examples that you can drop into pipelines, alerting systems, and dashboards.
You don’t need to maintain ETL scripts for OMIE, ENTSO-E, ESIOS, or EIA. You don’t need to reconcile symbol naming schemes, timezone edges, or publication calendars. With Energy API, you request electricity curves, gas/oil/coal/carbon reference prices, and grid carbon intensity — all sharing a consistent JSON schema — and you get exactly what you need to make anomaly flags both earlier and smarter.
Why Energy API
Operational anomaly detection hinges on not just “is this value odd?” but “is this value odd given current wholesale conditions?” Energy API brings multiple commodity categories into one normalized surface so your logic is simpler and your signal quality is higher. Here are the differentiators that matter when you’re on the hook for production reliability:
- One normalized REST interface for electricity, gas, oil, coal, carbon allowances, and grid carbon intensity. That means a single set of request/response patterns you can reuse across baselining and diagnostics (e.g., combine OMIE day-ahead with TTF gas and EUA carbon in one call), dramatically reducing code paths and chances for integration bugs.
- A consistent JSON schema with explicit fields for rates, dates, and currencies. You avoid case-by-case parsing and silently broken assumptions (like daily vs hourly). Most anomaly logic needs values aligned to a date index; Energy API structures responses so windowing, differencing, and resampling are straightforward.
- Intraday electricity curves where sources publish them (15-minute or hourly). Anomaly detection against meters requires comparing shape against reliable reference curves. Pull the entire day curve for a specific symbol (e.g., OMIE_ES_DA or EPEX_DE_DA) and compare hour-by-hour or quarter-hour-by-quarter-hour.
- Broad coverage with credible sources (OMIE, ENTSO-E, ESIOS, EIA, FRED, Ember). Your pipeline benefits from redundancy and high-quality upstreams, but you still ship against a single, stable API. Less surface area, fewer brittle scripts, and faster issue triage when something upstream changes.
The net benefit: instead of writing ETL, calendars, symbol normalization, and per-provider backfill logic, you write anomaly logic. Energy API supplies the ground truth you need to sort genuine telemetry defects (sensor drift, comms freeze, unit scaling errors) from market-driven shape changes.
Quick Start
Energy API exposes a base URL and a straightforward query pattern. Below we’ll fetch the latest values for three cross-commodity symbols in a single call — ideal for capturing a reference market snapshot to accompany every anomaly flag you generate.
Base URL: https://energy-api.com/api/v1
Request the most recent values for Brent crude, TTF gas, and EU ETS carbon allowances:
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 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 you’ll use:
- date: Overall reporting date for the snapshot. Store this next to your anomaly event to preserve temporal context.
- rates: Symbol-to-value map. You can compute percentile ranks or z-scores for contextual correlation (e.g., your telemetry anomaly coincides with a large TTF move).
- dates: Per-symbol publication dates. Useful when commodities publish on different schedules; align your baselines accordingly.
- currencies: Per-symbol currency code. If you aggregate to a portfolio risk view, convert or annotate units consistently.
Core Endpoints
Anomaly detection for grid operations blends intraday shapes, day-ahead references, historical backfills, and provider health. Below are key endpoints and how to use them in practice for building robust detection and triage pipelines.
1) GET /electricity/hourly — Intraday curve for shape-aware anomaly detection
Path: /electricity/hourly
Purpose: Retrieve the full 15-minute or hourly curve for a specific electricity symbol and date. This is your baseline for shape comparison and residual analysis against meter or SCADA telemetry. If a meter’s quarter-hour profile deviates materially from the published curve — and there’s no corresponding market, weather, or outage context — you likely have a data quality issue or a field device problem.
Key params:
- symbol (required): e.g., OMIE_ES_DA for Spain day-ahead, EPEX_DE_DA for Germany.
- date (required): YYYY-MM-DD for the curve date.
Example request:
curl -G "https://energy-api.com/api/v1/electricity/hourly" \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "date=2026-06-12" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"symbol": "OMIE_ES_DA",
"date": "2026-06-12",
"frequency": "hourly",
"unit": "EUR/MWh",
"curve": [
{"time": "2026-06-12T00:00:00+02:00", "value": 62.14},
{"time": "2026-06-12T01:00:00+02:00", "value": 58.92},
{"time": "2026-06-12T02:00:00+02:00", "value": 55.01},
{"time": "2026-06-12T03:00:00+02:00", "value": 53.77},
{"time": "2026-06-12T04:00:00+02:00", "value": 52.30},
{"time": "2026-06-12T05:00:00+02:00", "value": 54.10},
{"time": "2026-06-12T06:00:00+02:00", "value": 60.42},
{"time": "2026-06-12T07:00:00+02:00", "value": 68.98},
{"time": "2026-06-12T08:00:00+02:00", "value": 73.15},
{"time": "2026-06-12T09:00:00+02:00", "value": 70.22},
{"time": "2026-06-12T10:00:00+02:00", "value": 66.40},
{"time": "2026-06-12T11:00:00+02:00", "value": 64.85},
{"time": "2026-06-12T12:00:00+02:00", "value": 63.70},
{"time": "2026-06-12T13:00:00+02:00", "value": 62.95},
{"time": "2026-06-12T14:00:00+02:00", "value": 61.83},
{"time": "2026-06-12T15:00:00+02:00", "value": 60.11},
{"time": "2026-06-12T16:00:00+02:00", "value": 58.44},
{"time": "2026-06-12T17:00:00+02:00", "value": 59.77},
{"time": "2026-06-12T18:00:00+02:00", "value": 62.21},
{"time": "2026-06-12T19:00:00+02:00", "value": 64.10},
{"time": "2026-06-12T20:00:00+02:00", "value": 66.55},
{"time": "2026-06-12T21:00:00+02:00", "value": 69.40},
{"time": "2026-06-12T22:00:00+02:00", "value": 65.92},
{"time": "2026-06-12T23:00:00+02:00", "value": 61.30}
]
}
Field notes:
- curve: Time-stamped values in local market timezone. Use this to compute error bands vs. your metering series (e.g., absolute percentage error per interval or a rolling z-score).
- frequency: hourly or 15min depending on the market. Your anomaly windows should match this resolution for clean comparisons.
- unit: Store along with your internal series metadata to avoid unit mismatches in downstream models.
2) GET /timeseries — Build robust baselines and seasonality models
Path: /timeseries
Purpose: Retrieve historical series for one or more symbols across a date range. Baselines and anomaly thresholds improve when you include seasonality (weekly patterns, holiday effects) and structural breaks (fuel price regimes, emissions policy). With /timeseries, you can combine electricity, gas, and carbon in one request and feed a multivariate model or simply compute percentile bands.
Key params:
- start, end (required): Range in YYYY-MM-DD.
- symbols (required): Comma-separated list. For anomaly context, combine OMIE_ES_DA, TTF_GAS, and EUA_CO2.
- base (optional): Currency filter; often unnecessary if you’re storing native currencies.
Example request:
curl -G https://energy-api.com/api/v1/timeseries \
--data-urlencode "start=2026-04-01" \
--data-urlencode "end=2026-06-11" \
--data-urlencode "symbols=OMIE_ES_DA,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"base": "MIXED",
"start_date": "2026-04-01",
"end_date": "2026-06-11",
"rates": {
"OMIE_ES_DA": {
"2026-04-01": 61.15,
"2026-04-02": 58.44
},
"TTF_GAS": {
"2026-04-01": 33.25,
"2026-04-02": 33.10
},
"EUA_CO2": {
"2026-04-01": 63.80,
"2026-04-02": 64.20
}
},
"frequencies": {
"OMIE_ES_DA": "daily",
"TTF_GAS": "daily",
"EUA_CO2": "daily"
},
"currencies": {
"OMIE_ES_DA": "EUR",
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}
Field notes:
- rates: A two-level mapping symbol -> date -> value. This structure is perfect for building a DataFrame with columns per symbol and aligning dates for multivariate regressions or correlation checks.
- frequencies: Confirms cadence to avoid accidental resampling assumptions. If you join with sub-hourly telemetry, use a rolling daily join keyed by operating day.
- base/currencies: Explicit currency management enables you to model spread impacts (e.g., gas vs. power) without silent conversion issues.
3) GET /electricity/latest — Snapshot for NOC dashboards and guardrails
Path: /electricity/latest
Purpose: Pull the latest published value for all electricity symbols (optionally filtered by country). Use it for dashboards, shift handover notes, or guardrails that prevent false positives when the whole market has moved.
Key params:
- country (optional): ISO-2 filter. Example: ES, DE.
- base (optional)
Example request (filter Spain for concise output):
curl -G "https://energy-api.com/api/v1/electricity/latest" \
--data-urlencode "country=ES" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"date": "2026-06-11",
"symbols": {
"OMIE_ES_DA": {
"value": 69.75,
"currency": "EUR",
"frequency": "daily",
"published_at": "2026-06-11T12:10:00+02:00"
},
"PVPC_ES_2TD": {
"value": 0.147,
"currency": "EUR/kWh",
"frequency": "hourly",
"published_at": "2026-06-11T23:00:00+02:00"
}
}
}
Field notes:
- symbols: A symbol-indexed object with value and metadata. This lets you poll once and refresh multiple dashboard widgets.
- published_at: Useful to confirm staleness; if your internal price is newer than the official publication for a given day, escalate to your data governance channel.
4) GET /forecast — Day-ahead results for auction-sourced markets
Path: /forecast
Purpose: Look up the next published day-ahead price for auction markets without scraping auction portals. Anomaly detectors can use this to precompute expected shape change likelihood or to annotate next-day alarms with known price regimes.
Key params:
- symbol (required): An auction-sourced electricity symbol. Non-auction symbols return 404.
Example request:
curl -G "https://energy-api.com/api/v1/forecast" \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"symbol": "OMIE_ES_DA",
"auction_date": "2026-06-12",
"delivery_date": "2026-06-13",
"unit": "EUR/MWh",
"value": 66.42,
"curve": [
{"hour": "00:00", "value": 58.70},
{"hour": "01:00", "value": 56.95},
{"hour": "02:00", "value": 55.10}
]
}
Field notes:
- delivery_date: Tomorrow’s operating day for the published auction. Use this for next-day alarms or staffing plans.
- curve: When available, you get the hourly shape straight from the auction results. Compare this to your expected load shape to estimate anomaly risk windows.
5) GET /fluctuation — Volatility-aware anomaly thresholds
Path: /fluctuation
Purpose: Compute start/end, absolute and percentage changes over a period. Use it to modulate anomaly thresholds dynamically. For example, when TTF gas shifts more than 10% over a week, price-driven shape noise increases, so your telemetry anomaly detector should widen acceptable residual bands to avoid false alarms.
Key params:
- start, end (required): YYYY-MM-DD.
- symbols (required): One or more symbols across categories.
Example request:
curl -G https://energy-api.com/api/v1/fluctuation \
--data-urlencode "start=2026-05-15" \
--data-urlencode "end=2026-06-11" \
--data-urlencode "symbols=TTF_GAS,OMIE_ES_DA,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"start": "2026-05-15",
"end": "2026-06-11",
"results": {
"TTF_GAS": {
"start_value": 34.10,
"end_value": 38.15,
"change": 4.05,
"change_pct": 11.88
},
"OMIE_ES_DA": {
"start_value": 62.55,
"end_value": 69.75,
"change": 7.20,
"change_pct": 11.50
},
"EUA_CO2": {
"start_value": 65.00,
"end_value": 67.40,
"change": 2.40,
"change_pct": 3.69
}
}
}
Field notes:
- results: Per-symbol change metrics. You can drive adaptive thresholds by mapping change_pct to an inflation factor on your residual tolerances.
6) GET /status — Detect upstream delays before they become false positives
Path: /status
Purpose: Returns last fetch status per data provider. If a provider is delayed, you may see stale market values that should not trigger telemetry anomalies. Wire this into your health checks and pause certain alerts when upstream data is behind schedule.
Example request:
curl -G https://energy-api.com/api/v1/status \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"providers": [
{
"name": "OMIE",
"last_success_at": "2026-06-11T12:12:05+02:00",
"status": "ok"
},
{
"name": "ENTSO-E",
"last_success_at": "2026-06-11T12:05:01+02:00",
"status": "ok"
},
{
"name": "EIA",
"last_success_at": "2026-06-10T21:01:45Z",
"status": "ok"
}
]
}
Field notes:
- status: ok or degraded. On degraded, annotate alerts: “Market source delay detected — defer reconciliation.”
- last_success_at: Helps you set SLA-based freshness alarms distinct from data anomalies in your own meters.
Designing an Anomaly Detection Workflow with Energy API
Operationalizing anomaly detection means codifying a repeatable flow that distinguishes meter or telemetry irregularities from legitimate market-driven variability. Below is a practical architecture that dozens of grid teams adapt:
-
Baseline acquisition:
- Daily: Call /timeseries for OMIE_ES_DA, TTF_GAS, EUA_CO2 for the trailing 60–180 days to maintain rolling baselines.
- Intraday: Call /electricity/hourly for the operating day for your reference market to obtain the expected shape.
-
Context snapshot:
- At anomaly time: Call /latest with a cross-commodity basket (electricity day-ahead, gas, carbon) to capture current regime.
- Volatility regime: Call /fluctuation over the past 2–4 weeks to parameterize thresholds.
-
Health gates:
- Check /status before raising alerts to avoid blaming your meters for what’s actually a late market publication.
-
Residual computation:
- Align meter intervals to /electricity/hourly curve timestamps; compute interval residuals (meter_value vs price-derived expectation or forecasted load).
- Use rolling z-scores and MAD-based thresholds scaled by recent /fluctuation change_pct and by historical percentiles from /timeseries.
-
Triage and enrichment:
- If residual exceeds a hard cap and contextual signals (latest, fluctuation, carbon intensity) do not explain it, classify as telemetry anomaly.
- Include the JSON snapshots from /latest and /status in the alert payload so operators can adjudicate quickly.
This pattern reduces false positives and shows operators “why” an alarm fired alongside supporting evidence. Because Energy API normalizes everything, your joins are simple, and your code reads like business logic rather than plumbing.
Symbol Discovery and Portfolio Hygiene
Before you build rules at scale, enumerate available symbols and metadata. Portfolio hygiene matters: choose the right reference curves, currencies, and geographies that match your metering footprint and hedging books.
7) GET /symbols — Discover and standardize references
Path: /symbols
Purpose: List active symbols, including category, country, currency, and frequency. Use it to programmatically generate configuration for your anomaly jobs (e.g., “Spain meters compare against OMIE_ES_DA hourly; Germany compares against EPEX_DE_DA”).
Example request (gas category for brevity):
curl -G https://energy-api.com/api/v1/symbols \
--data-urlencode "category=gas" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response (truncated for brevity):
{
"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 Spot",
"category": "gas",
"country_code": "US",
"currency_code": "USD",
"frequency": "daily",
"description": "US benchmark natural gas spot price."
}
]
}
With this, you auto-generate drop-downs in dashboards and avoid hard-coding symbols across services. Consistent metadata also helps route events to the right regional ops teams.
Cross-Commodity Context: Why Your Anomaly Flags Need It
Single-source anomaly detectors are brittle. A clean operations story compares your meter or SCADA series to expected grid behavior and overlays cross-commodity signals that materially affect price and shape:
- Gas price surge (TTF_GAS) often lifts thermal dispatch costs and reshapes intraday price spreads. Treat spikes as context, not necessarily anomalies.
- Carbon allowance shifts (EUA_CO2) can tighten or relax marginal cost for thermal fleets; include this in your daily narrative to ops.
- Carbon intensity swings (CARBON_INT_* symbols) reflect renewable availability; unexpected emissions intensity may imply renewables underperforming vs forecast, contributing to shape shifts.
8) GET /latest with mixed symbols — A single market snapshot for alerts
We saw the /latest example earlier with BRENT_CRUDE, TTF_GAS, and EUA_CO2. The key takeaway is you can request multiple commodities at once, add the JSON blob to your anomaly record, and later explain “why” your model raised or suppressed a flag. This is a unique productivity booster: fewer calls, consistent schema, and instantly usable supporting evidence for NOC review.
9) GET /carbon-intensity — Emissions context for grid shape interpretation
Path: /carbon-intensity
Purpose: Retrieve current or recent grid carbon intensity by country (gCO2eq/kWh). High intensity when wind/solar should be strong suggests forecast errors or outages, which can explain price shape deviations. Use it to avoid misclassifying market-driven effects as telemetry faults.
Key params:
- country (required): ISO-2 code (e.g., DE, ES, FR).
- base (optional)
Example request:
curl -G "https://energy-api.com/api/v1/carbon-intensity" \
--data-urlencode "country=DE" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"country": "DE",
"unit": "gCO2eq/kWh",
"date": "2026-06-11",
"value": 305,
"source": "Ember/ENTSO-E"
}
Use value directly in your triage note: “High carbon intensity suggests low renewables; widen residual bands during morning ramp.”
10) GET /historical — Backfill gap days without breaking your detectors
Path: /historical
Purpose: Retrieve values for a specific date with automatic backfill to the prior publishing day if it’s a non-publishing day. Perfect for regenerating feature stores after outages or correcting for late-arriving data.
Example request:
curl -G https://energy-api.com/api/v1/historical \
--data-urlencode "date=2026-05-01" \
--data-urlencode "symbols=OMIE_ES_DA,TTF_GAS" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"date": "2026-05-01",
"base": "MIXED",
"rates": {
"OMIE_ES_DA": 64.40,
"TTF_GAS": 34.75
},
"currencies": {
"OMIE_ES_DA": "EUR",
"TTF_GAS": "EUR"
}
}
If the specified date falls on a weekend or holiday with no new publication, Energy API returns the most recent prior value, keeping your anomaly pipeline consistent and avoiding gaps that often cause spurious alerts.
End-to-End Examples: Implementation Snippets
Python: Compute hourly residuals against OMIE day-ahead curve
import requests
import pandas as pd
from datetime import datetime, timezone
BASE = "https://energy-api.com/api/v1"
API_KEY = "YOUR_API_KEY"
def fetch_curve(symbol: str, date: str) -> pd.Series:
r = requests.get(f"{BASE}/electricity/hourly", params={
"symbol": symbol,
"date": date,
"api_key": API_KEY
}, timeout=20)
r.raise_for_status()
data = r.json()
curve = pd.Series(
{pd.to_datetime(p["time"]): p["value"] for p in data["curve"]}
).sort_index()
return curve
# Example telemetry: hourly meter series already aligned to local time
def compute_residuals(meter: pd.Series, price_curve: pd.Series) -> pd.Series:
aligned = meter.reindex(price_curve.index).interpolate(limit_direction="both")
return (aligned - aligned.mean()) - (price_curve - price_curve.mean())
# Usage
operating_day = "2026-06-12"
price_curve = fetch_curve("OMIE_ES_DA", operating_day)
# dummy meter values for illustration: normally from SCADA/EMS
meter = price_curve * 0.01 # e.g., kWh proxy scaled to price for testing
residuals = compute_residuals(meter, price_curve)
z = (residuals - residuals.mean()) / residuals.std(ddof=1)
flags = z.abs() > 3.0 # simple threshold; you can modulate via /fluctuation
print("Flagged intervals:", list(flags[flags].index))
Node.js: Capture a cross-commodity snapshot for alert enrichment
import fetch from "node-fetch";
const BASE = "https://energy-api.com/api/v1";
const API_KEY = "YOUR_API_KEY";
async function marketSnapshot() {
const u = new URL(`${BASE}/latest`);
u.searchParams.set("symbols", "OMIE_ES_DA,TTF_GAS,EUA_CO2");
u.searchParams.set("api_key", API_KEY);
const r = await fetch(u.toString(), { timeout: 20000 });
if (!r.ok) throw new Error(`HTTP ${r.status}`);
const data = await r.json();
return {
ts: new Date().toISOString(),
rates: data.rates,
currencies: data.currencies,
dates: data.dates
};
}
marketSnapshot().then(console.log).catch(console.error);
Real-World Use Cases
1) Meter-to-curve health monitor for distribution utilities
A utility compares feeder- or substation-level hourly energy against the /electricity/hourly curve for its market reference (e.g., OMIE_ES_DA). Residuals are scaled by a volatility factor derived from /fluctuation(TTF_GAS, OMIE_ES_DA) and suppressed when /status indicates a provider delay. Alerts are enriched with /latest snapshots so the NOC can see whether a spike aligns with broader market behavior.
2) Renewable asset telemetry sanity checks for IPPs
An IPP operating wind and solar assets uses /timeseries(EUA_CO2, CARBON_INT_DE) to detect periods where carbon intensity suggests curtailment or low renewable output across the grid. When asset telemetry deviates without matching market or emissions signals, the system escalates a turbine-level sensor check. The dispatcher reviews the attached JSON evidence and greenlights corrective maintenance if needed.
3) Trading ops P&L anomaly guardrails
A trading team tracks day-ahead exposures using /forecast for EPEX_DE_DA and correlates P&L outliers with /latest(TTF_GAS, EUA_CO2). If P&L outliers occur with negligible commodity moves and normal emissions intensity, the cause likely lies in position data or an ingestion error. Automated runbooks kick off to reconcile trade legs before market close.
Additional Endpoints Worth Integrating
11) GET /gas/latest — Benchmark gas prices, single call
Gas fuels many marginal units. Calling /gas/latest gives you TTF_GAS and HENRY_HUB in one response, useful for cross-region dashboards that explain shape anomalies in partially hedged portfolios.
12) GET /emissions/latest — EUA allowance snapshot
For EU markets, EUA_CO2 affects thermal costs; include this in every daily briefing and as a feature in your residual models.
13) GET /coal/latest — Coal reference for multi-fuel stacks
In markets where coal still plays a role, the relative fuel economics matter for merit order and expected shapes. Include COAL_ROTTERDAM and COAL_NEWCASTLE where relevant.
14) GET /electricity/pvpc — Spanish PVPC hourly retail reference
PVPC_ES_2TD can be used to sanity check retail billing and detect meter-time offsets or unit scaling errors when customer anomalies surface. Join PVPC hourly values with customer load intervals to detect improbable bills before they go out.
15) GET /ohlc — Regime detection on longer horizons
For volatility regime detection, use /ohlc monthly candles on TTF_GAS, BRENT_CRUDE, or EUA_CO2. Regime tags inform how aggressively to widen or tighten anomaly thresholds in your operational models.
16) POST /cost-estimate — Back-of-the-envelope guardrails
Even though it’s not an anomaly endpoint per se, /cost-estimate provides a quick sanity check for wholesale exposure using latest price × kWh/month. As a guardrail, it helps identify when a meter or billing profile would imply implausible monthly charges before customer-impacting actions occur.
Error Handling, Reliability, and Best Practices
Your anomaly pipeline is only as reliable as its failure modes. Energy API uses clear HTTP status codes and human-readable errors:
- 401 — Missing or invalid api_key
- 404 — No data for the given symbols or date
- 422 — Validation error (missing required param, invalid format)
- 429 — Rate limit exceeded. Implement exponential back-off
Error shape:
{
"success": false,
"error": "Human-readable message."
}
Best practices:
- Idempotent retries: For transient errors (network blips), retry GETs with jittered back-off. For 429, back off progressively and log the event for observability.
- Input validation: Validate date ranges and symbol sets before calling. Use /symbols to drive UIs that prevent invalid inputs.
- Freshness guardrails: Read published_at or per-symbol dates to ensure you’re not using stale references to judge real-time telemetry.
- Time zone discipline: /electricity/hourly times are in local market time. Normalize to your processing zone or store tz-aware timestamps end-to-end.
- Schema evolution resilience: Because the schema is consistent across categories, write parsing that keys off documented properties (e.g., rates, curve, currencies) rather than positional fields.
Field-by-Field Interpretation: Turning JSON into Signals
Here’s how to convert common fields into model-ready features:
- rates (from /latest, /timeseries, /historical): Direct numeric features. Combine with day-of-week and holiday flags to build seasonal priors.
-
curve (from /electricity/hourly, /forecast): Shape features. Compute:
- Ramp rates: diff per interval for morning/evening ramps.
- Peak/off-peak spreads: max(curve) - min(curve).
- Load-shape alignment: correlation between meter intervals and price curve.
- change_pct (from /fluctuation): Volatility regime feature that scales anomaly thresholds dynamically to avoid false positives during turbulent markets.
- currencies: Categorical metadata ensuring apples-to-apples comparisons and correct conversions in aggregated dashboards.
- published_at / dates: Freshness and provenance. Use to tag anomalies that occur before or after official publications to separate “data early/late” vs “genuine meter issue.”
Putting It All Together: A Practical Detection Policy
Below is a concise detection policy that many teams adapt:
-
For each operating day D:
- Fetch OMIE_ES_DA curve via /electricity/hourly(symbol=OMIE_ES_DA, date=D).
- Align your meter intervals to the curve timestamps and compute residuals.
- Calculate an hourly z-score of residuals.
-
Contextual modulation:
- Fetch /fluctuation(start=D-28, end=D, symbols=OMIE_ES_DA,TTF_GAS,EUA_CO2) and inflate the z-score threshold proportionally to the max change_pct across symbols.
- Query /carbon-intensity(country=ES) and widen thresholds during high-intensity windows that correlate with low renewable availability.
-
Health gating:
- Call /status. If provider status is degraded, mark anomalies as “tentative” and defer heavy escalations until status returns to ok.
-
Escalation:
- If any interval exceeds the adaptive threshold and context does not explain the deviation, raise a telemetry anomaly. Attach /latest snapshot to the alert payload.
FAQ
How often does the TTF gas price update?
TTF_GAS is provided as a daily series. You can pull the latest value with /gas/latest or /latest and backfill ranges with /timeseries. Use /fluctuation to quantify changes across any period and modulate anomaly thresholds accordingly.
Can I get historical energy prices going back 5 years?
Use /timeseries with start and end parameters to retrieve long historical windows for supported symbols. For specific dates, /historical returns the value for that day or the most recent value before it if publication didn’t occur on that date. This gives you stable baselines and clean gap handling for model backtests.
Does the API support multiple currencies in one response?
Yes. Responses include a currencies map keyed by symbol. Many calls return a base of MIXED, indicating native units per commodity. Keep these currency codes with your features to avoid conversion errors in multi-commodity dashboards or reports.
Can I get hourly curves for electricity to compare against metered intervals?
Yes. Use /electricity/hourly with a symbol and date to retrieve full hourly or 15-minute curves where available. These curves are the backbone for shape-aware anomaly detection against meters or SCADA intervals.
How do I handle delayed publications or upstream outages?
Call /status to check provider health and last_success_at timestamps. When status is degraded, annotate alerts and adjust logic to prevent false positives driven by stale market references rather than real telemetry issues.
Conclusion + CTA
Great anomaly detection in grid operations is not about catching every spike; it’s about quickly separating “market-normal” from “meter-broken.” That requires a clean, unified view across electricity curves, fuels, and emissions. With Energy API, you stop stitching together scrapers and parsers and start shipping reliable detectors that your operators trust.
By leveraging intraday curves from /electricity/hourly, robust baselines from /timeseries, volatility-aware thresholds from /fluctuation, and provider health from /status, you can build production-grade anomaly detection that minimizes false positives and surfaces the issues that truly need attention. Add cross-commodity snapshots from /latest and emissions context from /carbon-intensity, and you have a complete, defensible signal for operations, trading, and compliance stakeholders.
If you’re ready to turn market context into operational reliability, explore the endpoints and start integrating today. Visit Energy API to learn more, and Try Energy API for free to prototype your anomaly detection pipeline in minutes.
Ready to get started?
Get your API key and start querying energy commodity prices in minutes.
Get API KeyRelated posts
Discover how energy metering API services can streamline data management, enhance utility services, and empowe...
Read more →
Discover how Energy API enhances energy efficiency for utilities by streamlining smart metering and market dat...
Read more →
Unlock the potential of Energy API to streamline grid operations. Discover how smart analytics can enhance you...
Read more →
Discover how Energy API transforms energy storage solutions, enhancing grid flexibility and sustainability. Un...
Read more →
Discover how to leverage Energy API for smart grid analytics, enhancing efficiency and reliability in the ener...
Read more →