Spanish PVPC Electricity API: Hourly PVPC as JSON
You need the official Spanish PVPC (Peninsula) regulated electricity price for a specific calendar date, hour by hour, as clean JSON you can chart or store. By the end of this guide you’ll be able to fetch PVPC_ES_2TD for a given date from Energy API, validate the response, handle edge cases like missing hours, and feed the result directly into your app.
What you get: official PVPC hourly prices as JSON
The endpoint returns the regulated PVPC tariff for Spain’s Peninsula (indicator 1001) for one official PVPC date, broken down by hour. On Energy API this data is exposed under the symbol PVPC_ES_2TD and returned in EUR.
- Symbol: PVPC_ES_2TD (ESIOS/REE indicator 1001)
- Granularity: hourly, within the requested date
- Currency: EUR (do not request another base currency if you need the PVPC rows)
- Units: price_eur_mwh is expressed in EUR per MWh
- No MCP: the response does not include an MCP field
Important: this is not the wholesale OMIE day-ahead series. If you also consume OMIE wholesale prints for analytics, keep them separate from PVPC. A wholesale OMIE example appears later to highlight the difference, and we’ll show exactly how to request PVPC in this article.
Endpoint and request shape
Energy API serves hourly PVPC via a simple GET with two query parameters: date and api_key. The path is fixed for this tariff; the symbol resolves server-side, and the JSON includes the symbol field for your checks.
HTTP method: GET
Endpoint: https://energy-api.com/api/v1/electricity/pvpc
Query parameters:
- date: the official PVPC calendar date you want (e.g., 2026-06-18)
- api_key: your Energy API key
Copy-paste this curl and replace YOUR_API_KEY with your key:
curl -s "https://energy-api.com/api/v1/electricity/pvpc?date=2026-06-18&api_key=YOUR_API_KEY"
Notes for correctness:
- Currency: rows are returned in EUR. Do not pass base=USD when you need EUR rows.
- Scope: one date per call, hour by hour. If you need multiple dates, loop client-side.
Official PVPC sample
curl "https://energy-api.com/api/v1/electricity/pvpc?date=2026-06-18&api_key=YOUR_API_KEY"
What to pay attention to in the response:
- success: boolean, check this first before reading the payload.
- symbol: the server-resolved code. For this article it should be PVPC_ES_2TD. Validate it if your app mixes multiple series.
- date: the official PVPC date you requested.
- currency: the base currency of the series. Expect EUR here; don’t convert unless your UI requires it.
- hours: an array of hourly entries. Each entry contains:
- hour: the hour label for the PVPC date (parse as a string; don’t assume a timezone conversion is needed if you are simply plotting the official calendar hours).
- price_eur_mwh: the price for that hour in EUR/MWh.
- count: how many hourly entries are in hours. Do not hardcode 24 elements—see the section below on array length.
Handling fields, units, and edge cases
Here’s what to build into your parser so you don’t lose time in production:
- Check success before use. If success is false, do not assume any of the other fields are reliable. You can log the response and retry, or surface an error state in your UI. Backoff and alerting are good practice.
- Symbol guardrails. If you pass dates from various sources into the same processing pipeline, verify symbol === PVPC_ES_2TD before aggregating, so you don’t mix tariff types.
- Units and base currency. price_eur_mwh is EUR per MWh. Keep calculations in EUR to avoid rounding drift. If your frontend needs another currency, convert outside the API. Do not ask this endpoint for USD rows.
- Array length. The documentation does not freeze a 24-hour price array. Use count to drive loops and X-axis ticks. This makes your code resilient to any official calendar or scheduling quirks.
- Missing values. Treat absent or null price_eur_mwh as missing data. Show a gap, carry forward previous value only if your analytics policy allows it, or fall back to a placeholder with an explicit “no data” label. Don’t fabricate values.
- Dates and timezone. The request uses an official PVPC date and returns hours within that date. Display the date as returned. If you must map to UTC for storage, keep the original date and hour string alongside any converted timestamps so you can reproduce the official calendar view later.
End-to-end example in Python
Below is a minimal Python snippet that fetches a PVPC date, validates the response, and prepares a pair of arrays you can hand to a charting library (hour labels and numeric EUR/MWh values):
import os
import sys
import requests
API_KEY = os.getenv("ENERGY_API_KEY", "YOUR_API_KEY")
DATE = "2026-06-18"
URL = "https://energy-api.com/api/v1/electricity/pvpc"
def fetch_pvpc(date):
params = {"date": date, "api_key": API_KEY}
r = requests.get(URL, params=params, timeout=30)
r.raise_for_status()
data = r.json()
return data
def parse_pvpc(data):
# 1) success guard
if not data.get("success", False):
raise RuntimeError("PVPC request was not successful")
# 2) symbol guard
if data.get("symbol") != "PVPC_ES_2TD":
raise RuntimeError(f"Unexpected symbol: {data.get('symbol')}")
# 3) currency guard
if data.get("currency") != "EUR":
raise RuntimeError(f"Unexpected currency: {data.get('currency')}")
# 4) extract hours safely
hours = data.get("hours") or []
count = data.get("count")
hour_labels = []
prices_eur_mwh = []
for row in hours:
hour = row.get("hour")
price = row.get("price_eur_mwh")
# Skip rows with missing fields; alternatively, append None and handle gaps in the chart
if hour is None or price is None:
continue
hour_labels.append(hour)
prices_eur_mwh.append(float(price))
# Optional consistency check with count
if count is not None and count != len(hours):
# Log and continue — server-provided 'count' refers to array size, not post-filtered rows
sys.stderr.write(f"Info: count={count}, received={len(hours)} rows\\n")
return {
"date": data.get("date"),
"hour_labels": hour_labels,
"prices_eur_mwh": prices_eur_mwh,
}
if __name__ == "__main__":
payload = fetch_pvpc(DATE)
parsed = parse_pvpc(payload)
print(f"PVPC date: {parsed['date']}")
print(f"Hours: {len(parsed['hour_labels'])} | First 5: {parsed['hour_labels'][:5]}")
print(f"First 5 prices (EUR/MWh): {parsed['prices_eur_mwh'][:5]}")
How this differs from wholesale OMIE
You may see an electricity print on Energy API affiliated with the official “latest mix” that references OMIE wholesale series and a specific EUR/MWh value. That is a different symbol and dataset from PVPC_ES_2TD.
{
"base": "MIXED",
"date": "2026-06-11",
"rates": {
"OMIE_ES_DA": 82.30
}
}
Use PVPC_ES_2TD via the /electricity/pvpc path shown earlier when you need regulated consumer tariff data by hour. Use wholesale OMIE symbols for day-ahead market analysis. Keep them in separate pipelines and label charts carefully so that you don’t mix regulated and wholesale series in the same plot.
Production notes that save time
Input validation
- Make the date an explicit parameter in your scheduler or CLI. Validate the format before calling the API.
- Do not assume a fixed hour set. Always iterate the hours array and use count to dimension your arrays.
Missing and partial data
- If you receive success=false, backoff and retry, and log the entire payload for traceability. Avoid falling back to yesterday’s values without marking them as such.
- For missing price_eur_mwh in a row, decide whether your business logic shows a gap or omits the point. Both are acceptable if you label the state.
Caching and re-fetch strategy
- If your UI shows a single official date at a time, cache that date’s response keyed by date and symbol. When reloading the same date frequently, serve from cache to reduce API calls.
- If you need to refresh, consider a short TTL for “today” while leaving previous dates cached longer. Use ETag/conditional requests on your side if you proxy or store responses.
Charting
- Build the X-axis from hours[].hour as returned; don’t synthesize hour labels. If a gap exists, show it explicitly.
- Use price_eur_mwh values directly for EUR/MWh plots. If you later add other series, preserve unit annotations in your legend.
Pagination and bulk loads
- This endpoint returns one date’s worth of data per call. There is no pagination in this shape.
- For multi-day views, loop across your date range and merge the results client-side by concatenating hours.
Operational setup
- Environment variables: store api_key in a secret manager or ENV var.
- Monitoring: alert on non-success responses and JSON schema mismatches (e.g., missing hours).
- Currency discipline: keep PVPC in EUR end to end; only convert for user display if necessary.
Run it live in four steps
- Register — 7-day trial / 50 calls included.
- Copy your api_key from the dashboard.
- GET /electricity/pvpc with a date: use the curl above or the Python example.
- Chart hours[].price_eur_mwh for the official PVPC date. There is no MCP field in this dataset.
Pricing tip: the Starter plan is $19.99/mo and includes 5,000 calls and 5 symbols with the trial noted above. For details beyond this article, check the Documentation.
Common pitfalls and how to avoid them
- Confusing PVPC with OMIE: keep PVPC_ES_2TD separate from OMIE wholesale symbols. They answer different questions and are not interchangeable.
- Assuming a 24-hour array: rely on count and iterate hours[]; never hardcode 24 bars in your chart.
- Currency drift: don’t pass base=USD to this endpoint. Keep PVPC in EUR and convert in your application only if you must.
- Silent failures: always check success. Don’t proceed to chart on a failed response.
- Dropping the hour label: store hour as returned alongside numeric values so your plots and CSV exports remain auditable.
FAQ
Q: How do I request the PVPC hourly prices for a date?
A: Call GET https://energy-api.com/api/v1/electricity/pvpc with date and api_key as query parameters. The symbol PVPC_ES_2TD is returned in the JSON.
Q: What fields do I need to chart PVPC?
A: From the JSON, use hours[].hour for the X-axis and hours[].price_eur_mwh (EUR/MWh) for the Y-axis. Check success, symbol, currency, and count first.
Q: Can I assume 24 values every day?
A: No. Use the count field and iterate hours[]. The documentation does not guarantee a fixed 24-element array.
Q: Is PVPC the same as OMIE day-ahead prices?
A: No. PVPC_ES_2TD is a regulated tariff series. OMIE wholesale day-ahead is a different symbol and should be consumed separately.
Q: What currency are PVPC prices in?
A: EUR. The field is price_eur_mwh, and the top-level currency is EUR. Do not pass base=USD when you need EUR rows.
Ready to ship? Start your 7-day trial, pull your first PVPC date, and get your chart live this afternoon. Register and then review the endpoint details in the Documentation.
Ready to get started?
Get your API key and start querying energy commodity prices in minutes.
Get API Key