End-to-End Meter-to-Bill Reconciliation for Utilities: Using Energy API to Automate Netting, Tariff Rules, and Dispute Workflows

End-to-End Meter-to-Bill Reconciliation for Utilities: Using Energy API to Automate Netting, Tariff Rules, and Dispute Workflows

Utilities and energy retailers live and die by accurate meter-to-bill reconciliation. If your settlement engine can’t tie the interval meter reads to wholesale position, tariff rules, and contracted indices, revenue leakage follows. Disputes build up, cash is delayed, and engineering teams end up firefighting spreadsheets, manual downloads from market portals, and a maze of CSV schedulers that break on holidays. Meanwhile, your customers expect transparent bills with line-item detail (energy, network, taxes, levies, carbon) and a clear rationale for why their totals change month to month.

This post shows how to build an end-to-end meter-to-bill reconciliation pipeline using Energy API: a unified REST interface over official wholesale energy datasets. We’ll walk through automated netting of import/export intervals, application of tariff structures (flat, time-of-use, day-ahead pass-through), and building the evidence pack you need for dispute workflows. You’ll see how to fetch day-ahead auctions, intraday hourly curves, and reference price series with the same JSON schema—so you can ship a robust reconciliation service in days instead of weeks of ETL work.

You are a developer, data engineer, or product lead. You want reliable energy market data—electricity, gas, oil, coal, carbon allowances, and grid carbon intensity—without scraping multiple government portals or normalizing incompatible formats. With Energy API, you can query multiple commodities in one call, orchestrate tariff lookups per meter interval, and generate a transparent audit trail that de-risks billing and drives down dispute handling time.

Why Energy API

Billing engines and settlement services need three core ingredients: correct prices, consistent schemas, and predictable publishing schedules. In practice, European day-ahead electricity auctions, Spanish PVPC retail references, and EU ETS carbon prices all publish on different clocks, in different currencies and formats, and with evolving symbol names. Trying to maintain custom scrapers and translators bloats your codebase, increases operational risk, and makes every regional expansion a small refactor hell.

Energy API consolidates official sources—OMIE, ENTSO-E, ESIOS, EIA, FRED, and partner feeds—under a single normalized REST surface. That means electricity intraday curves, PVPC hourly references for Spain, TTF gas, Brent/WTI crude, coal benchmarks, EUA carbon allowances, and grid carbon intensity share the same JSON shape. You can:

  • Share data components across products. One transformer parses /timeseries for both electricity and carbon without custom adapters per provider. That’s real engineering leverage when you expand into a new country or add a carbon line item to bills.
  • Ship features faster with deterministic coverage. Need the next published day-ahead price for OMIE_ES_DA to compute tomorrow’s tariff? Hit /forecast. Need the full hourly curve for a specific settlement date and symbol? Use /electricity/hourly. Repeat the same calling pattern across markets.
  • Reduce operational risk. The /status endpoint reports last fetch states for each provider. You can wire health checks and circuit breakers to pause settlements if an upstream source hasn’t published yet, instead of ingesting partial data that creates downstream disputes.
  • Model-ready responses. Intraday 15-minute or hourly curves where sources provide them; OHLC candles for traders; fluctuation analytics for volatility controls; and day-level latest/historical snapshots for fast index calculations. All keyed by a single symbol namespace.

Quick Start

Base URL for all requests:

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

Energy API uses a simple query parameter api_key. Below is a first call to fetch the most recent Brent crude, TTF gas, and EUA carbon prices in a single request. This is useful when your tariff or reconciliation pipeline references multiple indices (e.g., power price base on day-ahead auction plus carbon pass-through; or a dual-fuel bill needing both power and gas references).

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"

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

What to note:

  • rates: the latest value per symbol. You can use these directly in tariff multipliers (e.g., a gas index rider or carbon line item).
  • dates: the publication date per symbol. For reconciliation, store this for audit reproducibility and to prove which vintage you used.
  • currencies: currency per symbol. If you bill in a single currency, convert in your pricing layer using your FX policy.

Core Endpoints for Meter-to-Bill Reconciliation

1) Discover symbols: GET /symbols

Use /symbols to discover what’s available and capture metadata like country_code, frequency, and description. This is handy for building your tariff configuration UI and for validating a symbol before running a settlement.

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

Sample response (truncated for brevity):

{
"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 electricity auction price for Spain."
},
{
"symbol": "EPEX_DE_DA",
"name": "EPEX Germany Day-Ahead",
"category": "electricity",
"country_code": "DE",
"currency_code": "EUR",
"frequency": "daily",
"description": "Day-ahead auction price for Germany."
},
{
"symbol": "PVPC_ES_2TD",
"name": "Spain PVPC Reference (2TD)",
"category": "electricity",
"country_code": "ES",
"currency_code": "EUR",
"frequency": "hourly",
"description": "Hourly PVPC retail reference tariff for Spain (2-term distribution)."
}
]
}

Field notes:

  • symbol: canonical code used in other endpoints. Store this string directly in tariff rules.
  • frequency: daily vs hourly. Use hourly for interval settlement and daily for index multipliers.
  • country_code and currency_code: map to your customer’s meter location and billing currency policy.

2) Intraday/Hourly curves: GET /electricity/hourly

To reconcile interval meter reads to wholesale energy, you need the actual curve used for settlement. /electricity/hourly returns the full hourly (or 15-min, where available) curve for a symbol and date. If your tariff passes through day-ahead prices, or you need to compute weighted-average costs by interval, this is your backbone endpoint.

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

Sample response:

{
"success": true,
"symbol": "OMIE_ES_DA",
"date": "2026-06-10",
"currency": "EUR",
"interval": "hourly",
"curve": [
{"timestamp": "2026-06-10T00:00:00+02:00", "price": 78.43},
{"timestamp": "2026-06-10T01:00:00+02:00", "price": 76.10},
{"timestamp": "2026-06-10T02:00:00+02:00", "price": 71.55},
{"timestamp": "2026-06-10T03:00:00+02:00", "price": 69.80},
{"timestamp": "2026-06-10T04:00:00+02:00", "price": 68.33},
{"timestamp": "2026-06-10T05:00:00+02:00", "price": 70.22},
{"timestamp": "2026-06-10T06:00:00+02:00", "price": 75.66},
{"timestamp": "2026-06-10T07:00:00+02:00", "price": 82.10},
{"timestamp": "2026-06-10T08:00:00+02:00", "price": 88.05},
{"timestamp": "2026-06-10T09:00:00+02:00", "price": 92.20},
{"timestamp": "2026-06-10T10:00:00+02:00", "price": 94.10},
{"timestamp": "2026-06-10T11:00:00+02:00", "price": 95.00},
{"timestamp": "2026-06-10T12:00:00+02:00", "price": 93.55},
{"timestamp": "2026-06-10T13:00:00+02:00", "price": 90.10},
{"timestamp": "2026-06-10T14:00:00+02:00", "price": 86.33},
{"timestamp": "2026-06-10T15:00:00+02:00", "price": 84.00},
{"timestamp": "2026-06-10T16:00:00+02:00", "price": 85.90},
{"timestamp": "2026-06-10T17:00:00+02:00", "price": 90.40},
{"timestamp": "2026-06-10T18:00:00+02:00", "price": 96.88},
{"timestamp": "2026-06-10T19:00:00+02:00", "price": 99.55},
{"timestamp": "2026-06-10T20:00:00+02:00", "price": 101.10},
{"timestamp": "2026-06-10T21:00:00+02:00", "price": 95.66},
{"timestamp": "2026-06-10T22:00:00+02:00", "price": 88.77},
{"timestamp": "2026-06-10T23:00:00+02:00", "price": 82.30}
]
}

Field notes:

  • timestamp: timezone-aware. Align with your meter’s interval timestamps before aggregation. Never assume UTC; reconcile explicitly by timezone.
  • interval: hourly or 15-min. Your settlement engine should be interval-agnostic and resample if your meters use different granularity.
  • curve: the exact series to multiply by interval kWh for pass-through tariffs.

3) Spanish PVPC hourly references: GET /electricity/pvpc

For Spanish residential and SME tariffs tied to PVPC, you must price energy at the published hourly retail reference. This endpoint pulls the official hourly PVPC curve for a given date to support retail reconciliation and customer bill transparency.

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

Sample response:

{
"success": true,
"date": "2026-06-10",
"currency": "EUR",
"interval": "hourly",
"pvpc": [
{"timestamp": "2026-06-10T00:00:00+02:00", "price": 0.1452},
{"timestamp": "2026-06-10T01:00:00+02:00", "price": 0.1431},
{"timestamp": "2026-06-10T02:00:00+02:00", "price": 0.1390},
{"timestamp": "2026-06-10T03:00:00+02:00", "price": 0.1362},
{"timestamp": "2026-06-10T04:00:00+02:00", "price": 0.1339},
{"timestamp": "2026-06-10T05:00:00+02:00", "price": 0.1375},
{"timestamp": "2026-06-10T06:00:00+02:00", "price": 0.1449},
{"timestamp": "2026-06-10T07:00:00+02:00", "price": 0.1520},
{"timestamp": "2026-06-10T08:00:00+02:00", "price": 0.1601},
{"timestamp": "2026-06-10T09:00:00+02:00", "price": 0.1683},
{"timestamp": "2026-06-10T10:00:00+02:00", "price": 0.1715},
{"timestamp": "2026-06-10T11:00:00+02:00", "price": 0.1742},
{"timestamp": "2026-06-10T12:00:00+02:00", "price": 0.1708},
{"timestamp": "2026-06-10T13:00:00+02:00", "price": 0.1655},
{"timestamp": "2026-06-10T14:00:00+02:00", "price": 0.1592},
{"timestamp": "2026-06-10T15:00:00+02:00", "price": 0.1567},
{"timestamp": "2026-06-10T16:00:00+02:00", "price": 0.1589},
{"timestamp": "2026-06-10T17:00:00+02:00", "price": 0.1644},
{"timestamp": "2026-06-10T18:00:00+02:00", "price": 0.1721},
{"timestamp": "2026-06-10T19:00:00+02:00", "price": 0.1768},
{"timestamp": "2026-06-10T20:00:00+02:00", "price": 0.1800},
{"timestamp": "2026-06-10T21:00:00+02:00", "price": 0.1730},
{"timestamp": "2026-06-10T22:00:00+02:00", "price": 0.1652},
{"timestamp": "2026-06-10T23:00:00+02:00", "price": 0.1564}
]
}

Practical use:

  • Multiply PVPC hourly price by interval energy after netting import/export to compute customer charges. Round according to your regulatory rounding policy per line item.
  • Keep the PVPC timestamped curve in your audit store alongside meter intervals to explain bills and resolve disputes quickly with exact reference prices.

4) Day-ahead forecast (deterministic lookup): GET /forecast

Many reconciliation engines compute tomorrow’s estimated bill or cost-to-serve as soon as auction results are posted. /forecast provides the next published day-ahead price for eligible auction symbols (e.g., OMIE_ES_DA). This is not a predictive model; it’s a deterministic retrieval of the next auctioned curve or day-level result the moment it’s published.

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

Sample response:

{
"success": true,
"symbol": "OMIE_ES_DA",
"for_date": "2026-06-12",
"currency": "EUR",
"interval": "hourly",
"curve": [
{"timestamp": "2026-06-12T00:00:00+02:00", "price": 79.10},
{"timestamp": "2026-06-12T01:00:00+02:00", "price": 76.80}
/* ... 22 more hourly points ... */
],
"published_at": "2026-06-11T13:05:00+02:00",
"source": "OMIE"
}

Implementation tips:

  • Wire this into your “tomorrow’s tariff” calculation so you can notify customers or update retail pricing UIs as soon as data is live.
  • If you serve multiple regions (e.g., EPEX_DE_DA and OMIE_ES_DA), call /forecast per symbol and standardize the hourly curve interface across markets.

5) Time series for trend and QA: GET /timeseries

Use /timeseries to validate monthly averages, compute index escalators, or generate baseline cost forecasts. When disputes arise, historical trends help you demonstrate that a given day’s price wasn’t anomalous or, if it was, how it compares to neighboring days.

curl -G https://energy-api.com/api/v1/timeseries \
--data-urlencode "start=2026-05-01" \
--data-urlencode "end=2026-06-10" \
--data-urlencode "symbols=OMIE_ES_DA,EUA_CO2,TTF_GAS" \
--data-urlencode "api_key=YOUR_API_KEY"

Sample response:

{
"success": true,
"base": "MIXED",
"start_date": "2026-05-01",
"end_date": "2026-06-10",
"rates": {
"OMIE_ES_DA": {
"2026-05-02": 78.20,
"2026-05-03": 75.15
/* ... */
},
"EUA_CO2": {
"2026-05-02": 67.90,
"2026-05-03": 68.35
/* ... */
},
"TTF_GAS": {
"2026-05-02": 36.10,
"2026-05-03": 36.45
/* ... */
}
},
"frequencies": {
"OMIE_ES_DA": "daily",
"EUA_CO2": "daily",
"TTF_GAS": "daily"
},
"currencies": {
"OMIE_ES_DA": "EUR",
"EUA_CO2": "EUR",
"TTF_GAS": "EUR"
}
}

Why this matters:

  • rates: keyed by symbol, then by date, perfect for time-weighted average costs over a billing cycle.
  • frequencies and currencies: allow your analytics to adapt automatically per symbol without hard-coded assumptions.
  • Multi-commodity: You can fetch electricity, gas, and carbon in one call—which is ideal for dual-fuel billing or adding a carbon component to power.

6) Latest at a glance: GET /latest

We already used /latest in Quick Start. Use it inside validation steps and dashboards to snapshot today’s price references across commodities. This is perfect for monitoring as you close a billing cycle, or for computing provisional charges before full interval reconciliation completes.

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

Interpretation:

  • It returns the latest value per symbol. For PVPC, the “latest” is typically the current day’s context; always anchor detailed billing to hourly curves via /electricity/pvpc for precision.

7) Publication health: GET /status

Your reconciliation pipeline should not run on partial data. /status returns last fetch status for each provider so you can gate your jobs. If ENTSO-E or OMIE is delayed, you can hold settlement until a healthy state returns, preventing data gaps that otherwise create disputes down the line.

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

Sample response:

{
"success": true,
"providers": {
"OMIE": {
"last_success": "2026-06-11T13:07:10Z",
"last_error": null,
"status": "ok"
},
"ENTSOE": {
"last_success": "2026-06-11T12:58:44Z",
"last_error": null,
"status": "ok"
},
"ESIOS": {
"last_success": "2026-06-11T12:30:12Z",
"last_error": null,
"status": "ok"
},
"EIA": {
"last_success": "2026-06-10T20:01:05Z",
"last_error": null,
"status": "ok"
},
"FRED": {
"last_success": "2026-06-10T20:01:10Z",
"last_error": null,
"status": "ok"
}
}
}

Best practice: Fail-fast if a required provider is “degraded” or “error,” and retry with exponential backoff. If a billing run must complete, record the missing sources explicitly and generate a pro forma that is flagged for later adjustment once data arrives.

Designing an End-to-End Meter-to-Bill Reconciliation Flow

Below is a practical architecture pattern you can implement with Energy API to reconcile interval meter reads into auditable invoices and cost-of-goods-sold (COGS) line items. This covers netting, tariff application, and generating a dispute-ready evidence pack.

Step 1: Ingest and align meter intervals

  • Pull meter reads per EAN/EIC/MPRN as 15-min or 60-min intervals in local time, with import (kWh delivered) and export (kWh injected) channels if applicable.
  • Normalize timezones and fill missing intervals as zeros to ensure a complete contiguous series for billing logic.

Step 2: Netting

  • For each interval i, compute net_kwh[i] = import[i] - export[i]. For net metering policies, negative net might roll to credits; for self-consumption, you may price import at retail and export at a feed-in rate.
  • Persist per-interval net_kwh and separately keep gross import/export for transparency. Dispute workflows often require showing both.

Step 3: Fetch price curves and indices

  • If pass-through to day-ahead or intraday curves: use /electricity/hourly with symbol matching the meter region (e.g., OMIE_ES_DA for Spain, EPEX_DE_DA for Germany).
  • For PVPC-tied tariffs: use /electricity/pvpc for the settlement date.
  • For carbon or gas riders: use /latest or /timeseries for EUA_CO2 and TTF_GAS to compute monthly pass-through factors.
  • Confirm data availability via /status and implement a circuit breaker.

Step 4: Tariff rules

  • Flat energy rate: multiply net import kWh per billing cycle by fixed price.
  • Time-of-use: define peak/off-peak blocks and multiply intervals by the block price. You can also mix wholesale indices (OMIE_ES_DA) with margins.
  • Day-ahead pass-through: multiply each interval by the corresponding hourly price from /electricity/hourly or /electricity/pvpc.
  • Add riders (carbon, gas index) using /timeseries averages or /latest snapshots per your tariff contract.

Step 5: Taxes, network, and levies

  • Apply regulated components as configured in your billing engine. While Energy API focuses on market data, keeping each line item as a separate component ensures clarity and agrees with regulatory invoice formats.

Step 6: Evidence pack for disputes

  • Store: meter intervals, price curve with timestamps, source symbol, publication dates, and computed line items. Attach the raw JSON snippets from Energy API per settled day for complete auditability.
  • On dispute, retrieve the exact JSON curve and show interval-by-interval calculations with timezone, rounding policy, and currency conversions.

Applying Netting and Tariff Rules with Code

Below are simplified code patterns to take hourly net consumption and multiply by an hourly curve from Energy API. Adjust for 15-min intervals, export credits, and currency conversion as needed.

Python: Hourly pass-through using OMIE day-ahead

import requests
from decimal import Decimal, ROUND_HALF_UP

BASE = "https://energy-api.com/api/v1"
API_KEY = "YOUR_API_KEY"

def get_curve(symbol: str, date: str):
r = requests.get(
f"{BASE}/electricity/hourly",
params={"symbol": symbol, "date": date, "api_key": API_KEY},
timeout=30,
)
r.raise_for_status()
data = r.json()
assert data["success"]
return data["currency"], data["curve"]

def settle_hourly_pass_through(net_kwh_by_ts, curve):
# net_kwh_by_ts: dict[timestamp_iso] -> kWh
# curve: [{"timestamp": iso, "price": float}]
price_by_ts = {p["timestamp"]: Decimal(str(p["price"])) for p in curve}
total_energy_cost = Decimal("0")
details = []
for ts, kwh in net_kwh_by_ts.items():
price = price_by_ts.get(ts)
if price is None:
# handle missing hour (e.g., DST): either interpolate or skip per policy
continue
# cost = price (e.g., EUR/MWh) * kWh/1000
cost = (price * Decimal(str(kwh)) / Decimal("1000")).quantize(Decimal("0.00001"), rounding=ROUND_HALF_UP)
total_energy_cost += cost
details.append({"timestamp": ts, "kwh": kwh, "price": float(price), "cost": float(cost)})
return float(total_energy_cost), details

if __name__ == "__main__":
currency, curve = get_curve("OMIE_ES_DA", "2026-06-10")
# Example net consumption dict—replace with real meter data:
net_kwh = {
"2026-06-10T00:00:00+02:00": 1.23,
"2026-06-10T01:00:00+02:00": 1.10,
# ... 22 more hours ...
}
total, lines = settle_hourly_pass_through(net_kwh, curve)
print("Currency:", currency)
print("Total energy cost:", total)
# Persist 'lines' as evidence with raw curve JSON.

JavaScript (Node): PVPC-based retail reconciliation

import fetch from "node-fetch";

const BASE = "https://energy-api.com/api/v1";
const API_KEY = "YOUR_API_KEY";

async function getPvpc(date) {
const url = new URL(`${BASE}/electricity/pvpc`);
url.searchParams.set("date", date);
url.searchParams.set("api_key", API_KEY);
const res = await fetch(url, { method: "GET", timeout: 30000 });
if (!res.ok) throw new Error(`PVPC fetch failed: ${res.status}`);
const json = await res.json();
if (!json.success) throw new Error(`PVPC error: ${json.error}`);
return json;
}

function settlePvpc(netKwhByTs, pvpcCurve) {
const map = new Map(pvpcCurve.map(p => [p.timestamp, p.price]));
let total = 0;
const lines = [];
for (const [ts, kwh] of Object.entries(netKwhByTs)) {
const price = map.get(ts);
if (price == null) continue; // handle per policy
const cost = (price * kwh); // PVPC is already in EUR/kWh
total += cost;
lines.push({ timestamp: ts, kwh, price, cost });
}
return { total, lines };
}

(async () => {
const pvpc = await getPvpc("2026-06-10");
const netKwh = {
"2026-06-10T00:00:00+02:00": 0.88,
"2026-06-10T01:00:00+02:00": 0.80
// ...rest of the day...
};
const { total, lines } = settlePvpc(netKwh, pvpc.pvpc);
console.log("PVPC total EUR:", total.toFixed(5));
})();

Both approaches demonstrate a clean separation: fetch normalized market data from Energy API, align timestamps to interval reads, compute per-interval charges, and persist detailed lines for audit and disputes.

Building Dispute-Ready Workflows

Disputes usually arise because of one of the following: different clocks (DST or timezone mismatches), missing intervals or late publications, misunderstanding of tariff rules (peak/off-peak windows, export credits), or currency/rounding policies. Your best defense is a reproducible pack that includes:

  • Raw meter intervals (import, export, net) with timestamps and timezone.
  • Exact price curve JSON returned by Energy API for the settlement date and symbol.
  • The symbol list and metadata from /symbols to prove the source and category.
  • Per-interval calculations (kWh × price) including unit conversions (EUR/MWh to EUR/kWh = divide by 1000).
  • Any riders (EUA_CO2, TTF_GAS) with a daily timeseries or latest snapshot and a clear method to compute monthly averages.
  • The publication health snapshot (/status) in case of late publications requiring adjustments.

Here’s a minimal JSON structure you could persist per customer per bill:

{
"customer_id": "CUST-12345",
"bill_period": {"start": "2026-06-01", "end": "2026-06-30"},
"meter_id": "ES1234567890",
"timezone": "Europe/Madrid",
"tariff": {
"type": "day_ahead_pass_through",
"symbol": "OMIE_ES_DA",
"currency": "EUR",
"riders": [{"symbol": "EUA_CO2", "method": "monthly_avg", "applied_rate": 68.12}]
},
"sources": {
"electricity_curve": {
"endpoint": "/electricity/hourly",
"symbol": "OMIE_ES_DA",
"date": "2026-06-10",
"response_json": { /* store exact response from Energy API */ }
},
"status": { /* /status response at settlement time */ }
},
"calculations": [
{"timestamp": "2026-06-10T00:00:00+02:00", "kwh": 1.23, "price_EUR_MWh": 78.43, "cost_EUR": 0.09649},
/* ... per interval ... */
],
"totals": {"energy_cost_EUR": 34.551, "riders_EUR": 2.118, "taxes_EUR": 5.004, "grand_total_EUR": 41.673}
}

With this schema, recreating a bill is straightforward and defensible. You can expose this data in a customer portal for full transparency and faster dispute resolution.

Error Handling and Data Quality Best Practices

No reconciliation flow is complete without robust error handling. Energy API standardizes error responses across endpoints:

  • 401: missing or invalid credentials. Surface a clear internal alert; do not present raw errors to customers.
  • 404: no data for requested symbol/date. In settlement, treat this as a soft failure; retry when the source is expected to publish later that day.
  • 422: validation error (bad date, unsupported symbol). Validate inputs earlier in your job so the fault doesn’t reach production runs.
  • 429: rate limits. Implement exponential backoff with jitter. Persist partial progress so you can resume gracefully.

Standard error shape:

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

Additional tips:

  • Always check /status before a big settlement batch. Pause if a critical source is not “ok.”
  • Guard against daylight saving time. If a timestamp from the curve is missing in your meter data (or vice versa), follow a documented rule (interpolate, prorate, or skip and flag).
  • Keep currency explicit end-to-end. Electricity prices might be in EUR/MWh, PVPC in EUR/kWh, and fuels in USD or EUR. Convert once, in a dedicated step, with consistent rounding.
  • When disputes occur, respond with the exact Energy API JSON payload used for that bill cycle. Storing the raw response avoids arguments about data drifts or holiday adjustments.

Real-World Use Cases

1) Automated PVPC residential billing with transparency

A Spanish retailer bills residential customers using PVPC references. The engine fetches hourly PVPC via /electricity/pvpc for each settlement day, multiplies by net import kWh, and renders per-hour lines in the customer portal. Optional riders (EUA_CO2 monthly average via /timeseries) are added as a separate line item with a clear calculation method.

Endpoints: /electricity/pvpc, /timeseries, /status

2) Industrial pass-through with day-ahead auctions

An industrial C&I client is billed on OMIE day-ahead pass-through with a fixed margin. The platform uses /forecast to post next-day estimated costs to the client’s dashboard minutes after auction results publish, and /electricity/hourly for the final reconciliation. Variance explanations are generated by comparing the /forecast curve to the actual curve used during invoicing.

Endpoints: /forecast, /electricity/hourly, /status

3) Dual-fuel SME contracts with carbon surcharge

A supplier bills electricity using EPEX day-ahead and gas on TTF day-ahead, with a monthly EUA allowance pass-through. The reconciliation job aggregates meter intervals, fetches /latest and /timeseries for TTF_GAS and EUA_CO2, and applies a monthly average rider. A shared JSON schema means the SME billing code paths look identical for gas and power.

Endpoints: /latest, /timeseries, /electricity/hourly, /status

Additional Endpoint Patterns You’ll Likely Use

Historical snapshots: GET /historical

When you need the value on a specific past date, /historical returns the price for that day or the most recent prior publishing day if it was a holiday. This is convenient for month-end adjustments and backfills.

curl -G https://energy-api.com/api/v1/historical \
--data-urlencode "date=2026-05-15" \
--data-urlencode "symbols=TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
{
"success": true,
"date": "2026-05-15",
"base": "MIXED",
"rates": {
"TTF_GAS": 37.10,
"EUA_CO2": 66.85
},
"currencies": {
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}

Fluctuation analytics: GET /fluctuation

To explain bill changes month over month, fluctuation reports provide start_value, end_value, change, and change_pct per symbol. Embed these explanations in customer communications or internal P&L reviews to reduce disputes preemptively.

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

Example response:

{
"success": true,
"period": {"start": "2026-05-01", "end": "2026-05-31"},
"symbols": {
"OMIE_ES_DA": {
"start_value": 76.55,
"end_value": 82.10,
"change": 5.55,
"change_pct": 7.25
},
"EUA_CO2": {
"start_value": 66.90,
"end_value": 68.80,
"change": 1.90,
"change_pct": 2.84
}
}
}

Use this to auto-generate a “why your bill changed” narrative: “Day-ahead prices increased 7.25% from early to late May, contributing €X to your energy cost.”

FAQ

How do I reconcile 15-minute meters with hourly auction curves?

Resample your meter data or the price curve to a common resolution. A practical approach is to allocate the hourly price pro-rata to the four sub-intervals (each 15-minute interval receives one quarter of the hourly price). Keep a record of the resampling method in your evidence pack to maintain auditability.

Can I request electricity, gas, and carbon prices in the same call?

Yes. Endpoints like /latest and /timeseries accept multiple symbols across commodities. This is ideal for dual-fuel billing and for adding a carbon allowance rider to power invoices without juggling multiple services.

What happens on holidays or non-publishing days?

/historical will return the most recent value before the requested date when the market didn’t publish. For hourly settlement, use the actual hourly curves on published days and follow your regulated policy for non-publishing periods (e.g., nearest published curve or contract-specific handling).

How do I guard my billing runs from incomplete data?

Check /status prior to executing a settlement batch. If a required source is degraded, pause the run and retry with exponential backoff. If you must invoice, generate a provisional invoice tagged for adjustment and store the /status snapshot alongside your evidence.

How should I store responses for audit and disputes?

Persist the exact JSON returned by Energy API for each settlement date and symbol, along with your input meter intervals and any tariff configurations. This guarantees reproducibility of customer bills and accelerates dispute resolution by providing a time-stamped, tamper-evident record of the inputs.

Conclusion and Call to Action

Accurate, defensible meter-to-bill reconciliation hinges on trustworthy price curves, consistent schemas, and deterministic publishing. By using Energy API’s unified REST surface, you eliminate the toil of stitching together OMIE, ENTSO-E, ESIOS, EIA/FRED, and other sources, and you gain a standard interface you can apply across electricity, gas, oil, coal, carbon allowances, and carbon intensity. The result: fewer disputes, faster cash, and a leaner engineering footprint.

Whether you’re building PVPC retail reconciliation, C&I pass-throughs, or dual-fuel contracts with carbon riders, the same set of endpoints—/electricity/hourly, /electricity/pvpc, /forecast, /latest, /timeseries, /historical, and /status—power your netting, tariff rules, and audit trail. The combination of normalized symbols, clear JSON, and multi-commodity support lets you ship production-grade billing workflows in days, not weeks.

Start integrating today. Explore the endpoints, wire health checks, and stand up a dispute-ready evidence store with a few calls to Energy API. Ready to build faster? Try Energy API for free and put end-to-end meter-to-bill reconciliation into production with confidence.

Ready to get started?

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

Get API Key

Related posts