WattMarkets

The API is the product

Free at 120 requests a minute, 50k a day, with the live stream unmetered. Reads work without a key. If you republish the data, credit "Peak data by WattMarkets" with a link. Your own key is waiting at sign-in.

Graded in public.0 of 3 live days flagged this season.every call, graded
A live example this is production data, right now
$ curl https://wattmarkets.com/v1/predictions/daily?program=ercot-4cp-2026
{
  "date": "2026-07-04",
  "p_peak_day": 0.0241,
  "level": "CLEAR",
  "drivers": {
    "forecast_max_mw": 80403.3,
    "month_max_mw": 82136,
    "margin_mw": -1732.7,
    "p_raw": 0.0831,
    "p_final": 0.0241
  },
  "model_version": "mercury-1.0.0"
}

That's today's real call, 2% CLEAR, not sample data. The inputs ship with every probability. That's the transparency promise.

Endpoints
GET /v1/predictions/daily?program&dateP(peak day), level, window, driver vector, model version
GET /v1/predictions/intervals?program&dateper-interval probabilities (the Interval Strip, as JSON)
GET /v1/load/actual?start&endsystem load series
GET /v1/load/forecast?date&asofERCOT forecast vintages
GET /v1/peaks?program&season&statuspeak intervals + MW
GET /v1/peaks/history?yearhistorical 4CP peaks from settled load
GET /v1/zones/current · /frames · /citiesthe Texas map, as JSON
GET /v1/scorecard · /calls · /attestationsthe public scorecard + hash-chain attestations
GET /v1/season/days?programthe month ladder
GET /v1/streamSSE: load, predictions, level changes, peaks (30s heartbeats)
POST /v1/webhookssigned webhooks — HMAC SHA-256, replay-protected
GET /v1/calendar.icsWATCH+ days as a calendar feed
Verify a webhook in 6 lines
# X-Watt-Signature: t=<unix>,v1=<hex>   v1 = HMAC-SHA256(secret, f"{t}.{raw_body}")
import hmac, hashlib, time
def verify(secret, sig_header, raw_body, tolerance=300):
    parts = dict(p.split("=", 1) for p in sig_header.split(","))
    if abs(time.time() - int(parts["t"])) > tolerance: return False  # replay guard
    expected = hmac.new(secret.encode(), f"{parts['t']}.{raw_body}".encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])