Historical South Australia Electricity Prices

Historical South Australia Electricity Prices

You need reliable, dated spot prices for South Australia to power a forecast, report, or dashboard, but stitching together feeds and formats is slowing you down. By the end of this guide, you will query, parse, and validate historical timeseries for South Australia Electricity (AEMO SA1 spot) from the Energy API and ship it into your code with a minimal, repeatable workflow.

What you will integrate

This guide focuses on a single Energy API symbol and endpoint so you can move from zero to production without detours:

Illustration: Historical South Australia Electricity Prices
  • Symbol name: South Australia Electricity
  • Symbol code: AEMO_SA1_SPOT
  • Unit: AUD/MWh
  • Endpoint: GET /api/v1/timeseries?start=&end=&symbols=&api_key=
  • Authentication: api_key query parameter (use YOUR_API_KEY during setup)

The result you care about lives under rates.AEMO_SA1_SPOT keyed by date, with currencies.AEMO_SA1_SPOT confirming the currency used. Do not pass base=USD when you also need TTF_GAS or EUA_CO2. There is no MCP host involved. Plans start at $19.99/mo with a 7-day / 50-call trial.

Endpoint anatomy and required parameters

You will call a single endpoint with a start date, end date, a comma-separated symbols list, and your API key:

  • HTTP method: GET
  • URL: https://energy-api.com/api/v1/timeseries
  • Query params:
    • start: inclusive ISO date (YYYY-MM-DD)
    • end: inclusive ISO date (YYYY-MM-DD)
    • symbols: at least AEMO_SA1_SPOT for this guide
    • api_key: YOUR_API_KEY

Response fields you will use:

  • success: boolean request status
  • date: response date snapshot
  • base: base currency for the response context
  • rates: object keyed by symbol; numeric values for each symbol
  • dates: object keyed by symbol; ISO date string for that symbol’s value
  • currencies: object keyed by symbol; currency code
  • base_filter_note: may be null or a note; not required downstream

Quickstart: cURL you can paste

Run the official sample to confirm your environment can reach the API and that query-string auth works. This call uses the correct symbol for South Australia Electricity:

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

If you plan to automate, keep this structure: date-bounded range, explicit symbol list, and api_key as a query parameter. Do not relocate the key to a header unless the docs instruct otherwise.

Official sample response (structure reference)

The following JSON is the official sample to illustrate the response structure. Copy this block as-is when testing parsers that expect the documented fields and shapes:

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

Field usage in your code:

  • rates: read the numeric value for your symbol; use floating-point with care (decimal if you require strict precision).
  • dates: align each symbol’s value to its source date; do not assume it matches the top-level date.
  • currencies: confirm units and currency; for AEMO_SA1_SPOT you expect AUD and AUD/MWh.

Real API response for South Australia Electricity (use these values)

When integrating AEMO_SA1_SPOT, rely on the real example below to validate your parsing and currency assumptions:

What to verify in your pipeline:

  • Unit is AUD/MWh for AEMO_SA1_SPOT.
  • Base currency is AUD in this response, and currencies.AEMO_SA1_SPOT is AUD.
  • You consume rates.AEMO_SA1_SPOT and line it up with dates.AEMO_SA1_SPOT.

Python example: fetch and normalize AEMO_SA1_SPOT

The snippet below calls the same timeseries endpoint, extracts the South Australia Electricity price, confirms the currency, and emits a typed record your downstream jobs can consume.

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

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

def fetch_sa_price(start_date, end_date, api_key):
params = {
"start": start_date,
"end": end_date,
"symbols": "AEMO_SA1_SPOT",
"api_key": api_key
}
url = API_URL + "?" + urllib.parse.urlencode(params)
with urllib.request.urlopen(url) as resp:
data = json.loads(resp.read().decode("utf-8"))

if not data.get("success"):
raise RuntimeError("API call unsuccessful")

# Read the fields we actually need
symbol = "AEMO_SA1_SPOT"
rates = data.get("rates", {})
dates = data.get("dates", {})
currencies = data.get("currencies", {})

if symbol not in rates or symbol not in dates or symbol not in currencies:
raise KeyError("Missing expected symbol fields in response")

# Validate currency is AUD for this symbol
currency = currencies[symbol]
if currency != "AUD":
raise ValueError(f"Unexpected currency for {symbol}: {currency}")

value = rates[symbol]
date = dates[symbol]

# Normalize into a consistent record
record = {
"symbol": symbol,
"date": date, # YYYY-MM-DD
"value": float(value), # AUD/MWh
"currency": currency,
"unit": "AUD/MWh"
}
return record

if __name__ == "__main__":
api_key = os.environ.get("ENERGY_API_KEY", "YOUR_API_KEY")
try:
rec = fetch_sa_price("2026-01-01", "2026-03-31", api_key)
print(json.dumps(rec, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)

Interpreting dates, units, and base currency

Values for South Australia Electricity are denominated in AUD/MWh. The timeseries endpoint also reports a top-level base currency and a symbol-level currency. Your code should treat currencies.AEMO_SA1_SPOT as authoritative for the symbol. Align the value to dates.AEMO_SA1_SPOT, not the top-level date, which is a snapshot of the response day.

Timezone handling is simplified because dates are provided as ISO date strings (no timestamp). If you aggregate or resample into other timezones, use the date as a boundary and apply your own timezone rules consistently across your pipeline.

Request ranges, batching, and idempotence

Pass a clearly bounded start and end window, and keep each request idempotent by fixing those dates in job configuration. If you need to backfill or re-run, you will produce identical output for the same window, simplifying caching and deduplication.

The endpoint accepts a comma-separated symbols list, but keep your first integration focused on AEMO_SA1_SPOT. When you expand, maintain one symbol per alert or per transformation step to isolate failures.

Caching and refresh strategy

Because values are historical by date, cache responses keyed by (symbol, start, end). For daily pipelines, snapshot the previous business day’s data and store the raw JSON alongside normalized rows for traceability. If you must refresh, use the same query parameters to avoid cache misses. For interactive dashboards, set a modest TTL and invalidate on user-triggered refresh.

Validation checks that catch silent errors

  • Schema check: success is true, and all of rates, dates, currencies exist.
  • Symbol presence: AEMO_SA1_SPOT present in all three objects.
  • Currency check: currencies.AEMO_SA1_SPOT equals AUD.
  • Unit assumption: store or label the metric as AUD/MWh.
  • Monotonic window: requested start is not after end; reject otherwise before calling the API.

Common pitfalls (and how to avoid them)

  • Mixing base and symbol currency: always trust currencies.AEMO_SA1_SPOT for this symbol instead of the top-level base.
  • Assuming hourly granularity: the response shows dates per symbol. If you need sub-daily intervals, do not infer them from this endpoint.
  • Silent unit drift: persist the unit string (AUD/MWh) next to values so a later conversion step cannot accidentally treat them as AUD/kWh.
  • Overfetching windows: keep queries as narrow as needed to reduce payload sizes and simplify reconciliation.
  • Combining incompatible conversions: do not pass base=USD when you also need TTF_GAS or EUA_CO2; keep currency handling explicit per symbol.

Minimal JavaScript example for browser or Node

This example requests the same symbol and normalizes a single-day response shape into a record you can chart directly.

async function fetchSA1Spot(start, end, apiKey) {
const params = new URLSearchParams({
start,
end,
symbols: "AEMO_SA1_SPOT",
api_key: apiKey
});
const url = `https://energy-api.com/api/v1/timeseries?${params.toString()}`;
const res = await fetch(url, { method: "GET" });
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
if (!data.success) {
throw new Error("API returned success=false");
}

const sym = "AEMO_SA1_SPOT";
const currency = data.currencies?.[sym];
if (currency !== "AUD") {
throw new Error(`Unexpected currency for ${sym}: ${currency}`);
}

const value = data.rates?.[sym];
const date = data.dates?.[sym];
if (value == null || !date) {
throw new Error("Missing value or date for AEMO_SA1_SPOT");
}

return {
symbol: sym,
date, // YYYY-MM-DD
value: Number(value),
currency, // "AUD"
unit: "AUD/MWh"
};
}

// Example usage:
fetchSA1Spot("2026-01-01", "2026-03-31", "YOUR_API_KEY")
.then(console.log)
.catch(console.error);

Operational notes that save time

  • Retry policy: retry idempotent GETs with exponential backoff on transient network errors; do not mutate parameters between retries.
  • Observability: log the full querystring (excluding the api_key) plus a hashed key identifier and response success to correlate issues.
  • Versioning: pin the URL and parameters in code; avoid implicit defaults that can change over time.
  • Data lineage: store the raw JSON alongside transformed rows for auditing and reprocessing.

Testing your integration

Write table-driven tests that feed the parser with both the official sample JSON and the real AEMO_SA1_SPOT example above. Assert that:

  • The parser extracts the symbol’s numeric value and date correctly.
  • The currency validation rejects unexpected currencies.
  • Missing fields in any of rates, dates, or currencies produce a clear error.

Finally, run an end-to-end test using a tiny date window (two or three days) in a non-production environment, and verify that your storage, caching, and dashboards ingest the records as expected.

Where to go next

If you want to add more regions later, keep each symbol’s transform independent and apply the same checks: currency, unit, date alignment, and numeric validation. For definitive parameter details and additional endpoints, review the official docs.

FAQ

Q: How do I authenticate requests?
A: Pass your key as api_key in the query string. Use the string literal YOUR_API_KEY during setup and replace it with your real key when deploying.

Q: What units do AEMO_SA1_SPOT values use?
A: AUD/MWh. Confirm with currencies.AEMO_SA1_SPOT (AUD) and document the unit next to the value.

Q: Can I request multiple symbols at once?
A: Yes, pass a comma-separated list to symbols. Start with AEMO_SA1_SPOT and expand after you’ve validated your pipeline.

Q: Should I rely on the top-level date?
A: Use dates.AEMO_SA1_SPOT to align each value. Treat the top-level date as metadata about the response, not the series index.

Q: Is there a free trial?
A: Yes. The Starter plan is $19.99/mo, and there’s a 7-day / 50-call trial.

Register for an API key and start querying South Australia Electricity spot prices in minutes: Register. For endpoints, parameters, and field definitions, check the Documentation.

Ready to get started?

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

Get API Key