Read-only REST API and outbound webhooks, included with the Business plan. Create API keys and webhook endpoints from your account (owner or team admins).
| Requests per API key | 60 per minute |
| Requests per account (all keys) | 20,000 per day (resets at midnight AEST) |
| Active API keys per account | 5 |
| Price history per request | 7 days |
| Webhook endpoints per account | 3 |
| Webhook delivery attempts | 3 (immediately, then after 5 and 30 minutes) |
| CSV export range | 31 days per file |
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix time).
Over a limit you get 429 with Retry-After in seconds. Requests rejected for a missing or invalid key don't count.
Prices update every 5 minutes, so polling faster than once a minute won't return new data.
Send your key as a bearer token. Keys belong to the account, not a person, and stop working if the account leaves Business.
curl -H "Authorization: Bearer nem_..." https://nemstats.com.au/api/v1/prices/latest
Errors return JSON: {"error": {"code": "...", "message": "..."}} with status 400, 401, 403 (no Business plan), 404, 405 or 429.
All times are NEM time (AEST, UTC+10:00, no daylight saving). Prices are regional reference prices in AUD/MWh for the 5-minute dispatch interval ending at interval_end.
GET /api/v1/prices/latestLatest dispatch price for all five regions.
{
"interval_end": "2026-11-03T14:35:00+10:00",
"unit": "AUD/MWh",
"data": [{"region": "NSW", "price": 92.14}, {"region": "QLD", "price": 88.02}, ...]
}
GET /api/v1/prices?region=NSW&from=…&to=…
5-minute prices for one region (NSW, QLD, VIC, SA, TAS).
from/to are ISO 8601 (e.g. 2026-11-01T00:00, read as NEM time, or with an offset).
Defaults to the 24 hours up to the latest interval; at most 7 days per request.
{
"region": "NSW", "from": "2026-11-01T00:00:00+10:00", "to": "2026-11-02T00:00:00+10:00",
"unit": "AUD/MWh", "interval_minutes": 5,
"data": [{"interval_end": "2026-11-01T00:05:00+10:00", "price": 71.30}, ...]
}
GET /api/v1/alertsYour team's price alerts and whether each condition is currently active or paused by plan limits.
{"data": [{"id": 12, "region": "SA", "direction": "above", "trigger_price": 300, "notify_email": true,
"notify_sms": true, "notify_roster": false, "condition_active": false, "paused": false, "paused_reason": null}]}
GET /api/v1/usageSMS usage for the current allowance period.
{"plan": "business", "billing_interval": "year",
"period_start": "2026-11-14T09:30:00+10:00", "period_end": "2026-12-14T09:30:00+10:00",
"sms": {"included": 2000, "included_used": 412, "included_remaining": 1588, "extra_enabled": false,
"extra_used": 0, "extra_rate_cents": 5, "extra_cost_cents": 0, "extra_cap_cents": 2000,
"topup_amount_cents": 2000, "topup_balance_cents": 0, "status": "ok"}}
When one of your team's alerts triggers or clears we POST a JSON event to each of your HTTPS endpoints.
Respond with any 2xx within 5 seconds. Redirects aren't followed, and endpoints must resolve to a public address on port 443.
Events for alerts paused by plan limits aren't sent.
POST /your-endpoint
Content-Type: application/json
X-NEMStats-Event: alert.triggered
X-NEMStats-Delivery: 8812
X-NEMStats-Signature: t=1793780100,v1=5f2c...
{"id": "a12-triggered-1793780100", "type": "alert.triggered", "created": "2026-11-03T04:35:00+00:00",
"data": {"alert_id": 12, "region": "SA", "matched_region": "SA", "direction": "above",
"trigger_price": 300, "price": 412.5, "unit": "AUD/MWh"}}
Verify the signature: compute HMAC-SHA256 of "{t}.{raw body}" using your endpoint's signing secret,
compare it with v1 in constant time, and reject timestamps more than 5 minutes old. The event id
is stable across retries, so use it to ignore duplicates.
$expected = hash_hmac('sha256', $t . '.' . $rawBody, $secret);
$valid = hash_equals($expected, $v1) && abs(time() - $t) < 300;
The API is read-only and covers the endpoints above. Creating or editing alerts, generator statistics and FCAS prices aren't available through the API yet.