On this page

API documentation

One REST API for European power prices and probabilistic forecasts. Base URL https://voltcast.com/api · JSON everywhere · all timestamps UTC (ISO 8601).

Machine-readable spec: /openapi.json · SDKs: Python · TypeScript · Integrations

Quickstart

1. Try it right now — no account, no key, nothing to install:

Request
curl "https://voltcast.com/api/v1/demo/prices?zone=DE-LU"

Real day-ahead prices, last 48h + tomorrow. Also keyless: GET /v1/zones (the full registry), GET /v1/briefing/{zone} (plain-language daily briefing), GET /v1/accuracy (the live scorecard).

  1. 2. Like what you see? Start with Home at €9/month. Complete Stripe checkout, create an API key on the dashboard, then choose the one European bidding zone included for prices and history; Croatia (HR) and every other price-enabled European zone are available.
  2. 3. Fetch your zone's full curve with the key:
Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/prices/DE-LU"

Returns yesterday → tomorrow at native resolution. That's it — you're consuming the 15-minute market.

Authentication

Pass your API key as a bearer token on every keyed request:

Request
Authorization: Bearer YOUR_API_KEY

Keys are created and revoked on the dashboard. A missing or invalid key returns 401. Keys inherit your plan's entitlements.

Core concepts

Zones & EIC codes

Zones use short codes (DE-LU, SE3, AU-NSW, US-SP15). GET /v1/zones lists all of them — Europe plus world markets — with region, currency and EIC codes.

The resolution seam

Day-ahead switched from hourly to 15-minute periods on 2025-10-01. Every price row carries a resolution_flag (PT15M/PT60M) so mixed history is always explicit.

Delivery periods

A price applies to [delivery_start, delivery_end) UTC. A normal post-seam day has 96 periods; DST days have 92 or 100 — never assume 96.

Probabilistic forecasts

P50 is the median path; P10/P90 bound an 80% interval. Every forecast response links the zone's live accuracy record — verified daily, walk-forward.

Plans & rate limits

Free (legacy)HomeStarterProScale
Zones (prices & grid data)any 1, your choiceany 1, your choiceallallall
History7 days90 days1 yearfullfull
Forecast48h P507d P507d P507d P10–P907d P10–P90
Webhook rules13unlimitedunlimited
Load, generation & carbon
Wind/solar + weather forecasts
Bulk export
Rate limit30/min60/min120/min600/min1500/min

Home is the lowest plan available to new accounts. Existing grandfathered Free accounts remain active with their original limits. Every response includes X-RateLimit-Limit and X-RateLimit-Remaining; exceeding the limit returns 429 with Retry-After. Grandfathered Free and Home plans are scoped to one zone of your choice across keyed price, forecast, grid, capture and webhook APIs — set or switch it at no cost on the dashboard.

GET /v1/zones public

List all market areas and reference prices. Geographic areas render as polygons; overlapping trading hubs, DLAPs and WEIM aggregate nodes carry entity_type=reference plus point coordinates. Every row declares native currency, resolution, market product and coverage notes.

Request
curl "https://voltcast.com/api/v1/zones"
Response 200
{
  "data": [
    {
      "code": "DE-LU",
      "eic_code": "10Y1001A1001A82H",
      "name": "Germany-Luxembourg",
      "country_code": "DE",
      "timezone": "Europe/Berlin",
      "currency": "EUR",
      "region": "europe",
      "native_resolution": "PT15M",
      "fifteen_min_since": "2025-10-01",
      "launch_zone": true
    },
    {
      "code": "AU-NSW",
      "name": "New South Wales (NEM)",
      "country_code": "AU",
      "timezone": "Australia/Sydney",
      "currency": "AUD",
      "region": "apac",
      "native_resolution": "PT5M",
      "coverage_note": "Real-time 5-minute dispatch prices (the NEM has no day-ahead auction). Source: AEMO."
    }
  ],
  "meta": { "count": 57 }
}

Prices are always served in the zone's native currency (see meta.currency / meta.unit on price responses): EUR across most of Europe, UAH for Ukraine, GBP for Great Britain, TRY for Türkiye, AUD for the NEM and USD for US markets.

GET /v1/prices/{zone} API key

Day-ahead prices at native resolution (15-minute post-seam, hourly before), source-collapsed and gap-honest.

GET /v1/prices/{zone}/real-time API key

Explicit real-time market prices, currently WEIM five-minute LMPs. These rows are structurally separate from day-ahead curves and carry market, source and native resolution on every interval.

GET /v1/compat/awattar/{de|at}/marketdata public

Drop-in aWATTar-compatible endpoint (awattar.de now redirects to tado° Energy): identical JSON shape — object/list, epoch-ms timestamps, hourly marketprice in Eur/MWh, same start/end params. Keyless and free, like the original. Migration guide →

GET /v1/indices/bess public

The European BESS Revenue Index: monthly battery revenue benchmark per zone (perfect-foresight DA arbitrage ceiling per MW, 2h/4h systems, + FCR capacity revenue where auctions are public). Keyless, free to cite with attribution.

ParamTypeDescription
fromdateStart (inclusive). Default: yesterday 00:00 UTC.
todateEnd (exclusive). Default: tomorrow 24:00 UTC. Max span 100 days — use bulk export beyond.
resolutionenumnative (default) or hourly (15-minute periods averaged per hour at read time).
Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/prices/DE-LU?from=2026-07-10&to=2026-07-12"
Response 200
{
  "data": [
    {
      "delivery_start": "2026-07-10T00:00:00Z",
      "delivery_end": "2026-07-10T00:15:00Z",
      "price_eur_mwh": 128.44,
      "resolution_flag": "PT15M",
      "source": "smard"
    }
  ],
  "meta": {
    "zone": "DE-LU",
    "unit": "EUR/MWh",
    "count": 192,
    "attribution": ["Data source: SMARD.de, Bundesnetzagentur | CC BY 4.0."],
    "license_note": "…"
  }
}
GET /v1/forecasts/{zone} API key

The latest issued probabilistic forecast curve, at 15-minute resolution, up to 7 days ahead. Reissued daily after the ~13:00 CET auction. P50 follows the account's zone entitlement: Home and grandfathered Free receive their selected zone; Starter and above include all zones. Horizon depth, P10/P90 and commercial-use rights vary by plan.

ParamTypeDescription
horizonenum48h or 7d (default). Capped by your plan.
Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/forecasts/DE-LU?horizon=48h"
Response 200
{
  "data": [
    {
      "target_start": "2026-07-11T00:00:00Z",
      "resolution_flag": "PT15M",
      "p50": 100.53,
      "p10": 73.12,
      "p90": 126.25
    }
  ],
  "meta": {
    "zone": "DE-LU",
    "model_version": "volt-2026.07.10",
    "issued_at": "2026-07-10T11:35:12Z",
    "quantiles": [10, 50, 90],
    "accuracy": "https://voltcast.com/accuracy#DE-LU",
    "unit": "EUR/MWh"
  }
}

P10/P90 require Pro. Grandfathered Free, Home and Starter receive p50 only. Never trust a forecast blindly — check its live scorecard first; that's what it's for.

GET /v1/imbalance/{zone} API key Pro+

Imbalance prices, revision-aware. Coverage: DE-LU, BE, NL, AT, FR, GB, plus Belgium's 1-minute NRT feed aggregated per 15-minute period.

ParamDescription
from / toWindow (default: last 24h). Max 31 days.
price_typeshort (insufficient balance) · long (excess) · imbalance-nrt (BE 1-minute NRT mean)
revisionslatest (default) or all — TSOs revise imbalance prices; we store every revision, never overwrite.
Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/imbalance/BE?price_type=short&revisions=all"

Note: Germany's quality-assured reBAP is published by the TSOs with a lag of several weeks — recent DE-LU periods fill in as settlement runs publish (that's the market, not a gap on our side; an empty window returns meta.latest_available so you can see where the data ends). Enterprise early access to wider TSO coverage via sales@voltcast.com.

GET /v1/imbalance/{zone}/forecast API key Pro+ · BETA

Short-horizon imbalance-price forecast: P10/P50/P90 for the settled short price up to 12h ahead, 15-minute periods. Issued continuously as the underlying feeds refresh; accuracy vs last-known-value persistence accumulates publicly on /accuracy. Coverage starts with BE (best NRT feed) and expands as source freshness allows.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/imbalance/BE/forecast"

Intraday auctions 9 zones

Claims discipline, up front: these are intraday auction prices (IDA1/IDA2/IDA3, 15-minute resolution) — not EPEX/Nord Pool continuous trading (ID1/ID3/ID-AEP), which is exchange-proprietary data that requires a redistribution license. Coverage: ES + PT via OMIE and all 7 Italian zones via GME (MI-A sessions, aggregate results are public domain per the GME market rules); more zones the day their TSOs publish IDA results.

GET /v1/intraday/{zone} API key

All three IDA curves beside the day-ahead price, with per-period ida1_da_spread. IDA1 (~15:20 local D-1) and IDA2 (~22:20 local D-1) cover the full delivery day; IDA3 (~10:20 local D) covers the second half.

GET /v1/intraday/{zone}/spread API key v1 model: Scale

DA-vs-IDA1 spread history (daily mean/abs/max), spread_forecast_v0 (per-slot climatology — the disclosed baseline, free with the endpoint) and spread_forecast_v1: the ML model (volt-spread-1), issued after the DA auction and before the 15:00 local IDA1 gate — forward-blind — and scored daily against the v0 climatology on identical slots. Losses shown.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/intraday/IT-NORD?session=1"

The ida_published webhook event fires within minutes of each session's results. Attribution: OMIE (ES/PT) · GME (IT).

Cross-border flows & EXAA

GET /v1/flows/{zone} API key

Physical cross-border flows (ENTSO-E A11): net export per border per period, signed from {zone}'s perspective. What the interconnectors actually carried — near-real-time, ~1h lag. Also the flow overlay on the live map.

GET /v1/exaa/{zone} API key

EXAA spot auctions for AT + DE-LU: the 10:15 grey/green auctions (clearing before SDAC — a leading price signal) and the 12:00 market coupling, beside the SDAC price with exaa_da_spread. Params: auction=grey|green|market_coupling.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/flows/DE-LU"

GB borders are absent from the ENTSO-E platform post-Brexit — shown as missing, not guessed. EXAA attribution: EXAA Abwicklungsstelle für Energieprodukte AG.

GET /v1/ancillary/{zone} API key Pro+

FCR / aFRR / mFRR reserve prices — capacity blocks (EUR/MW) and 15-minute balancing-energy slots (EUR/MWh), average + marginal accepted bids. Coverage: DE-LU via regelleistung.net and FI via Fingrid (FCR-N/FCR-D/aFRR/mFRR hourly).

ParamDescription
productFCR (symmetric) · aFRR · mFRR
marketcapacity (4h blocks, EUR/MW) · energy (15-min slots, EUR/MWh)
from / toWindow (default: last 7 days). Max 92 days.
Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/ancillary/DE-LU?product=aFRR&market=capacity"

This is the revenue-stacking dataset for batteries and flexible assets: pair it with the battery simulator and imbalance prices.

GET /v1/outages/{zone} API key

Generation-unavailability events (planned + forced, ENTSO-E A80): unit, fuel, unavailable MW, event window — revision-aware (revisions=all for the audit trail). Params: from, to, type=planned|forced, min_mw.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/outages/FR?type=forced&min_mw=500"

Outages move prices. Subscribe to the unavailability_published webhook event to get pushed the moment a new outage message lands — set the rule's threshold_eur_mwh to use it as a minimum-MW filter for this event.

GET /v1/load/{zone} API key

Total load: realised (actual) and the day-ahead forecast (forecast_da — published before the auction, the same series our models use). Params: from, to, kind=actual|forecast_da|all.

GET /v1/generation/{zone} API key

Actual generation mix by fuel type (wind, solar, gas, nuclear, hydro, …) per settlement period, in MW with a per-slot total.

GET /v1/grid/us/balancing-authorities API key

EIA-930 balancing-authority registry. Grid identity is separate from market-price zones.

GET /v1/grid/us/balancing-authorities/{code} API key

Hourly EIA-930 demand, day-ahead demand forecast, net generation, fuel mix and signed BA-pair interchange. Public-domain US grid data; not a wholesale clearing price.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/generation/DE-LU"
Response 200 (excerpt)
{
  "data": [
    {
      "ts": "2026-07-11T06:00:00Z",
      "resolution_flag": "PT15M",
      "total_mw": 61240.0,
      "mix_mw": { "gas": 4210.0, "solar": 18730.5, "wind_onshore": 12480.2, "...": 0 }
    }
  ]
}

Default window: last 24h through +36h (load forecasts extend into tomorrow). Max 31 days per request. GB included via Elexon BMRS (FUELHH generation by fuel + INDO demand, 30-minute periods; transmission-metered — embedded solar/wind behind the meter is invisible to FUELHH, disclosed here rather than guessed). Türkiye included via EPİAŞ hourly real-time consumption, D-1 load plan and resource-level aggregate generation. EPİAŞ reports hourly MWh, which is numerically equal to average MW over each one-hour interval. Aggregate import/export is excluded from domestic generation because it has no counterparty breakdown; the carbon methodology is generation-only, consistently across all zones.

GET /v1/carbon/{zone} API key

Carbon intensity (gCO2eq/kWh) and green score per settlement period, derived from the live generation mix.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/carbon/DE-LU"
Response 200 (excerpt)
{
  "data": [
    {
      "ts": "2026-07-11T06:00:00Z",
      "intensity_gco2eq_kwh": 187.4,
      "renewable_share_pct": 58.1,
      "low_carbon_share_pct": 64.3,
      "green_score": 64
    }
  ]
}

Method, fully disclosed: generation-mix-weighted lifecycle emission factors (IPCC AR5 WG3 Annex III medians — e.g. wind 11, solar 45, gas 490, hard coal 820 gCO2eq/kWh). green_score = low-carbon share of generation (renewables + nuclear), 0–100. Values describe the production mix (generator-side), not flow-traced consumption. Storage discharge (pumped storage, batteries) is excluded from the renewable and low-carbon shares — Eurostat/IEA accounting: storage moves energy, it doesn't generate it — and stays in total generation with a hydro-like proxy factor at discharge, a disclosed simplification. Pair with optimization to charge when the grid is greenest, not just cheapest.

GET /v1/carbon/auctions?market=EU&days=365 API key Pro+

EU ETS allowance (EUA) primary auction results — the carbon price that sets the coal-to-gas switching band. Per auction: clearing price €/tCO2, volume, cover_ratio (bid volume / auction volume — the demand signal), bidder counts and revenue. market = EU (common auction, default), DE, PL, NIR or ALL; product=EUAA for aviation allowances. History from 2020.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/carbon/auctions?market=EU&days=90"

Updated weekdays minutes after the ~11:00 CET auctions clear (EU common auctions Mon/Tue/Thu, DE Fri, PL Wed — per the EEX calendar). Source: EEX (European Energy Exchange), primary market auction results, redistributed with permission and attribution. Scope is honest and narrow: primary auction results only — EEX spot, futures and index data are licensed products we neither serve nor redistribute.

MCP server (AI agents)

Voltcast ships a native Model Context Protocol server, so AI agents (Claude, Cursor, custom agents) can query prices, forecasts, carbon and optimization directly. Streamable HTTP transport at:

Request
https://voltcast.com/api/mcp
Client config (e.g. Claude Desktop / Cursor)
{
  "mcpServers": {
    "voltcast": {
      "url": "https://voltcast.com/api/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

Tools: list_zones (no auth) · get_prices · get_forecast · get_carbon · get_renewables · cheapest_window. Tool calls run through the exact same entitlements and rate limits as the REST API — your key, your plan.

GET /v1/risk/negative/{zone} API key Pro+ full

The negative-price risk calendar: P(price < 0) per 15-minute period up to 14 days ahead, with daily aggregates. Home, Starter and grandfathered Free receive a 48h teaser. Brier-scored daily against trailing climatology — publicly.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/risk/negative/DE-LU?days=14"
Response 200
{
  "data": {
    "curve": [ { "target_start": "2026-07-12T11:00:00Z", "p_negative": 0.64 } ],
    "daily": [
      { "date": "2026-07-12", "max_p_negative": 0.72,
        "expected_negative_hours": 3.5, "periods_above_50pct": 12 }
    ]
  },
  "meta": { "zone": "DE-LU", "model_version": "volt-2026.07.11" }
}

Why it matters: under the Solarspitzengesetz, new installations lose their EEG premium during negative-price periods — P(negative) is direct P&L. Pair with the negative_prices webhook for day-ahead confirmation.

POST /v1/optimize/cheapest-window API key Pro+

The cheapest contiguous time window(s) for a flexible load, over published prices where available and the latest P50 forecast beyond.

Request
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"zone":"DE-LU","duration_minutes":120,"count":3}' \
  "https://voltcast.com/api/v1/optimize/cheapest-window"
Response 200
{
  "data": [
    {
      "start": "2026-07-11T11:00:00Z",
      "end": "2026-07-11T13:00:00Z",
      "avg_price_eur_mwh": 42.15,
      "basis": "published"
    }
  ],
  "meta": { "zone": "DE-LU", "curve_basis": { "published": 96, "forecast": 480 } }
}

basis tells you whether a window rests on published auction prices or forecast — treat forecast-based windows with the uncertainty the scorecard quantifies.

POST /v1/optimize/schedule API key Pro+

A cost-optimal charge/dispatch schedule: deliver a given energy amount before a deadline at limited power, in the cheapest 15-minute periods.

Request
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"zone":"DE-LU","energy_kwh":40,"max_power_kw":11,"deadline":"2026-07-11T07:00:00Z"}' \
  "https://voltcast.com/api/v1/optimize/schedule"
Response 200
{
  "data": {
    "schedule": [
      { "start": "2026-07-11T01:15:00Z", "end": "2026-07-11T01:30:00Z",
        "power_kw": 11, "energy_kwh": 2.75, "price_eur_mwh": 38.20, "basis": "published" }
    ],
    "energy_kwh": 40,
    "expected_cost_eur": 1.62,
    "baseline_cost_eur": 3.41,
    "savings_eur": 1.79,
    "savings_pct": 52.5
  }
}

The baseline is "charge immediately at full power" — savings_eur is the honest difference, not a marketing number.

POST /v1/optimize/battery API key Pro+

Battery arbitrage simulator: charge-low / discharge-high schedule and revenue estimate for a battery (capacity, power, round-trip efficiency, cycle budget). Point from/to at a past window for a backtest: "what would this battery have earned?"

Request
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"zone":"DE-LU","capacity_kwh":4000,"max_power_kw":2000,
       "round_trip_efficiency":0.88,"from":"2026-06-01","to":"2026-07-01"}' \
  "https://voltcast.com/api/v1/optimize/battery"
Response 200 (excerpt)
{
  "data": {
    "cycles": [ { "day": "2026-06-01", "charge": {"start": "…", "avg_price_eur_mwh": 12.4},
                  "discharge": {"start": "…", "avg_price_eur_mwh": 94.1},
                  "revenue_eur": 287.05, "spread_eur_mwh": 81.7 } ],
    "summary": { "days": 30, "cycles_used": 30, "total_revenue_eur": 6110.20,
                 "avg_spread_eur_mwh": 78.9, "annualized_revenue_per_mw_eur": 37170 }
  },
  "meta": { "mode": "backtest", "honesty": "Screening-grade… perfect foresight…" }
}

Honest by construction: day-ahead arbitrage only (no reserve co-optimization — see ancillary prices for what stacking adds), no grid fees/taxes/degradation, and backtests use realized prices = perfect foresight. Treat results as a screening estimate, not a revenue promise.

GET /v1/history/export API key Pro+

Bulk history as pre-generated zone-year files (parquet or CSV) via short-lived signed URLs. Zero egress fees.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/history/export?zone=DE-LU&from=2018-01-01&to=2026-12-31&format=parquet"
Response 200
{
  "data": [
    {
      "year": 2018,
      "format": "parquet",
      "size_bytes": 141888,
      "url": "https://…signed…",
      "expires_at": "2026-07-10T13:05:00+00:00"
    }
  ],
  "meta": { "zone": "DE-LU", "count": 9 }
}

URLs expire after 30 minutes — request fresh ones rather than storing them. Files contain zone, delivery_start_utc, delivery_end_utc, price_eur_mwh, resolution_minutes, source.

POST /v1/webhooks API key Home+

Create an event rule. Voltcast POSTs to your URL seconds after the day-ahead auction publishes.

FieldDescription
urlYour HTTPS endpoint.
eventauction_published · ida_published · price_below · price_above · negative_prices · unavailability_published
zoneOptional zone code. Home rules are always bound to the selected zone (and default to it when omitted); multi-zone plans may omit it for all zones.
threshold_eur_mwhRequired for price_below/price_above.
Request
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your.app/hooks/voltcast","event":"negative_prices","zone":"DE-LU"}' \
  "https://voltcast.com/api/v1/webhooks"

The response includes your signing secret exactly once. Manage rules with GET /v1/webhooks and DELETE /v1/webhooks/{id}.

Verifying deliveries

Every delivery is signed. Recompute the HMAC and compare before trusting a payload:

Headers
X-Voltcast-Event: negative_prices
X-Voltcast-Delivery: 42
X-Voltcast-Signature: t=1783087562,v1=<hex hmac>
Python verification
import hashlib, hmac

def verify(secret: str, signature_header: str, body: bytes) -> bool:
    t, v1 = [p.split("=", 1)[1] for p in signature_header.split(",")]
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, v1)

Respond with any 2xx within 10 seconds. Failures retry at 1m, 5m, 30m and 2h (5 attempts total).

Capture Index keyless + tiered

Market value = Σ generation×price ÷ Σ generation per period (15-minute slot grid, interval-weighted across the 2025-10 resolution seam); capture rate = market value ÷ baseload mean; NEG = the technology's generation share sold below €0. Provisional rows recompute daily while ENTSO-E actuals revise; frozen rows (month_end + 12 days) never restate. Full spec: /capture/methodology — the same text this section quotes, single-sourced.

GET /v1/public/capture/{zone} API key Public, keyless

Latest 13 months, all technologies, status-labeled. The full monthly index for every zone is a free CSV at /capture.csv — attribution line embedded.

GET /v1/capture/{zone} API key Home: monthly · Pro: +daily, 5y · Scale: full history

Capture stats from the index. Grandfathered Free keys retain their monthly 24-month view. Params: technology (solar | wind_onshore | wind_offshore | wind), grain (month | day), from/to.

GET /v1/capture/forecast/{zone} API key Scale

Forward capture, 1–7 days: P50 generation × P50 price (v0 — tends to run high in high-RES regimes, bias printed; bias-corrected v1 in shadow, both scored daily on realized capture).

POST /v1/capture/profile API key Scale (3 runs/month teaser)

Upload a 15-minute or hourly generation profile → realized market value, capture rate and negative-price exposure vs an entitled zone — the same math library as the index. Body: {zone, profile: [{ts, mw}…]}.

Request
curl "https://voltcast.com/api/v1/public/capture/de-lu"

Webhook events capture_monthly_final and capture_record_low fire the moment a month freezes (Pro+, see webhooks).

PPA analytics Scale

POST /v1/ppa/value API key Scale

Pay-as-produced PPA backcast: monthly (capture − strike) settlements over up to 36 months — what the deal would have paid, month by month. Capture history itself lives in the Capture Index.

Request
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"zone":"DE-LU","technology":"solar","strike_eur_mwh":55}' \
  "https://voltcast.com/api/v1/ppa/value"
Response 200 (excerpt)
{
  "data": {
    "months": [ { "month": "2026-06", "capture_price_eur_mwh": 31.2, "baseload_price_eur_mwh": 63.8,
                  "capture_rate": 0.489, "settlement_eur_mwh": -23.8 } ],
    "summary": { "avg_capture_rate": 0.51, "avg_settlement_eur_mwh": -19.4,
                 "months_below_strike": 10, "worst_month_eur_mwh": -31.2 }
  }
}

Method, disclosed: capture price = generation-weighted average day-ahead price (ENTSO-E A75 × our price history); months with insufficient generation data are omitted, never interpolated. This is a screening backcast, not a forward valuation — no price simulation or credit/profile adjustments. Capture history deepens automatically as the generation backfill extends.

Retailer risk simulation Scale

For suppliers obligated to offer dynamic tariffs: what does serving a customer portfolio cost across real market months, and how much does hedging change the tail?

POST /v1/simulate/retailer API key Scale

Procurement-cost distribution (p5/p50/p95, cost-at-risk) for a load profile served at spot, blended with a hedged share at a fixed price. Params: profile=baseload|household|business, hedge_ratio 0–1, fixed_price_eur_mwh, window up to 60 months.

Request
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"zone":"DE-LU","profile":"household","hedge_ratio":0.5}' \
  "https://voltcast.com/api/v1/simulate/retailer"
Response 200 (excerpt)
{
  "data": {
    "summary": { "months_simulated": 24, "hedge_ratio": 0.5,
                 "portfolio_cost_p50_eur_mwh": 78.4, "portfolio_cost_p95_eur_mwh": 132.7,
                 "cost_at_risk_eur_mwh": 54.3, "avg_profile_premium_eur_mwh": 6.1 }
  }
}

Historical simulation over realized spot months — a risk screen, not a hedging recommendation. Standard profiles are synthetic (shapes disclosed); custom profile upload is on the roadmap. White-label use is permitted on Scale with attribution — built for consultants serving municipal utilities.

Renewables & weather

GET /v1/renewables/{zone} API key Pro+

Two day-ahead wind + solar forecasts side by side: the TSO's official one (ENTSO-E A69, *_forecast_mw) and our own model (*_voltcast_mw with a q10–q90 band), next to realized generation. The verification block in every response scores both against actuals on the same slots — voltcast_beats_tso tells you honestly whether we add value on top of the TSO.

GET /v1/weather/{zone} API key Pro+

Market-facing weather at the zone centroid: the leakage-free previous-run point forecast (temp, wind, radiation, cloud) plus the ~40-member wind-ensemble band (mean/std/min/max) up to 7 days out.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/renewables/DE-LU"

Built for the same question the price product answers — "what will the grid actually do tomorrow?" — with the same accountability: every forecast series ships with its own measured error. Our model (volt-res-1) learns the TSO's residual from inputs knowable at issue time, applied with a validated shrinkage weight — where we don't add value, the weight selects zero and our forecast equals the TSO's rather than degrading it. The verification answers exactly one question: do we add value on top? Head-to-head record on the accuracy page.

GET /v1/gas/storage/{area}?days=90 API key Pro+

European gas storage from GIE AGSI+ — the winter power-price driver. Per country (DE, FR, …) or the EU aggregate: fill % of working gas volume, TWh in storage, daily injection/withdrawal — plus the 5-year band for today's day-of-year and the distance to its minimum in percentage points, so a fill number becomes a signal.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/gas/storage/EU"

Daily after GIE's evening publication, history from 2020 for the band. Source: GIE AGSI+ transparency platform, attributed in every response.

Temperature

Station-exact probabilistic daily Tmax/Tmin on the gauges markets and weather contracts actually settle on (Paris = Le Bourget, CME London = Heathrow — full registry), plus CME-city degree-day trackers and population-weighted zone temperature. Scored publicly every day on /accuracy.

GET /v1/temperature/stations public

The resolution-station registry: ICAO, coordinates, which segment settles on it, honest resolution notes (proxies disclosed), and a live reporting status — a stale settlement gauge is settlement risk.

GET /v1/temperature/{station}?kind=tmax API key Scale

Latest probabilistic forecasts per model version for D+1..D+5: quantiles (P05–P95) and 1°C bucket probabilities (bucket "26" = the finalized value rounds to 26°C — the exact shape daily markets quote), plus recent METAR-derived daily observations, day-of-year climatology and the trailing verification block.

GET /v1/degree-days/{city}?contract=HDD API key Scale

CME-city settle-index tracking (amsterdam, essen, london, paris): month-to-date HDD (base 18°C) / CAT from finalized station days, and the probabilistic projection of the FINAL monthly index (P10/P50/P90) — the distribution of the settle while the month is still running. Indicative, not official settlement data.

GET /v1/temperature/zone/{zone} API key Pro+

Population-weighted zone temperature — the RTE/Enedis-style demand metric (France swings ~2 GW of load per winter °C on this series). Two columns: temp_da_c (day-ahead, leakage-free — safe as a model feature) and temp_best_c (latest estimate).

GET /v1/features/temperature/{station}?kind=tmax API key Contact

The exact per-station training matrix volt-temp-1 consumes: HRES forecast per horizon (previous-runs — knowable at issue), climatology, observation lags, and the finalized label (null until matured, never imputed).

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/temperature/LFPB?kind=tmax"

Honesty & compliance: informational and analytical use only — never financial, trading or wagering advice. Three model versions run side by side (climatology, volt-temp-0 raw ECMWF ensemble, volt-temp-1 trained) and all are scored daily, losses included; the trained model serves only once it beats the disclosed baseline. Observations are METAR (the same ASOS feed public settlement pages display); rare QC divergences vs third-party finalized values are disclosed in the payload.

Forecast Bench open beta

The open, forward-blind EU day-ahead price forecasting leaderboard — voltcast.com/bench. Any active key, including grandfathered Free keys, can compete; the named Voltcast pre-auction P50 and persistence baseline are frozen before the same deadline with source/curve hashes, and losing months stay on the board.

POST /v1/bench/submissions API key

Submit tomorrow's curve (hourly or 15-minute points) before 12:00 Europe/Berlin on D-1 — enforced server-side, before SDAC results exist. Resubmission allowed until the deadline. method_url lets you link your approach.

GET /v1/bench/leaderboard?zone=DE-LU&window=30 public

Score-ordered leaderboard (MAE/RMSE over matched periods; ≥3 scored days to rank).

Verifiability: the literal scoring code running in production is published at /bench/scoring. Realized truth = the same source-collapsed curve GET /v1/prices serves — no special bench data. Rule changes are announced ahead and never retroactive.

ML feature matrices

Training your own price models? The hardest part isn't the model — it's assembling features that were actually knowable at issue time. We solved that for our own forecasts; point-in-time-correct rows are available by arrangement through contact sales.

GET /v1/features/{zone}?issue_from=2026-06-01&issue_to=2026-06-07&horizons=1,2 API key Contact

One row per (issue day, target 15-min slot): price lags, previous-run weather, grid drivers, day-ahead load/wind/solar forecasts, ensemble spread — each column documented with WHEN it becomes known — plus the realized target_price label (null until matured, never imputed). Max 7 issue days per request.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/features/DE-LU?issue_from=2026-06-01&horizons=1"

Why this is hard to fake: knowledge timestamps come from our live recorders — revision histories and arrival times deepen daily and cannot be reconstructed retroactively. Walk-forward backtests built on these rows are leakage-free by construction. Pair with the as-of API for arbitrary reconstruction.

GET /v1/features/{zone}/export API key Contact

Bulk training export: the full recorded history (~800k rows/zone) as Parquet, regenerated daily, identical column semantics to the row API. Returns a signed R2 download URL (expires after 30 minutes) — no egress metering games.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/features/DE-LU/export"

Point-in-time (as-of) API Scale

GET /v1/asof/{zone}?at=2026-07-03T14:03:00Z API key Scale

The market exactly as it was known at a moment in time: prices with arrival timestamps, the forecast that was live, imbalance prices at their then-current revision, outages as then published. For backtest integrity, audits and dispute resolution.

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/asof/DE-LU?at=2026-07-03T14:03:00Z"

Imbalance and outages are fully bitemporal — every revision stored, never overwritten. Knowledge timestamps begin at each recorder's start and deepen daily; that history cannot be reconstructed retroactively by anyone who starts recording later.

Vintages — the revision archive Scale

ENTSO-E overwrites revised values in place: TSO wind/solar forecasts change many times a day, actual load and generation settle silently after the first print. The vintages API returns every value exactly as it was published — revision 1 is the first print (with its observed publication time), later revisions are the corrections. Recording began 2026-07-17; the archive deepens daily and is physically impossible to backfill.

GET /v1/vintages/{zone}?series=wind_fc&amp;date=2026-07-17 API key Scale

Revision history for one series and delivery day. Series: load, load_fc, wind_fc, solar_fc, generation (k = PSR type), flow (k = destination zone), price (k = source).

Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/vintages/DE-LU?series=wind_fc&date=2026-07-17"

What it's for: leakage-free backtests on the TSO forecasts the market actually saw, first-print vs settled revision-risk analysis, and publication-latency measurement (first_print_at per point). Pairs with the as-of API, whose grid block reconstructs these series at any timestamp.

Scenario engine Scale

POST /v1/scenarios API key Scale

Monte Carlo price paths around the live forecast: day-block residual bootstrap (whole historical error days preserve intra-day correlation). Params: zone, days (≤7), paths (≤500), seed for reproducibility.

Request
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"zone":"DE-LU","days":2,"paths":100,"seed":42}' \
  "https://voltcast.com/api/v1/scenarios"

Accountable by design: every response carries a calibration block — the empirical coverage of the scenario band over matured days. We publish how well the scenarios were calibrated, we don't just promise it.

GET /v1/indices/flex/{zone} public

The Voltcast Flex Index (FLEX-2H): the daily EUR/MWh value of shifting energy on the day-ahead curve — the ceiling any 2h-flexible asset could have captured. Free with attribution; commercial referencing requires a license.

Request
curl "https://voltcast.com/api/v1/indices/flex/DE-LU?days=30"

Flexibility telemetry (opt-in)

Help build the only dataset on how European flexibility actually responds to 15-minute prices — and get early access to the aggregate statistics.

POST /v1/telemetry/flex API key

Report an anonymized planned/executed flexibility action: zone, device_type (ev/battery/heatpump/appliance/other), planned_start/end, energy_kwh, trigger.

Privacy, explicitly: no PII beyond your account link; individual records are never published or resold; per-zone aggregates (public stats) only appear above a 25-reporter k-anonymity floor.

Integrations

All official integrations live in Voltcast-com/integrations (Home Assistant, evcc, n8n — and every future one); SDKs in Voltcast-com/sdk. Recipes:

Grafana

Use the Infinity data source (free, official). Add a data source with base URL https://voltcast.com/api/v1 and an Authorization: Bearer YOUR_API_KEY header, then query:

Request
Type: JSON · Parser: Backend · Source: URL
URL: https://voltcast.com/api/v1/prices/DE-LU
Rows/Root: data
Columns: delivery_start (Time) · price_eur_mwh (Number)

# Forecast overlay: /v1/forecasts/DE-LU with target_start + p50
# Carbon panel:     /v1/carbon/DE-LU with ts + intensity_gco2eq_kwh

n8n

Community node @voltcast/n8n-nodes-voltcast (prices, forecasts, carbon, imbalance, cheapest-window — published on npm; source in Voltcast-com/n8n-nodes-voltcast). Install via Settings → Community Nodes in self-hosted n8n, or import the starter workflow — hourly cheapest-window check with a negative-price branch, using the plain HTTP node.

Google Sheets

Copy voltcast-sheets.gs into Extensions → Apps Script, set your key, and use custom functions in any cell:

Request
=VOLTCAST_PRICES("DE-LU", "2026-07-01", "2026-07-02")
=VOLTCAST_FORECAST("SE3")
=VOLTCAST_CARBON("FR")

Excel (Power Query)

Data → Get Data → From Other Sources → Blank Query → Advanced Editor, paste (replace the key):

Request
let
  Source = Json.Document(Web.Contents("https://voltcast.com/api/v1/prices/DE-LU",
    [Headers=[Authorization="Bearer YOUR_API_KEY"]])),
  Rows = Table.FromRecords(Source[data]),
  Typed = Table.TransformColumnTypes(Rows, {
    {"delivery_start", type datetimezone}, {"price_eur_mwh", type number}})
in
  Typed

Refreshable like any query — works in Excel and Power BI. Swap the URL for /v1/forecasts/DE-LU, /v1/carbon/DE-LU or any endpoint.

Monthly report digest (RSS)

Subscribe to /reports/feed.xml — every zone's monthly market report the moment a month closes. Pipe it into Slack, email or n8n.

Embeddable price widget

A live day-ahead price chart for any zone, free to embed on any site — attribution and backlink included (that's the deal). One line:

Request
<script src="https://voltcast.com/widget.js" data-zone="DE-LU" async></script>

<!-- options: data-zone="any zone code" · data-theme="dark|light" -->

No API key needed — the widget uses a public, cached, rate-limited feed (today + tomorrow only). For anything more, start with Home.

GET /v1/stream API key Pro+

Server-Sent Events: auction_published pushed the moment a zone's day-ahead curve lands, plus 15s heartbeats. Params: zones=DE-LU,AT (default: all zones in your plan).

Request
curl -N -H "Authorization: Bearer YOUR_API_KEY" \
  "https://voltcast.com/api/v1/stream?zones=DE-LU,AT"

event: auction_published
data: {"zone":"DE-LU","delivery_date":"2026-07-12","period_count":96,
       "detected_at":"2026-07-11T11:00:41Z","prices_url":"…/api/v1/prices/DE-LU"}

Browser EventSource can't set headers — pass ?token=YOUR_API_KEY instead (prefer the header elsewhere; query strings can end up in logs). Connections are time-boxed to 20 minutes with a retry hint for auto-reconnect, and concurrency is capped per account. For reliable fan-out at scale use webhooks — the stream is a convenience for dashboards and dev loops.

Public endpoints

No key required — rate limited per IP:

  • GET /v1/accuracy — the daily forecast scorecard: pinball loss + MAE per zone/horizon vs naive persistence. Rendered at /accuracy.
  • GET /v1/status/ingestion — live ingestion health per data source, errors included. Rendered at /status.
  • GET /v1/zones — the zone registry, with per-zone coverage notes.
  • GET /v1/briefing/{zone} — the daily zone briefing (today/tomorrow summary, negative-price flags, forecast teaser) as JSON.
  • GET /v1/widget/{zone} — the cached price feed behind widget.js (attribution required).
  • GET /v1/indices/flex/{zone} — the daily Voltcast Flex Index (EUR/MWh value of 2h load-shifting).
  • GET /v1/bench/leaderboard — the Forecast Bench leaderboard, scored with published code.
  • GET /v1/telemetry/flex/stats — anonymized community flexibility telemetry aggregates (opt-in program).
  • GET /v1/demo/prices · GET /v1/demo/savings — the landing-page demo feed and savings calculator (DE-LU sample, no key).

Errors

Errors are JSON with a stable machine-readable code and a human explanation:

Response 403
{
  "error": {
    "code": "zone_not_in_tier",
    "message": "Your Free plan is currently scoped to FR. You can switch the included zone to DE-LU at no cost in the dashboard, or upgrade for simultaneous access to all zones.",
    "selected_zone": "FR",
    "requested_zone": "DE-LU",
    "can_switch_zone": true,
    "change_zone_url": "https://voltcast.com/dashboard"
  }
}
HTTPCodeMeaning
401Missing or invalid API key.
403subscription_required · zone_selection_required · zone_not_in_tier · history_beyond_tier · export_requires_pro · webhooks_require_plan · webhook_rule_limitA paid plan is required, or the request is outside the active plan's entitlements. Home and grandfathered Free zone errors include change_zone_url; switching the included zone is free.
404zone_not_found · no_forecast_available · webhook_not_foundUnknown resource.
422invalid_range · range_too_largeInvalid parameters.
429Rate limit exceeded — honor Retry-After.

Attribution & licensing

Price responses carry a meta.attribution array — display it wherever you surface the data. Verbatim DE-LU and AT prices are CC BY 4.0 (SMARD, Bundesnetzagentur); forecasts and derived outputs are Voltcast's own. Full policy: data licensing.