Claude-skill-registry gridstatus-api

This skill should be used when the user asks to "get electricity data", "query grid data", "get LMP prices", "fetch load data", "get fuel mix", "query ERCOT data", "query CAISO data", "query PJM data", "get electricity prices", "analyze grid operations", "get ISO data", or mentions electricity market data (load, generation, pricing, LMP, fuel mix, ancillary services, etc.).

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/gridstatus-api" ~/.claude/skills/majiayu000-claude-skill-registry-gridstatus-api && rm -rf "$T"
manifest: skills/data/gridstatus-api/SKILL.md
source content

GridStatus API Skill

Query electricity grid data from US Independent System Operators (ISOs) using the GridStatus.io API. Access real-time and historical data for load, pricing (LMP), generation, fuel mix, and more.

Quick Start

IMPORTANT: Always use the Python SDK. The direct curl API has issues with date filtering on the free tier and returns stale sample data. The Python SDK correctly handles all parameters.

Setup

  1. Install SDK (use uv for isolation):
cd /tmp && uv venv -q && source .venv/bin/activate && uv pip install gridstatusio pandas -q
  1. API Key: Check for

    GRIDSTATUS_API_KEY
    in the user's
    .env
    file. If not present, instruct the user to:

  2. Query data:

import os
os.environ['GRIDSTATUS_API_KEY'] = 'key_from_dotenv'

from gridstatusio import GridStatusClient
client = GridStatusClient()

df = client.get_dataset(
    dataset="isone_fuel_mix",
    start="2026-01-25",
    end="2026-01-26",
    limit=100
)
print(df.tail())

Free tier limit: 500,000 rows per month. Always use

limit
parameter.

Supported ISOs

ISORegionKey Datasets
ERCOTTexas
ercot_load
,
ercot_spp_*
,
ercot_fuel_mix
CAISOCalifornia
caiso_load
,
caiso_lmp_*
,
caiso_fuel_mix
PJMMid-Atlantic/Midwest
pjm_load
,
pjm_lmp_*
,
pjm_standardized_*
MISOMidwest
miso_load
,
miso_lmp_*
NYISONew York
nyiso_load
,
nyiso_lmp_*
ISO-NENew England
isone_load
,
isone_lmp_*
,
isone_fuel_mix
SPPSouthwest/Central
spp_load
,
spp_lmp_*

See

references/datasets-by-iso.md
for complete dataset catalog.

Standard Query Template

Use this template for all queries. Run in a Python heredoc:

cd /tmp && source .venv/bin/activate && python3 << 'EOF'
import os
os.environ['GRIDSTATUS_API_KEY'] = 'YOUR_KEY_HERE'

from gridstatusio import GridStatusClient
client = GridStatusClient()

df = client.get_dataset(
    dataset="DATASET_NAME",
    start="YYYY-MM-DD",
    end="YYYY-MM-DD",
    limit=100
)
print(df.to_string())
EOF

Common Query Patterns

Current Fuel Mix (What's generating now?)

df = client.get_dataset(
    dataset="isone_fuel_mix",  # or ercot_fuel_mix, caiso_fuel_mix
    start="2026-01-25",
    end="2026-01-26",
    limit=500
)
latest = df.iloc[-1]
total = latest[['coal','hydro','natural_gas','nuclear','oil','solar','wind','wood','refuse','other']].sum()
print(f"Oil: {latest['oil']:.0f} MW ({latest['oil']/total*100:.1f}%)")

System Load

df = client.get_dataset(
    dataset="pjm_load",
    start="2026-01-25",
    end="2026-01-26",
    timezone="US/Eastern",
    limit=100
)
print(f"Current load: {df.iloc[-1]['load']:,.0f} MW")

Electricity Prices (LMP)

df = client.get_dataset(
    dataset="ercot_spp_real_time_15_min",
    start="2026-01-25",
    end="2026-01-26",
    filter_column="location",
    filter_value="HB_HOUSTON",
    limit=100
)
print(f"Houston price: ${df.iloc[-1]['spp']:.2f}/MWh")

Zone-Specific Load (Standardized Datasets)

df = client.get_dataset(
    dataset="pjm_standardized_hourly",
    start="2026-01-25",
    end="2026-01-26",
    timezone="market"
)
# Zone data in columns: df['load.comed'], df['load.aep'], etc.
print(f"ComEd load: {df.iloc[-1]['load.comed']:,.0f} MW")

Dataset Discovery

Check Dataset Metadata (date range, columns)

# Get dataset info including available date range
import requests
import os

api_key = os.environ.get('GRIDSTATUS_API_KEY')
r = requests.get(f"https://api.gridstatus.io/v1/datasets/pjm_load",
                 headers={"x-api-key": api_key})
meta = r.json()
print(f"Available: {meta['earliest_available_time_utc']} to {meta['latest_available_time_utc']}")
print(f"Columns: {[c['name'] for c in meta['all_columns']]}")

List Datasets

client.list_datasets(filter_term="ercot")  # Search by keyword
datasets = client.list_datasets(filter_term="fuel_mix", return_list=True)

Dataset naming convention:

{iso}_{data_type}_{frequency}

  • ercot_load
    - ERCOT system load
  • caiso_lmp_real_time_5_min
    - CAISO 5-minute real-time LMPs
  • pjm_lmp_day_ahead_hourly
    - PJM day-ahead hourly LMPs

Energy Calculations

Load (MW) measures instantaneous power. Energy (MWh) = power x time.

Data FrequencyEnergy FormulaExample
5-minute
energy_MWh = load_MW * (5/60)
100,000 MW x 0.0833 = 8,333 MWh
15-minute
energy_MWh = load_MW * (15/60)
100,000 MW x 0.25 = 25,000 MWh
Hourly
energy_MWh = load_MW * 1
100,000 MW x 1 = 100,000 MWh
# Total energy for a period (5-min data)
total_mwh = (df['load'] * (5/60)).sum()
total_gwh = total_mwh / 1000

Query Parameters Reference

ParameterTypeDescription
dataset
strRequired. Dataset ID (e.g.,
ercot_load
)
start
strStart date (YYYY-MM-DD or ISO format)
end
strEnd date
limit
intMax rows to return
timezone
str
"market"
for ISO local time, or
"US/Central"
etc.
filter_column
strColumn to filter on
filter_value
str/listValue(s) to match
filter_operator
str
=
,
!=
,
>
,
<
,
>=
,
<=
,
in
resample
strAggregate frequency (
"1 hour"
,
"1 day"
)
resample_function
str
mean
,
sum
,
min
,
max

See

references/api-reference.md
for complete documentation.

Troubleshooting

IssueCauseFix
Old/stale data returnedUsing curl directlyUse Python SDK instead - curl has date filtering issues on free tier
401 UnauthorizedInvalid/missing API keyCheck
GRIDSTATUS_API_KEY
is set correctly
Empty DataFrameDate range outside coverageCheck dataset metadata for available date range
ModuleNotFoundErrorSDK not installedRun:
cd /tmp && uv venv -q && source .venv/bin/activate && uv pip install gridstatusio pandas -q
"Unknown column" errorWrong filter columnZone data is in columns after fetch, not filterable. Use
df['load.comed']
429 Rate LimitedToo many requestsSDK auto-retries with backoff

Why Not curl?

The direct HTTP API has a critical issue on the free tier: date parameters are ignored and it returns sample data from years ago. The Python SDK correctly handles date filtering and returns current data.

If you must use curl (e.g., for dataset metadata), it works for non-query endpoints:

# This works - metadata endpoint
curl -s -H "x-api-key: $GRIDSTATUS_API_KEY" \
  "https://api.gridstatus.io/v1/datasets/pjm_load"

# This returns stale data - query endpoint has issues
curl -s -H "x-api-key: $GRIDSTATUS_API_KEY" \
  "https://api.gridstatus.io/v1/datasets/pjm_load/query?start=2026-01-25"  # BROKEN

Additional Resources

Reference Files

  • references/datasets-by-iso.md
    - Complete dataset catalog by ISO
  • references/api-reference.md
    - Full API parameter documentation
  • references/common-queries.md
    - Ready-to-use query patterns

Example Files

  • examples/python-query.py
    - Python SDK examples