Building a Demand-Charge Avoidance Service with Energy API: Real-Time Load Shaping, Customer Signals, and Billing Integration for Utilities and ESCOs
You need to keep large customers under their contracted demand threshold without annoying curtailment calls that hurt operations or revenue. By the end of this post, you’ll know how to build a demand-charge avoidance service that shapes load in real time, sends customer-friendly control signals, and reconciles billing—using a single normalized data surface from Energy API.
Introduction
Demand charges penalize peaks, not kWh. If you operate a utility, ESCO, or load flexibility platform, you already know that shaving a few MW at the right hour can save a customer more than an entire week of energy efficiency work. The challenge is timing and trust. You need reliable market and grid data—hourly curves, day-ahead auction results, and carbon intensity—to trigger the right load reduction at exactly the right time.
Pulling this data from several official sources means decoding different schemas, calendars, and naming conventions. Your team shouldn’t spend sprints merging CSVs or driving one-off scrapers. With Energy API, you can discover symbols, fetch spot and day-ahead prices, read intraday curves, and even estimate wholesale costs using the same JSON schema across electricity, gas, oil, coal, carbon, and carbon intensity. This post shows how to wire those endpoints into a production-grade demand-charge avoidance workflow.
Why Energy API
- One normalized REST surface: Replace OMIE, ENTSO-E, EIA, ESIOS, and others with consistent endpoints and fields. You can ship features without building custom ETL for each source.
- Same schema across commodities: Fetch electricity prices, EUA carbon allowances, and gas benchmarks in one call and get a uniform response shape, so your alerting and optimization logic stays simple.
- Intraday electricity curves where available: Pull 15-minute or hourly curves via a single endpoint for operational decisions like pre-heating, battery dispatch, and EV charging throttling.
- Deterministic day-ahead forecast endpoint: Retrieve the next published auction day-ahead price for auction sources. No guesswork, no model drift—ideal for next-day peak shaving schedules.
Quick Start
Base URL: https://energy-api.com/api/v1
Authentication: Append your key as a query parameter api_key.
First request: fetch the latest price for multiple commodities in one call. This is helpful when your control logic needs electricity and carbon allowances to weigh cost versus emissions.
cURL
curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=OMIE_ES_DA,EUA_CO2,TTF_GAS" \
--data-urlencode "api_key=YOUR_API_KEY"
Illustrative JSON response
{
"success": true,
"date": "2026-06-11",
"base": "MIXED",
"rates": {
"OMIE_ES_DA": 79.12,
"EUA_CO2": 67.40,
"TTF_GAS": 38.15
},
"dates": {
"OMIE_ES_DA": "2026-06-11",
"EUA_CO2": "2026-06-11",
"TTF_GAS": "2026-06-11"
},
"currencies": {
"OMIE_ES_DA": "EUR",
"EUA_CO2": "EUR",
"TTF_GAS": "EUR"
}
}
What you’ll use: rates for the latest values, dates to confirm staleness on non-publishing days, and currencies to handle unit conversions or display. The base value is “MIXED” when multiple currencies are returned.
Core Endpoints
Below are four core endpoints you’ll use to power load shaping, customer signals, and billing reconciliation.
1) Discover electricity symbols to target the right market
Endpoint: GET /symbols
Key params:
category(optional): filter toelectricitybase(optional): currency filterprovider(optional): e.g.,omie
Use this before deployment to decide which symbols drive your program logic and UI labels (e.g., OMIE Spain Day-Ahead vs EPEX DE).
cURL
curl -G https://energy-api.com/api/v1/symbols \
--data-urlencode "category=electricity" \
--data-urlencode "api_key=YOUR_API_KEY"
Illustrative JSON response
{
"success": true,
"count": 3,
"symbols": [
{
"symbol": "OMIE_ES_DA",
"name": "OMIE Spain Day-Ahead",
"category": "electricity",
"country_code": "ES",
"currency_code": "EUR",
"frequency": "daily",
"description": "Day-ahead price published by OMIE."
}
]
}
Fields to note: symbol is your programmatic handle; frequency signals expected publishing cadence; country_code helps map to service territories.
2) Pull intraday curves to time-shift flexible load
Endpoint: GET /electricity/hourly
Key params:
symbol(required): e.g.,OMIE_ES_DAdate(required): YYYY-MM-DD
Use this to create the day’s operating schedule for battery dispatch, HVAC pre-cooling, or EV fleet charging—especially when 15-minute granularity is available.
cURL
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"
Tip: Cache curves per symbol-date in your backend and invalidate only when the provider’s auction results are republished. Use the /status endpoint (below) to monitor provider freshness.
3) Retrieve the next published day-ahead result for peak shaving
Endpoint: GET /forecast
Key params:
symbol(required): valid auction-sourced electricity symbol
This is not a predictive model. It returns the next published day-ahead price for symbols that publish via auctions. It’s perfect for sending next-day DR setpoints to customers right after results are available.
cURL
curl -G https://energy-api.com/api/v1/forecast \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "api_key=YOUR_API_KEY"
Behavior: If you pass a non-auction symbol, the API returns HTTP 404. Always implement graceful fallback (e.g., keep the last known curve until the new one publishes; notify operators via your incident channel).
4) Monitor real-time price and carbon signals together
Endpoint: GET /latest
Key params:
symbols(required): comma-separated list, e.g.,OMIE_ES_DA,EUA_CO2,CARBON_INT_EUbase(optional)
It’s often useful to weigh cost and emissions when deciding whether to clip demand or run on-site generation. Query electricity, carbon allowances, gas benchmarks, or grid carbon intensity together and route the combined signals to your control logic.
cURL
curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=OMIE_ES_DA,EUA_CO2,CARBON_INT_EU" \
--data-urlencode "api_key=YOUR_API_KEY"
Illustrative JSON response
{
"success": true,
"date": "2026-06-11",
"base": "MIXED",
"rates": {
"OMIE_ES_DA": 79.12,
"EUA_CO2": 67.40,
"CARBON_INT_EU": 235.0
},
"dates": {
"OMIE_ES_DA": "2026-06-11",
"EUA_CO2": "2026-06-11",
"CARBON_INT_EU": "2026-06-11"
},
"currencies": {
"OMIE_ES_DA": "EUR",
"EUA_CO2": "EUR",
"CARBON_INT_EU": "gCO2eq/kWh"
}
}
Key fields: rates holds the numeric signals you’ll normalize; currencies clarifies units (note that carbon intensity returns gCO2eq/kWh instead of a currency); dates timestamps each symbol individually to handle mixed publishing calendars.
5) Backtest your control strategy to prove savings
Endpoint: GET /timeseries
Key params:
start(required): YYYY-MM-DDend(required): YYYY-MM-DDsymbols(required): comma-separated
Use this to quantify avoided demand charges and energy costs over a historical window. It’s the backbone of your M&V (measurement and verification) reports to customers.
cURL
curl -G https://energy-api.com/api/v1/timeseries \
--data-urlencode "start=2025-01-01" \
--data-urlencode "end=2025-03-31" \
--data-urlencode "symbols=OMIE_ES_DA,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
Illustrative JSON response
{
"success": true,
"base": "MIXED",
"start_date": "2025-01-01",
"end_date": "2025-03-31",
"rates": {
"OMIE_ES_DA": {
"2025-01-02": 76.30,
"2025-01-03": 75.90
},
"EUA_CO2": {
"2025-01-02": 46.80,
"2025-01-03": 47.10
}
},
"frequencies": {
"OMIE_ES_DA": "daily",
"EUA_CO2": "daily"
},
"currencies": {
"OMIE_ES_DA": "EUR",
"EUA_CO2": "EUR"
}
}
You’ll iterate over rates[symbol][date] to simulate your control decisions, then compute counterfactual costs with and without peak clipping.
6) Simple wholesale cost estimate for billing reconciliation
Endpoint: POST /cost-estimate
Key params (body):
symbolORcountry(one required)kwh_per_month(required)
Use this to generate quick customer-facing estimates or to cross-check supplier invoices at a glance. It multiplies the latest price by a monthly usage estimate (excludes taxes, network charges, or hourly load shapes).
Example request (symbol-based)
curl -X POST https://energy-api.com/api/v1/cost-estimate \
-H "Content-Type: application/json" \
-d '{"symbol":"OMIE_ES_DA","kwh_per_month":120000}' \
--get --data-urlencode "api_key=YOUR_API_KEY"
Note: The endpoint uses POST with a JSON body. The above shows the body and appends api_key as a query parameter as documented.
7) Provider fetch status for production monitoring
Endpoint: GET /status
Use this to alert your team if a data provider hasn’t updated. Pair it with circuit breakers so your control loop can fall back to last known good values if a provider lags.
cURL
curl -G https://energy-api.com/api/v1/status \
--data-urlencode "api_key=YOUR_API_KEY"
End-to-End Flow for Demand-Charge Avoidance
Here’s how you can wire the endpoints into a practical control loop.
- Day-Ahead Scheduling: When auction results publish, call
/forecastfor your market symbol (e.g.,OMIE_ES_DA) to generate a next-day schedule for pre-cooling, battery charging, and flexible process windows. - Intraday Adjustments: Pull
/electricity/hourlyfor the current date and blend with/latestsignals (carbon intensity or EUA) to refine the control setpoints as conditions change. - Customer Signals: Translate the upcoming expensive or high-emission hours into clear instructions for BMS/EMS or direct-to-device controls. Use the timestamps returned to align signals to local time in your UI.
- Backtesting and M&V: Use
/timeseriesto simulate the avoided peak and cost under different strategies, then produce a delta report for customers or internal finance. - Billing Reconciliation: For a quick sanity check, call
/cost-estimatewith monthly kWh. For more precision, multiply intraday curves by customer profiles in your own engine.
Python example: fetch multi-signal latest values
This example mirrors the earlier cURL call to /latest and reads pricing and carbon fields you’ll feed to your controller.
import requests
BASE_URL = "https://energy-api.com/api/v1/latest"
API_KEY = "YOUR_API_KEY"
symbols = "OMIE_ES_DA,EUA_CO2,CARBON_INT_EU"
params = {
"symbols": symbols,
"api_key": API_KEY
}
resp = requests.get(BASE_URL, params=params, timeout=15)
resp.raise_for_status()
data = resp.json()
if not data.get("success"):
raise RuntimeError(f"API error: {data.get('error')}")
rates = data["rates"]
dates = data["dates"]
currencies = data["currencies"]
price_eur_mwh = rates["OMIE_ES_DA"]
eua_eur_ton = rates["EUA_CO2"]
grid_intensity = rates["CARBON_INT_EU"] # gCO2eq/kWh
print("Electricity price:", price_eur_mwh, currencies["OMIE_ES_DA"], "as of", dates["OMIE_ES_DA"])
print("EUA:", eua_eur_ton, currencies["EUA_CO2"], "as of", dates["EUA_CO2"])
print("Grid intensity:", grid_intensity, currencies["CARBON_INT_EU"], "as of", dates["CARBON_INT_EU"])
Production note: Cache the response for a short TTL to smooth transient provider delays, handle HTTP 429 with exponential back-off, and check the dates field to avoid acting on stale data during non-publishing days.
Real-World Use Cases
- Automated peak clipping for C&I customers: Use
/forecastand/electricity/hourlyto find the next day’s most expensive blocks and pre-cool buildings or pre-charge batteries beforehand. Confirm the live signal with/latestto avoid over-curtailing when prices soften. - Green load shifting for sustainability teams: Combine
/latestfor electricity andCARBON_INT_*symbols to choose the lowest-emission hour to run discretionary loads without breaking cost ceilings. Build a UI that overlays both signals for operators. - M&V reporting and invoice cross-check: Backtest strategies with
/timeseries, and present a simple customer-facing estimate using/cost-estimate. Export the result to your billing system for reconciliation.
Practical Integration Notes
- Units and currencies: Electricity prices are typically in EUR/MWh or the market currency for the symbol; EUA is EUR/MT; carbon intensity is gCO2eq/kWh. The
currenciesmap in each response clarifies units. - Time and calendars: Different providers publish on different schedules and may skip weekends/holidays. On non-publishing days, use
datesto confirm the freshness of values you act on. - Error handling: Expect 401 for missing keys, 404 when data doesn’t exist (e.g., non-auction symbol passed to
/forecast), 422 for bad params, and 429 for rate limiting. Implement back-off and retries where appropriate. - Caching strategy: Cache symbol discovery (
/symbols) for days, intraday curves for the specific date, and/latestfor a short TTL aligned with your control loop (e.g., 1–5 minutes). - Observability: Poll
/statusto monitor provider pipelines. If a provider delays publication, surface a warning in your UI and avoid aggressive control changes until the next update.
FAQ
How do I know when the next day-ahead electricity price is available?
Call /forecast with your auction-based symbol (e.g., OMIE_ES_DA). It returns the next published day-ahead value as soon as it’s available. If you pass a non-auction symbol, you’ll get a 404—use that to gate your scheduling step.
Can I fetch gas, electricity, and carbon signals in a single request?
Yes. Use /latest with a comma-separated list of symbols (e.g., OMIE_ES_DA,EUA_CO2,TTF_GAS). The response includes a currencies map so you can handle mixed units and currencies consistently.
How far back can I backtest a demand-charge strategy?
Use /timeseries to retrieve historical series between two dates. The response contains a date-keyed map for each symbol and the frequencies you’ll need for charting and aggregation. If a requested date falls on a non-publishing day, use the returned keys to align your analysis window.
What happens on weekends or holidays when a market doesn’t publish?
When requesting a specific date with endpoints like /historical, the API returns the most recent value before the date if no new value exists. Always check the per-symbol dates map on /latest and use it as a staleness guard before issuing control signals.
Does Energy API support different time granularities for electricity?
Yes. Use /electricity/hourly to retrieve intraday curves with hourly or 15-minute resolution where available. For broader trend or M&V, use /timeseries which returns date-level series suitable for charts or analytics.
Conclusion + CTA
Building a credible demand-charge avoidance service means timing your moves with trustworthy market and grid data. With unified endpoints for symbol discovery, day-ahead results, intraday curves, and multi-commodity snapshots, your team can iterate on control logic instead of maintaining data ingestion scripts. Add backtesting and billing sanity checks, and you have a full stack from planning to reconciliation.
If you’re ready to ship load shaping and customer signals without weeks of ETL, start with Energy API. Wire the endpoints shown here into your scheduler, and get from prototype to production fast. Try Energy API for free and plug real market data into your demand-charge avoidance workflow today.
Ready to get started?
Get your API key and start querying energy commodity prices in minutes.
Get API KeyRelated posts
Discover how the Energy API empowers utilities to enhance real-time load forecasting, ensuring efficient deman...
Read more →
Discover how to build a robust probabilistic load-forecasting pipeline using Energy API and Bayesian models to...
Read more →
Discover how API retail tariff optimization and dynamic Time-of-Use plans can help utilities reduce customer b...
Read more →
Discover how Energy API streamlines meter-to-bill reconciliation for utilities, automating netting, tariff rul...
Read more →
Discover how Energy API transforms energy billing systems, enhancing customer transparency and streamlining da...
Read more →