Building Event-Driven Energy Apps: Using Webhooks, Streams, and Serverless Functions with Energy API for Real-Time Grid Automation
Energy is becoming event-driven. Grid conditions shift by the minute, intraday curves reprice with every auction, and commodity crosswinds ripple instantly from gas into power and carbon. Yet most developer stacks reading these signals are still batch-based: scrape a portal once a day, dump CSVs into a data lake, and hope downstream jobs keep up. That architecture can’t power alerting, automated hedging, or demand response with the precision modern products require.
This post shows how to build real-time and near-real-time energy applications using an event-driven approach with Energy API. We’ll wire together webhooks, streams, and serverless functions so your apps react to price changes, day-ahead auction results, and grid carbon intensity in minutes—not days. You’ll see how a unified JSON interface for electricity, gas, oil, coal, carbon allowances, and grid carbon intensity unlocks faster iteration than managing an alphabet soup of sources and formats.
Whether you’re shipping a price alerting service for traders, a carbon-aware workload scheduler, or a PVPC cost tracker for retail customers, your core loop is the same: subscribe → detect change → enrich with context → act. With Energy API providing a normalized REST surface across trusted providers like OMIE, ENTSO-E, EIA/FRED, and ESIOS, you can stay focused on building the reactive logic instead of doing ETL janitorial work.
Introduction
Developers face three persistent problems when building energy apps that must respond quickly to market changes:
- Every provider is different: formats, time zones, daylight-saving transitions, symbol names, and publishing schedules all vary. Harmonizing this by hand wastes weeks.
- Intraday and auction data are time-sensitive: delays compound across brittle scrapers, leading to stale signals and missed trades or mispriced offers.
- End users expect automation: alerts, serverless cost adjustments, and carbon-aware scheduling require event-driven plumbing, not nightly jobs.
Energy API collapses those differences behind one normalized JSON schema, spanning 39+ symbols and 16 endpoints that include latest quotes, intraday electricity curves, day-ahead forecasts, historical series, OHLC candles, fluctuation analytics, and provider status. That means you can fetch TTF gas, Brent crude, EU ETS allowances, OMIE day-ahead power, and DE grid carbon intensity in one call and receive a single shape you can drop into your code.
In this guide we’ll:
- Explain why one unified API surface is essential for building reliable, event-driven energy apps.
- Walk through core endpoints you’ll use for change detection, automation triggers, and dashboards.
- Show how to deliver events to clients using webhooks, SSE/WebSocket streams, and serverless functions.
- Provide robust error handling, retries, and health checks for production reliability.
Why Energy API
Consolidation is more than convenience. It’s a developer productivity unlock that reduces latency from “new market event” to “app reacts.” Here are the practical benefits when shipping production systems:
- One normalized REST surface replaces multiple portals and CSVs. You write once to a consistent JSON schema across electricity, gas, oil, coal, carbon allowances, and grid carbon intensity. Fewer adapters means fewer failure modes and less test surface.
- Multi-commodity joins without brittle glue code. Query BRENT_CRUDE, TTF_GAS, EUA_CO2, OMIE_ES_DA, and CARBON_INT_DE in a single call and receive a coherent response keyed by symbol. This makes correlation checks, synthetic indices, and risk flags much easier to compute in real time.
- Intraday curves where sources publish them. For electricity, you can fetch hourly or quarter-hourly price curves with consistent timestamps, enabling precise schedules, alerts, and optimization algorithms for demand response or storage dispatch.
- Deterministic day-ahead lookup. The /forecast endpoint gives you the next published day-ahead price for auction-sourced electricity symbols. No guesswork, just the official results once they land.
Result: you move from “build ETL for three sources before any product work” to “ship an MVP in a day and harden reliability next week.” When combined with webhooks or streaming to propagate updates to clients and partner systems, you can architect robust, low-latency energy features rapidly.
Quick Start
All examples below use the same REST base and a query parameter for authentication. Replace YOUR_API_KEY with your value.
Base URL:
https://energy-api.com/api/v1
First request: get the latest prices for Brent crude, TTF gas, and EU ETS allowances in one call.
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 status for the request.
- date: Anchor date for the response payload.
- rates: Latest numeric price by symbol. Multiple commodities and currencies can appear side-by-side.
- dates: Per-symbol publish date. Useful when sources publish at different times.
- currencies: Per-symbol currency code. Always read this if you aggregate cross-commodity metrics.
Core Endpoints for Event-Driven Energy Apps
Below are the endpoints you’ll most often combine into webhook triggers, serverless workflows, and client streams. We’ll show parameters, cURL snippets, JSON samples, and how to interpret the fields to power automation.
1) Discoverability: GET /symbols
Purpose: enumerate available symbols and their metadata so your system can auto-configure without hardcoding. You might use category filters to discover electricity or gas symbols to subscribe to.
Key params:
- base: currency code filter (optional)
- category: gas | electricity | oil | coal | carbon_intensity (optional)
- provider: e.g., omie | entso-e | eia | fred | esios (optional)
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."
}
]
}
How to use it:
- Drive subscription UIs (let users opt into symbols) and generate internal watchlists automatically.
- Programmatically register webhooks for each discovered symbol and region you support.
- Guardrails: the frequency field indicates expected cadence so you can tune polling intervals and webhook batching logic.
2) Latest values: GET /latest
Purpose: fetch the most recent price for one or more symbols. This powers diff-based polling for change detection. You can also fan-in different commodities into a single checkpoint for correlation analytics.
Key params:
- symbols: comma-separated list (required)
- base: optional currency filter
- category: optional category scope
curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=OMIE_ES_DA,TTF_GAS,EUA_CO2,BRENT_CRUDE" \
--data-urlencode "api_key=YOUR_API_KEY"
Tip: Store the previous rates map and compare on the next poll. If any symbol’s value or date changes, fire an event to your webhook pipeline or SSE stream.
3) Historical series: GET /timeseries
Purpose: retrieve historical series for trends, backfills, moving averages, and anomaly detection. Perfect for charting and model inputs.
Key params:
- start: YYYY-MM-DD (required)
- end: YYYY-MM-DD (required)
- symbols: comma-separated (required)
- base: optional
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"
}
}
Interpretation:
- rates: nested map keyed by symbol then date. Use this for quick rolling indicators like 7-day volatility or 30-day mean reversion triggers.
- frequencies: ensures you don’t misalign daily vs intraday data in your calculations.
- currencies: always check before combining series; normalize externally if producing single-currency analytics.
4) Intraday electricity curve: GET /electricity/hourly
Purpose: obtain the full intraday curve (15-minute or hourly) for a given electricity symbol and date. Drives operational decisions: charge/discharge schedules, flexible load shifting, and peak shaving.
Key params:
- symbol: an electricity symbol like OMIE_ES_DA, EPEX_DE_DA, AEMO_NSW1 (required)
- date: YYYY-MM-DD (required)
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"
Production tip: emit downstream events per-interval or as a single curve payload. For long-running optimization jobs, keep the curve cached and feed it to your solver, then stream results back to clients via SSE or WebSocket.
5) Day-ahead forecast (deterministic): GET /forecast
Purpose: retrieve the next published day-ahead price for auction-sourced electricity symbols. Unlike probabilistic models, this endpoint returns the official, already-published auction result—ideal for crontab triggers that alert as soon as the next day is known.
Key params:
- symbol: electricity symbol with auction schedule (required)
curl -G https://energy-api.com/api/v1/forecast \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "api_key=YOUR_API_KEY"
Use case: run a serverless function that polls /forecast on expected publish windows, diff against the last-seen value, and fan out a webhook to partners or a push notification to your app.
6) Period change analytics: GET /fluctuation
Purpose: get a summary of start/end values, absolute change, and percentage change over a time window. Excellent for alert thresholds, “top movers” widgets, and risk dashboards.
Key params:
- start: YYYY-MM-DD (required)
- end: YYYY-MM-DD (required)
- symbols: comma-separated list (required)
- base: optional
curl -G https://energy-api.com/api/v1/fluctuation \
--data-urlencode "start=2026-05-01" \
--data-urlencode "end=2026-06-01" \
--data-urlencode "symbols=EUA_CO2,TTF_GAS,BRENT_CRUDE" \
--data-urlencode "api_key=YOUR_API_KEY"
Implementation idea: Use change_pct to trigger webhook events when thresholds are breached (e.g., EUA_CO2 drops by more than 5% in a month).
7) Provider health: GET /status
Purpose: get the last fetch status for each upstream data provider. This is critical for production monitoring, circuit breakers, and fallback strategies.
curl -G https://energy-api.com/api/v1/status \
--data-urlencode "api_key=YOUR_API_KEY"
If a provider shows a delayed or failing status, you can temporarily widen alert tolerances or annotate dashboards to prevent noisy pages.
8) Category shortcuts: gas, emissions, coal, carbon-intensity
Purpose: quickly fetch category-specific data in one call. Useful for pipelines that operate per-commodity domain.
- GET /gas/latest — returns TTF_GAS and HENRY_HUB
- GET /emissions/latest — returns EUA_CO2
- GET /coal/latest — returns COAL_ROTTERDAM (API2) and COAL_NEWCASTLE
- GET /carbon-intensity — returns grid intensity by country (gCO2eq/kWh)
curl -G https://energy-api.com/api/v1/gas/latest \
--data-urlencode "api_key=YOUR_API_KEY"
curl -G "https://energy-api.com/api/v1/carbon-intensity?country=DE&api_key=YOUR_API_KEY"
Best practice: Use /carbon-intensity to power carbon-aware scheduling alongside /electricity/hourly for price-aware scheduling. Blend them to optimize for both cost and emissions.
9) Historical snapshot by date: GET /historical
Purpose: fetch values for all requested symbols on a specific date. If the date is a non-publishing day, you’ll get the latest available before it—great for daily backfills or audit views.
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"
This call supports reproducible research: with a deterministic date, you can rebuild portfolio snapshots or compliance reports without wrangling multiple source calendars.
10) OHLC candles: GET /ohlc
Purpose: weekly, monthly, or quarterly OHLC to power volatility charts and risk regimes. It’s also a compact representation for low-latency UI updates.
Key params:
- symbols: comma-separated list (required)
- period: weekly | monthly | quarterly (default monthly)
- start, end: optional date bounds
- base: optional
curl -G https://energy-api.com/api/v1/ohlc \
--data-urlencode "symbols=BRENT_CRUDE,EUA_CO2" \
--data-urlencode "period=monthly" \
--data-urlencode "start=2025-01-01" \
--data-urlencode "end=2025-06-30" \
--data-urlencode "api_key=YOUR_API_KEY"
Emit OHLC updates to clients via WebSocket when a new candle closes to keep interactive charts snappy with minimal payload.
11) Electricity latest: GET /electricity/latest
Purpose: fetch the latest values for all electricity symbols (optionally filter by country). Ideal for a grid overview dashboard that refreshes in one call.
curl -G "https://energy-api.com/api/v1/electricity/latest?country=DE&api_key=YOUR_API_KEY"
Use this to seed or refresh caches; let downstream components subscribe to fine-grained curves with /electricity/hourly.
12) PVPC retail reference: GET /electricity/pvpc
Purpose: track Spanish PVPC hourly reference prices by date. Useful for retail-facing calculators, bill explainers, and notification services.
curl -G "https://energy-api.com/api/v1/electricity/pvpc?date=2026-06-12&api_key=YOUR_API_KEY"
Hook this endpoint to a daily webhook: compute monthly totals or notify customers when tomorrow’s hours make a material difference in expected bills.
13) Simple cost estimates: POST /cost-estimate
Purpose: a quick way to derive monthly wholesale electricity cost estimates from the latest price and a kWh/month input. Great for rough budgeting and guiding plan selection logic.
Key body params:
- symbol or country: one is required
- kwh_per_month: required
curl -X POST https://energy-api.com/api/v1/cost-estimate \
-H "Content-Type: application/json" \
-d '{"symbol":"OMIE_ES_DA","kwh_per_month":450}' \
--data-urlencode "api_key=YOUR_API_KEY"
Note: excludes taxes, network charges, and hourly usage profiles. Pair with PVPC or intraday curves for more granular calculators.
Streaming Updates, Webhooks, and Serverless: Reference Implementation Patterns
Energy API is request/response HTTP, which plays nicely with event-driven patterns. The trick is to combine low-latency polling of relevant endpoints with your own push layer to deliver updates in real time. Below are reference patterns that have worked well across trading desks, fintech portals, and utility dashboards.
Pattern A: Poll + Webhook Fan-out
1) A serverless function (e.g., AWS Lambda, GCP Cloud Functions, Azure Functions) runs every 1–5 minutes.
- It calls /latest for a watchlist like BRENT_CRUDE, TTF_GAS, EUA_CO2, OMIE_ES_DA.
- Optionally, it calls /status to confirm upstream health and /forecast for auction windows.
- It compares the result against a cached snapshot in a key-value store (Redis, DynamoDB, Firestore).
- When a symbol changes (value or date), it posts a JSON payload to subscribed webhook URLs.
2) The webhook payload includes:
- symbol, price, currency, source date, and endpoint provenance
- delta vs previous, change_pct thresholds met
- a link to your app’s detail page for the symbol
3) Subscribers (internal microservices or partners) process updates instantly and render UI changes or trigger further automation.
Pattern B: Poll + Server-Sent Events (SSE) or WebSocket
Implement a long-lived connection for client apps:
- A background job performs the same polling-diff routine.
- On change, it publishes an event to a channel/bus (e.g., Redis Pub/Sub, Kafka).
- Your SSE or WebSocket gateway broadcasts events to connected clients in milliseconds.
SSE is ideal for dashboards and graphs where clients only need downstream updates. WebSocket is handy for bi-directional control (e.g., users pin symbols or set alerts live).
Pattern C: Auction Windows + Batch Notifications
Run a cron-based job that checks /forecast for auction symbols exactly when results are expected. Aggregate all new day-ahead results within a 5-minute window, then send one batched webhook or push to avoid alert storms.
Governance, Reliability, and Observability Best Practices
- Per-app keys and roles: Segment integration keys by service and environment. Log which app triggers each outbound webhook. Rotate keys per app to enforce least privilege.
- Audit logs and metrics: Track every poll call and emitted event. Store before/after values, endpoint used, and latency. This enables reliable incident reconstruction.
- Regional routing: Co-locate your polling functions with your primary user region to reduce round-trip times and jitter.
- Retries with exponential back-off: Honor HTTP 429 with back-off. Treat 404 for /forecast on non-auction symbols as an info, not an error. For 422, validate inputs before retries.
- Circuit breakers: If /status indicates a provider is delayed, slow down polling for related symbols and annotate UI cards with a “Delayed source” badge to prevent confusion.
- Health checks: Add liveness checks that perform a lightweight /latest on a known symbol set. Alert if changes stall beyond expected frequency windows.
Complete JSON Examples and Field Explanations
Below are end-to-end JSON samples that you can paste into tests. Each illustrates how to parse and act on key fields.
Example 1: Multi-commodity /latest for change detection
{
"success": true,
"date": "2026-06-11",
"base": "MIXED",
"rates": {
"BRENT_CRUDE": 74.82,
"TTF_GAS": 38.15,
"EUA_CO2": 67.40,
"OMIE_ES_DA": 86.50
},
"dates": {
"BRENT_CRUDE": "2026-06-11",
"TTF_GAS": "2026-06-11",
"EUA_CO2": "2026-06-11",
"OMIE_ES_DA": "2026-06-11"
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR",
"EUA_CO2": "EUR",
"OMIE_ES_DA": "EUR"
}
}
Practical use:
- Compare rates.BRENT_CRUDE to last-seen. If changed, emit webhook “BRENT_CRUDE_UPDATED”.
- Use dates map to confirm data freshness per symbol without guessing publish schedules.
- If building synthetic indices, convert currencies before summing or indexing.
Example 2: Electricity intraday curve for scheduling
While exact shape may vary, expect a list of intervals with timestamps and prices. Use the symbol + date request to retrieve specific-day curves.
{
"success": true,
"symbol": "OMIE_ES_DA",
"date": "2026-06-12",
"currency": "EUR",
"frequency": "hourly",
"points": [
{ "timestamp": "2026-06-12T00:00:00+02:00", "price": 78.10 },
{ "timestamp": "2026-06-12T01:00:00+02:00", "price": 76.55 },
{ "timestamp": "2026-06-12T02:00:00+02:00", "price": 74.30 }
// ... remaining 21 hours
]
}
Practical use:
- Read frequency to decide whether to schedule hourly or 15-minute control actions.
- Run a solver (e.g., linear programming) that uses “points” as inputs, then stream a dispatch schedule back to the UI via SSE.
- Align timezone-aware timestamps with your asset controller’s local time before issuing commands.
Example 3: Fluctuation analytics for alerts
{
"success": true,
"start": "2026-05-01",
"end": "2026-06-01",
"results": {
"EUA_CO2": {
"start_value": 69.1,
"end_value": 67.4,
"change": -1.7,
"change_pct": -2.46
},
"TTF_GAS": {
"start_value": 36.2,
"end_value": 38.15,
"change": 1.95,
"change_pct": 5.39
},
"BRENT_CRUDE": {
"start_value": 71.45,
"end_value": 74.82,
"change": 3.37,
"change_pct": 4.72
}
}
}
Practical use:
- Trigger alert if change_pct exceeds thresholds (e.g., TTF_GAS over +5% month-over-month).
- Render “top gainers/losers” on a home dashboard, sorted by change_pct.
- Feed change values into a rolling risk score for portfolio margin rules.
Example 4: Timeseries slice for trend computation
{
"success": true,
"base": "MIXED",
"start_date": "2025-02-01",
"end_date": "2025-02-10",
"rates": {
"BRENT_CRUDE": {
"2025-02-03": 77.25,
"2025-02-04": 76.10,
"2025-02-05": 76.95
},
"TTF_GAS": {
"2025-02-03": 44.90,
"2025-02-04": 45.60,
"2025-02-05": 45.20
}
},
"frequencies": {
"BRENT_CRUDE": "daily",
"TTF_GAS": "daily"
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR"
}
}
Practical use:
- Compute rolling 3-day averages and z-scores per symbol.
- Use missing days as a signal of non-publishing days rather than data gaps; your UI should interpolate display but not fabricate data.
Example 5: Carbon intensity for carbon-aware scheduling
{
"success": true,
"country": "DE",
"unit": "gCO2eq/kWh",
"date": "2026-06-11",
"value": 318,
"source": "ENTSO-E/Ember"
}
Practical use:
- Decide when to execute batch jobs or flexible loads to reduce embodied emissions.
- Blend carbon intensity with price curves to produce a weighted cost-of-carbon control policy.
Implementing Webhooks and Streams with Energy API
Below are compact reference implementations for building webhooks, SSE, and serverless jobs around Energy API primitives. These patterns are language-agnostic; you can run them in containers, Kubernetes, or managed functions.
Serverless poller and webhook broadcaster (Node.js)
/**
* Pseudo-implementation: AWS Lambda handler
* - Polls /latest for multiple symbols
* - Diffs against last snapshot in a KV store
* - Broadcasts to webhooks when values change
*/
import fetch from "node-fetch";
const API_BASE = "https://energy-api.com/api/v1";
const API_KEY = process.env.ENERGY_API_KEY;
const WATCHLIST = [
"BRENT_CRUDE",
"TTF_GAS",
"EUA_CO2",
"OMIE_ES_DA",
"CARBON_INT_DE"
];
const WEBHOOKS = [
"https://example.com/webhook/a",
"https://partner.io/energy-updates"
];
export const handler = async () => {
const url = new URL(`${API_BASE}/latest`);
url.searchParams.set("symbols", WATCHLIST.join(","));
url.searchParams.set("api_key", API_KEY);
const res = await fetch(url.toString());
if (!res.ok) {
// Optionally check /status and implement fallback logic
throw new Error(`Latest fetch failed: ${res.status}`);
}
const latest = await res.json();
const prev = await loadSnapshot(); // e.g., from DynamoDB/Redis
const changes = diff(latest, prev); // compare rates, dates per symbol
if (changes.length > 0) {
await saveSnapshot(latest);
await Promise.all(
WEBHOOKS.map((hook) =>
fetch(hook, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ type: "energy.update", at: Date.now(), data: changes })
})
)
);
}
return { ok: true, changed: changes.length };
};
Notes:
- Implement diff(latest, prev) to check both price and date changes per symbol.
- Persist last snapshot atomically to avoid duplicate events on retries.
- Enrich webhook payloads with computed fields (e.g., change_pct) or context (e.g., “source: latest”).
SSE gateway for browser dashboards (Express.js)
import express from "express";
import fetch from "node-fetch";
const app = express();
const clients = new Set();
app.get("/events", (req, res) => {
res.set({
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive"
});
res.flushHeaders();
res.write(`event: ready\ndata: ${JSON.stringify({ ok: true })}\n\n`);
const client = { res };
clients.add(client);
req.on("close", () => clients.delete(client));
});
// Run in background: poll Energy API and push to SSE clients
async function pollAndBroadcast() {
// Build the URL similar to the serverless example
// Compare snapshots, compute changes
const changes = await detectChanges();
if (changes.length > 0) {
const packet = `event: update\ndata: ${JSON.stringify(changes)}\n\n`;
for (const c of clients) c.res.write(packet);
}
setTimeout(pollAndBroadcast, 60_000); // 60s cadence; tune per symbol
}
pollAndBroadcast();
app.listen(8080);
Your browser can now subscribe with EventSource and update charts in real time as Energy API detects changes.
Error Handling, Health Checks, and Fallbacks
Robustness is table stakes for production energy apps. Implement the following:
- Parse and log explicit error codes:
- 401: Authentication missing/invalid. Ensure your configuration layer injects the key.
- 404: No data for given symbols or date. For /forecast and non-auction symbols, surface a friendly message.
- 422: Validation error. Validate symbol lists, dates, and params before issuing requests.
- 429: Rate limit exceeded. Implement exponential back-off and jitter; defer non-critical updates.
- Error shape is consistent:
Handle this uniformly across services and propagate actionable messages to logs and SRE dashboards.{ "success": false, "error": "Human-readable message." } - Provider status with /status: If a provider is delayed, slow polling and annotate UI to avoid misinterpretation. Consider widening alert thresholds temporarily.
- Idempotent webhooks: Include event IDs and deduplicate on the consumer side. Retries should not create double updates.
- Circuit breakers: If repeated upstream failures occur, open the breaker, switch to cached values, and notify operators.
- Observability: Tag each outbound webhook with the upstream endpoint that produced the change (e.g., “source:/latest”). Track per-symbol latency from publish to user-visible update.
Real-World Use Cases
1) Price Alert System for Traders
Polling /latest for TTF_GAS, BRENT_CRUDE, and EUA_CO2 every minute, a serverless function emits a webhook when price changes breach configured thresholds or when a new publish date lands. The consumer service posts Slack notifications with sparkline charts generated from /timeseries. Use /fluctuation to generate daily “movers” summaries and broadcast to web and mobile clients over SSE.
2) ESG and Carbon-Aware Scheduling Dashboard
Combine /electricity/hourly for EPEX_DE_DA or OMIE_ES_DA with /carbon-intensity for DE or ES. A planning service computes an optimal schedule that minimizes a weighted cost function of price and gCO2eq/kWh. As curves update, the system streams new setpoints to plant controllers and the UI via WebSocket. /status is polled to annotate charts when upstream sources are delayed, avoiding false alarms.
3) Retail Cost Calculator and Bill Explainer
For Spanish PVPC customers, query /electricity/pvpc daily and store hourly rates. A frontend calculator estimates the monthly bill using POST /cost-estimate for quick comparisons, then refines with the PVPC hourly profile for detailed breakdowns. Use /forecast to alert users when the next day’s hours imply a significant cost swing, and send proactive suggestions on shifting usage.
Comprehensive Endpoint Coverage and Practical Notes
Below is a succinct list of all 16 endpoints with their primary value in event-driven systems:
- GET /symbols — Discovery and dynamic subscriptions. Drive watchlists and UIs.
- GET /latest — Change detection core loop. Multi-commodity in one shot.
- GET /historical — Backfills and reproducible audit snapshots.
- GET /timeseries — Trends, volatility, charting, and model features.
- GET /fluctuation — Period change analytics for thresholds and summaries.
- GET /ohlc — Compact candle data for charts and regime analysis.
- GET /electricity/latest — Grid-wide electricity overview refresh.
- GET /electricity/hourly — Intraday curve for scheduling and dispatch.
- GET /electricity/pvpc — Retail PVPC tracking and consumer apps.
- GET /gas/latest — TTF_GAS and HENRY_HUB in one call.
- GET /emissions/latest — EUA_CO2 quick lookup for ETS contexts.
- GET /coal/latest — Coal benchmarks (API2, Newcastle) for cross-commodity views.
- GET /carbon-intensity — Country-level gCO2eq/kWh for carbon-aware optimization.
- GET /forecast — Deterministic next day-ahead auction value for electricity symbols.
- POST /cost-estimate — Back-of-the-envelope wholesale cost for planning UIs.
- GET /status — Provider pipeline health for circuit breakers and annotations.
Performance tips:
- Batch symbols into fewer /latest calls to reduce overhead and ensure atomic diffs.
- Cache static metadata from /symbols and refresh it daily.
- When computing aggregates, convert currencies consistently. Always reference the currencies field.
- Use ISO dates and timezone-aware timestamps consistently. Normalize before storing.
- Pre-compute derived metrics (e.g., change_pct) right after fetch and include them in your webhook payload to reduce consumer work.
End-to-End Example: From Poll to SSE with Python
This Python sketch performs a periodic poll of /latest, computes diffs, persists a snapshot, and exposes an SSE endpoint using a minimalist web server. It demonstrates how small the glue code can be with a normalized data layer.
import json, os, time, threading
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlencode
import requests
API_BASE = "https://energy-api.com/api/v1"
API_KEY = os.environ.get("ENERGY_API_KEY")
WATCHLIST = "BRENT_CRUDE,TTF_GAS,EUA_CO2,OMIE_ES_DA"
snapshot = None
subscribers = set()
def fetch_latest():
params = { "symbols": WATCHLIST, "api_key": API_KEY }
r = requests.get(f"{API_BASE}/latest", params=params, timeout=10)
r.raise_for_status()
return r.json()
def diff(now, prev):
if not prev:
return [{"symbol": s, "old": None, "new": v} for s, v in now["rates"].items()]
changes = []
for s, v in now["rates"].items():
old = prev["rates"].get(s) if prev and "rates" in prev else None
if old is None or old != v or now["dates"].get(s) != prev["dates"].get(s):
changes.append({
"symbol": s,
"old": old,
"new": v,
"currency": now["currencies"].get(s),
"date": now["dates"].get(s)
})
return changes
def poll_loop():
global snapshot
while True:
try:
now = fetch_latest()
changes = diff(now, snapshot)
if changes:
snapshot = now
payload = f"event: update\ndata: {json.dumps(changes)}\n\n"
dead = []
for s in list(subscribers):
try:
s.wfile.write(payload.encode("utf-8"))
s.wfile.flush()
except:
dead.append(s)
for d in dead:
subscribers.discard(d)
except Exception as e:
# Log and continue
pass
time.sleep(60)
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/events":
self.send_response(200)
self.send_header("Content-Type", "text/event-stream")
self.send_header("Cache-Control", "no-cache")
self.send_header("Connection", "keep-alive")
self.end_headers()
subscribers.add(self)
try:
while True:
time.sleep(10)
except:
subscribers.discard(self)
else:
self.send_response(200)
self.end_headers()
self.wfile.write(b"OK")
if __name__ == "__main__":
threading.Thread(target=poll_loop, daemon=True).start()
HTTPServer(("0.0.0.0", 8080), Handler).serve_forever()
Open your browser at /events and watch for live updates as prices change. Clients can subscribe without complex authentication between services because the poller guards upstream access while broadcasting sanitized events internally.
FAQ
How often does the TTF gas price update?
TTF_GAS is published on a daily cadence. Use GET /latest for quick reads and GET /timeseries for historical context. For change-driven systems, poll at a cadence aligned with market publishing windows and use the dates field to detect new official values.
Can I query multiple commodities (gas, electricity, carbon, oil) in a single call?
Yes. GET /latest supports comma-separated symbols across commodities, returning one normalized JSON payload. This is ideal for cross-commodity correlation, hedging logic, and consolidated dashboards.
Do you provide intraday electricity curves?
Yes, where sources publish them. Use GET /electricity/hourly with a symbol and date to fetch hourly or 15-minute curves. You can then compute schedules, trigger alerts on price spikes, or run optimization for storage and flexible loads.
Can I get historical energy prices going back multiple years?
Use GET /timeseries with start and end dates to retrieve historical series for supported symbols. For fixed historical snapshots, GET /historical on a specific date is ideal for reconciling positions or building audit views.
Does the API support provider health monitoring?
Yes. GET /status returns the last fetch status per provider. Use it to annotate dashboards, adjust polling back-offs, and implement circuit breakers if a provider is delayed or temporarily unavailable.
Conclusion + CTA
Event-driven energy applications require timely, normalized data delivered to downstream consumers with minimal friction. With Energy API, you avoid ETL sprawl and move faster: one REST surface for electricity, gas, oil, coal, carbon allowances, and grid carbon intensity; intraday curves where available; deterministic day-ahead lookups; and consistent JSON across all commodities. The result is a development loop focused on what matters—streaming insights to users, triggering automations, and making better decisions sooner.
From price alerting bots and ESG dashboards to carbon-aware schedulers and cost calculators, the patterns in this post—poll + webhook fan-out, SSE/WebSocket broadcasts, serverless orchestration, and health-aware fallbacks—are ready to plug into your stack today. You write less glue code, ship faster, and get production reliability from day one.
Build your first event-driven energy feature in hours, not weeks. Explore the endpoints, wire up a serverless poller, and push live updates to your UI. Try Energy API for free and start delivering real-time grid automation to your users.
Ready to get started?
Get your API key and start querying energy commodity prices in minutes.
Get API KeyRelated posts
Discover how Energy API can automate demand response programs, streamline event triggering, and enhance enroll...
Read more →
Discover how to enhance grid operations by operationalizing anomaly detection with Energy API. Learn to catch...
Read more →
Discover how an Energy API can streamline renewable integration and enhance grid management for utilities. Unl...
Read more →
Discover how to build offline-first mobile apps for field technicians using Energy API. Enhance decision-makin...
Read more →
Discover how Energy API enhances smart grid development by streamlining data access, reducing costs, and empow...
Read more →