Historical Spain Carbon Intensity Prices

Historical Spain Carbon Intensity Prices

You need reliable historical carbon intensity data for Spain that your code can fetch, parse, and ship to production. By the end of this guide, you will know exactly how to query the Energy API timeseries endpoint for the Spain Carbon Intensity symbol, validate responses, handle empty ranges, and wire it into your application with a copy-pasteable curl command and a Python implementation.

What you will query: Spain Carbon Intensity (CARBON_INT_ES)

This guide focuses on a single Energy API timeseries symbol so you can implement it quickly without guesswork:

Illustration: Historical Spain Carbon Intensity Prices
  • Symbol name: Spain Carbon Intensity
  • Symbol code: CARBON_INT_ES
  • Unit: gCO2/kWh
  • Authentication: api_key query parameter (value: YOUR_API_KEY)

Carbon intensity is reported in grams of CO2 per kilowatt-hour. You will read date-keyed values from the timeseries response under rates.CARBON_INT_ES, and you can confirm the unit via currencies.CARBON_INT_ES. Do not pass base=USD when you also need TTF_GAS or EUA_CO2 in the same query.

Endpoint and request structure

You will use a single endpoint with HTTP GET:

  • Path: /api/v1/timeseries
  • Query parameters: start, end, symbols, api_key
  • Auth: api_key in the query string (use YOUR_API_KEY as the placeholder during development)

Typical usage for Spain Carbon Intensity is a daily timeseries between two calendar dates that you explicitly set. Keep your date range as tight as needed to avoid sifting through large payloads. If your integration can tolerate eventual consistency, consider caching the response for the same start and end intervals to save calls.

Refer to the official API reference for broader parameter details and field semantics: Documentation.

Quickstart: curl request you can run now

This is the exact, official curl you can paste into your terminal. It targets CARBON_INT_ES for Q1 2026 and uses YOUR_API_KEY as the placeholder credential.

curl -G "https://energy-api.com/api/v1/timeseries" --data-urlencode "start=2026-01-01" --data-urlencode "end=2026-03-31" --data-urlencode "symbols=CARBON_INT_ES" --data-urlencode "api_key=YOUR_API_KEY"

If the call returns data, you will parse the rates, dates, and currencies objects. If the symbol has no coverage within your requested window, you should expect a structured error (see below) and handle it gracefully (for example, by shrinking the date window or changing the symbol).

Real response envelope: no data in the requested window

The live call for the range above did not return rates. You should expect and robustly handle this response:

{"success":false,"error":"No rate data available for the requested symbols."}

Interpretation:

  • success: false means you will not have a rates object to parse for this request.
  • error explains why: the symbol has no rate coverage in the provided date window.

Action items for your integration:

  • Surface a clear message to logs or observability tooling.
  • Allow the caller to modify start/end to match a supported period.
  • Do not attempt to coerce missing values or invent rates; keep the pipeline deterministic.

Field mapping when the request succeeds

When success is true, the timeseries shape includes base, rates, dates, currencies, and possibly a base_filter_note. The example below is the official sample success envelope you should use to validate your parsing logic. Note: the rate key shown (OMIE_ES_DA) is a different symbol from CARBON_INT_ES, but you must copy this example exactly to confirm your parser handles the real shape and fields correctly.

{
"success": true,
"date": "2026-10-12",
"base": "EUR",
"rates": {
"OMIE_ES_DA": 184.8822
},
"dates": {
"OMIE_ES_DA": "2026-10-12"
},
"currencies": {
"OMIE_ES_DA": "EUR"
},
"base_filter_note": null
}

How to adapt this shape for Spain Carbon Intensity in your code paths:

  • Use success to guard all downstream parsing.
  • Read base if you need to reason about cross-symbol currency contexts. Carbon intensity values are in gCO2/kWh; confirm via currencies.CARBON_INT_ES when success is true.
  • Index into rates.CARBON_INT_ES to get the numeric value for the symbol within your requested period.
  • Use dates.CARBON_INT_ES to associate the precise date for the returned rate.

Because the REAL API RESPONSE for our curl returned no rates for the selected window, your production logic must branch on success before touching rates/dates/currencies. Never attempt to cast or backfill a rate when success is false.

Production-grade Python example

The snippet below calls the same endpoint, checks success, and, if present, reads rates.CARBON_INT_ES and currencies.CARBON_INT_ES. It also turns the structured error into a Python exception so you can bubble it up to the caller or retry logic.

import os
import sys
import json
import urllib.parse
import urllib.request

API_URL = "https://energy-api.com/api/v1/timeseries"

def fetch_carbon_intensity_es(start, end, api_key):
params = {
"start": start,
"end": end,
"symbols": "CARBON_INT_ES",
"api_key": api_key,
}
url = f"{API_URL}?{urllib.parse.urlencode(params)}"
req = urllib.request.Request(url, method="GET")
try:
with urllib.request.urlopen(req, timeout=30) as resp:
payload = json.loads(resp.read().decode("utf-8"))
except Exception as e:
raise RuntimeError(f"HTTP or decode error: {e}")

# Always check the success flag first
if not isinstance(payload, dict) or not payload.get("success", False):
# The REAL API RESPONSE sample we observed:
# {"success":false,"error":"No rate data available for the requested symbols."}
err = payload.get("error", "Unknown error")
raise ValueError(f"Energy API returned an error: {err}")

# On success, read the symbol-specific fields
symbol = "CARBON_INT_ES"
rates = payload.get("rates", {})
dates = payload.get("dates", {})
currencies = payload.get("currencies", {})

if symbol not in rates:
raise KeyError(f"Expected rates.{symbol} in response payload")

value = rates[symbol]
date_for_value = dates.get(symbol)
unit = currencies.get(symbol) # For carbon intensity this denotes gCO2/kWh

return {
"symbol": symbol,
"date": date_for_value,
"value": value,
"unit": unit,
"base": payload.get("base"),
"as_of": payload.get("date"),
"base_filter_note": payload.get("base_filter_note"),
}

if __name__ == "__main__":
# Example invocation; replace YOUR_API_KEY with your actual key.
api_key = os.environ.get("ENERGY_API_KEY", "YOUR_API_KEY")
try:
result = fetch_carbon_intensity_es("2026-01-01", "2026-03-31", api_key)
print(json.dumps(result, indent=2))
except Exception as exc:
print(f"Fetch failed: {exc}", file=sys.stderr)
sys.exit(1)

Notes:

  • Timestamps and dates: The endpoint is queried with calendar dates. Respect the service’s notion of a “day” when you build rolling windows; avoid implicit timezone conversions on date-only strings.
  • Caching: Cache successful responses keyed by (start, end, symbols) to minimize repeat calls and keep within the 7-day trial / 50-call constraint.
  • Units: Expect gCO2/kWh for CARBON_INT_ES. Verify via currencies.CARBON_INT_ES on success.

Understanding error handling and retries

When the API indicates there is no rate data for the requested window, do not retry immediately with the same parameters. Instead, narrow your window or select a documented coverage period. The example error you should expect and handle is shown again here so you can verify idempotent parsing across retries:

Attempt A (initial window)

{"success":false,"error":"No rate data available for the requested symbols."}

Attempt B (same parameters; do not hammer)

{"success":false,"error":"No rate data available for the requested symbols."}

Attempt C (after parameter change, still no coverage)

{"success":false,"error":"No rate data available for the requested symbols."}

Your orchestration should short-circuit retries when the error indicates structural unavailability rather than transient transport failure. Prefer a human-readable log with the attempted date range and the specific symbol so you can adjust ranges quickly.

Validating a successful shape with the official sample

To ensure your parser is wired correctly before you obtain a successful CARBON_INT_ES payload, use the official success envelope below. While the symbol key inside rates/dates/currencies is OMIE_ES_DA in this sample, its structure matches what you will see with CARBON_INT_ES when success is true. Copy this block verbatim into your test fixtures to validate shape and field names.

{
"success": true,
"date": "2026-10-12",
"base": "EUR",
"rates": {
"OMIE_ES_DA": 184.8822
},
"dates": {
"OMIE_ES_DA": "2026-10-12"
},
"currencies": {
"OMIE_ES_DA": "EUR"
},
"base_filter_note": null
}

Checklist for your validation:

  • Ensure your code branches on success == true before reading rates.
  • Assert that the symbol you requested (CARBON_INT_ES) appears as a key in rates/dates/currencies when the call succeeds.
  • Confirm that currencies.CARBON_INT_ES reflects the expected unit (gCO2/kWh).

Operational considerations specific to carbon intensity

Carbon intensity is not a “price” in a currency sense; it is an intensity metric. Treat it as a measurement timeseries:

  • Unit integrity: Retain the unit gCO2/kWh end-to-end. Do not mix it with a monetary base setting. The base field is present in the envelope but does not convert the unit.
  • Aggregation: If you downsample daily values to weekly or monthly, document your aggregation function (mean, median) and avoid implying monetary semantics.
  • Non-trading days analog: Energy and emissions series may skip dates (maintenance gaps, holidays, or data unavailability). Your code should not assume continuous daily coverage.

If you query multiple symbols together later (for example, CARBON_INT_ES with energy pricing symbols), follow the instruction not to pass base=USD when you also need TTF_GAS or EUA_CO2 in the same call.

End-to-end testing plan

Use a staged approach to get to production with confidence:

  1. Connectivity test: Run the official curl and ensure your network path reaches the endpoint. Expect either success or the structured error shown earlier.
  2. Parser test: Seed your tests with the official success JSON and verify that your code reads rates, dates, and currencies correctly.
  3. Error-path test: Seed with the error envelope and confirm that your code raises a clear exception or returns a typed error to the caller.
  4. Fixture replacement: Once you see a real success for CARBON_INT_ES in your environment, store a sanitized fixture for regression tests.

Practical tips that will save you time

  • Parameter hygiene: Always pass symbols=CARBON_INT_ES explicitly. Avoid trailing spaces or comma errors when you expand the list.
  • Date boundaries: Keep start and end as ISO-8601 dates (YYYY-MM-DD). Do not send times unless the documentation specifies otherwise.
  • Idempotency: Caching responses per (start, end, symbols) avoids repeated parsing and keeps you within the trial’s 50-call limit.
  • Observability: Log the final request URL (redacting api_key) and the first 200 characters of the response for quick triage.
  • Downstream schemas: Store value as a float and unit as gCO2/kWh; annotate the symbol code to avoid collisions if you later add country variants.

Complete request/response gallery for your console tests

Use the following blocks to validate your CLI and CI pipelines. The first is the official curl. The next four are complete JSON envelopes you can paste into mocks to test success and failure paths.

cURL (official)

curl -G "https://energy-api.com/api/v1/timeseries" --data-urlencode "start=2026-01-01" --data-urlencode "end=2026-03-31" --data-urlencode "symbols=CARBON_INT_ES" --data-urlencode "api_key=YOUR_API_KEY"

JSON A: Real error envelope (no data)

{"success":false,"error":"No rate data available for the requested symbols."}

JSON B: Official success envelope (structure check)

{
"success": true,
"date": "2026-10-12",
"base": "EUR",
"rates": {
"OMIE_ES_DA": 184.8822
},
"dates": {
"OMIE_ES_DA": "2026-10-12"
},
"currencies": {
"OMIE_ES_DA": "EUR"
},
"base_filter_note": null
}

JSON C: Repeat error for retry-path testing

{"success":false,"error":"No rate data available for the requested symbols."}

JSON D: Repeat error for alerting-path testing

{"success":false,"error":"No rate data available for the requested symbols."}

Troubleshooting checklist

  • Got success: false with “No rate data available for the requested symbols.”? Tighten the date range or verify CARBON_INT_ES coverage for your period.
  • Parsing KeyError on rates.CARBON_INT_ES? Check success first; only read rates when success is true.
  • Unexpected unit handling? Inspect currencies.CARBON_INT_ES on success; for this symbol the unit is gCO2/kWh.
  • Multiple symbols in one call? Ensure you respect the instruction not to pass base=USD when also requesting TTF_GAS or EUA_CO2.
  • Timeouts or HTTP errors? Implement a short exponential backoff for transport-layer failures, but do not retry immediately on structured semantic errors.

FAQ

Which symbol should I use for Spain’s carbon intensity?
Use CARBON_INT_ES. The unit is gCO2/kWh, returned via currencies.CARBON_INT_ES when the call succeeds.

How do I authenticate?
Add api_key=YOUR_API_KEY as a query parameter. Keep your key out of logs and version control.

What fields should my parser read?
Always check success first. Then read base, rates.CARBON_INT_ES, dates.CARBON_INT_ES, currencies.CARBON_INT_ES, and optionally base_filter_note if present.

What if there is no data for my dates?
You will receive success: false with the error message “No rate data available for the requested symbols.” Adjust your date window or symbol and try again.

Can I request multiple symbols together?
Yes, but do not pass base=USD when you also need TTF_GAS or EUA_CO2. Keep symbol lists tightly scoped to reduce payload size and complexity.

Register and ship your integration

Get your API key and start making requests with the exact curl and Python samples above. Sign up for the Starter plan ($19.99/mo) with a 7-day / 50-call trial and begin integrating Spain’s carbon intensity into your pipeline today: Register. You can also review endpoint details and payload fields here: Documentation.

Ready to get started?

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

Get API Key

Related posts