Gramm Forecast API
Production API documentation for supported U.S. power markets. RESTful JSON API with forecast horizons from 1 day to 15 days across 7 ISO regions.
What to check before integration
Review the API surface below, then pair it with the public benchmark on /accuracy and the review materials on /enterprise. Gramm supports day-ahead forecasts and extended horizons where the grid, plan, and validation status allow them.
Base URL
https://api.gramm.ai/v1All endpoints are versioned under /v1. Responses are JSON by default.
Authentication
All queries except TAC_AREAS require a Bearer token:
Authorization: Bearer grmm_your_api_keyCreate an account to get an API key. Keys are prefixed with grmm_ and shown once on creation.
Supported Regions
Use any of these codes as the region parameter. List all via GET /v1/regions.
CAISOERCOTPJMMISONYISOISONESPPEndpoints
/v1/demand/forecastSystem load demand forecast. Returns MW values at the requested resolution (1h or 15min) for the requested horizon.
regionYesCAISO, PJM, ERCOT, MISO, NYISO, ISONE, SPP. Aliases accepted: CISO, ERCO, ISNE, NYIS, SWPP.
horizonNo1d (default), 2d, 7d, 15d. Availability varies by plan and grid.
resolutionNo1h (default), 15min. Sub-hourly resolution requires a paid plan where available.
Example
curl "https://api.gramm.ai/v1/demand/forecast?region=CAISO&horizon=2d" \
-H "Authorization: Bearer grmm_your_api_key"Response (Developer plan and above)
{
"status": "success",
"data": [
{ "timestamp": "2026-04-09T08:00:00+00:00", "value_mw": 24523.4, "p10": 23892.1, "p90": 25104.7 },
{ "timestamp": "2026-04-09T09:00:00+00:00", "value_mw": 25891.7, "p10": 25201.4, "p90": 26573.9 }
],
"meta": {
"region": "CAISO",
"horizon": "2d",
"resolution": "1h",
"count": 48,
"issued_at": "2026-04-09T06:00:00Z",
"model": "gramm-v22",
"generated_at": "2026-04-09T12:34:56Z"
}
}Free responses omit the p10/p90 keys. Prediction intervals are populated on rows where the model has produced them; intervals are absent on rows that do not yet carry quantile estimates.
/v1/demand/historyHistorical actual load from EIA data. Defaults to last 24 hours. Maximum query range: 31 days.
regionYesCAISO, PJM, ERCOT, MISO, NYISO, ISONE, SPP. Aliases accepted.
startNoISO 8601 datetime (default: 24h ago).
endNoISO 8601 datetime (default: now).
curl "https://api.gramm.ai/v1/demand/history?region=PJM&\
start=2026-04-07T00:00:00Z&end=2026-04-08T00:00:00Z" \
-H "Authorization: Bearer grmm_your_api_key"/v1/demand/latestLatest actual load value and most recent forecast for a region. Useful for dashboards and real-time monitoring.
{
"status": "success",
"data": {
"region": "ERCOT",
"actual": { "timestamp": "2026-04-09T12:00:00Z", "value_mw": 45231.5 },
"forecast": { "timestamp": "2026-04-09T13:00:00Z", "value_mw": 46102.3, "issued_at": "2026-04-09T06:00:00Z" }
}
}/v1/demand/accuracyLive forecast accuracy metrics. Computes MAPE, RMSE, MAE, and bias from actual forecast vs actuals data.
{
"status": "success",
"data": {
"region": "CAISO",
"metrics": {
"mape_pct": 2.62,
"mae_mw": 245.8,
"rmse_mw": 312.5,
"bias_mw": -15.2,
"sample_hours": 720
},
"model": {
"name": "gramm-v22",
"version": "v22",
"last_run": "2026-04-09T06:00:00Z",
"forecast_count": 336
}
}
}/v1/regionsList all supported regions with ISO name, timezone, available horizons, and status. No authentication required.
/v1/healthAPI health check. Returns status, model version, active grid count, and last forecast run time. No authentication required.
Rate Limits & Data Access
Exceeding your plan's rate limits returns HTTP 429 with a Retry-After header. Historical data access and per-region daily caps also vary by plan.
Free
- Req / Hour
- 100
- Req / Day
- 1,000
- API Keys
- 2
- History
- 24 hours
- Per-Region / Day
- 50
Developer
- Req / Hour
- 10,000
- Req / Day
- 50,000
- API Keys
- 5
- History
- 30 days
- Per-Region / Day
- 5,000
Team
- Req / Hour
- 50,000 pooled
- Req / Day
- 500,000 pooled
- API Keys
- Unlimited team
- History
- 30 days
- Per-Region / Day
- 5,000
Enterprise
- Req / Hour
- Custom
- Req / Day
- Custom
- API Keys
- Custom
- History
- 1 year
- Per-Region / Day
- 50,000
| Plan | Req / Hour | Req / Day | API Keys | History Window | Per-Region / Day |
|---|---|---|---|---|---|
| Free | 100 | 1,000 | 2 | 24 hours | 50 |
| Developer | 10,000 | 50,000 | 5 | 30 days | 5,000 |
| Team | 50,000 (pooled) | 500,000 (pooled) | Unlimited (team) | 30 days | 5,000 |
| Enterprise | Custom | Custom | Custom | 1 year | 50,000 |
Error Responses
Errors use machine-readable string codes. XML format for OASIS queries, JSON for resultformat=7. Every error includes a request_id for support debugging.
XML Error Response
<?xml version="1.0" encoding="UTF-8"?>
<OASISReport>
<MessagePayload>
<RTO>
<ERROR>
<ERR_CODE>rate_limited</ERR_CODE>
<ERR_DESC>Rate limit exceeded for Free plan. Retry after 1823 seconds.</ERR_DESC>
<REQUEST_ID>req_m3k8f2_a9c4xp</REQUEST_ID>
<DOCUMENTATION_URL>https://gramm.ai/api-docs#rate-limits</DOCUMENTATION_URL>
</ERROR>
</RTO>
</MessagePayload>
</OASISReport>JSON Error Response (resultformat=7)
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for Free plan. Retry after 1823 seconds.",
"documentation_url": "https://gramm.ai/api-docs#rate-limits",
"request_id": "req_m3k8f2_a9c4xp",
"details": {
"plan": "free",
"limit_hourly": 100,
"remaining_hourly": 0,
"limit_daily": 1000,
"remaining_daily": 450,
"retry_after_seconds": 1823
}
}
}unauthorizedMissing or invalid API key
invalid_keyAPI key revoked or not found
rate_limitedRate limit exceeded (includes Retry-After header)
invalid_queryUnsupported queryname
missing_parameterRequired parameter not provided
no_dataNo forecast data available for this grid
| HTTP | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing or invalid API key |
| 401 | invalid_key | API key revoked or not found |
| 429 | rate_limited | Rate limit exceeded (includes Retry-After header) |
| 400 | invalid_query | Unsupported queryname |
| 400 | missing_parameter | Required parameter not provided |
| 404 | no_data | No forecast data available for this grid |
Quick Start
Python
import requests
BASE_URL = "https://api.gramm.ai/v1"
headers = {"Authorization": "Bearer grmm_your_api_key"}
# Get 48-hour forecast for ERCOT
resp = requests.get(f"{BASE_URL}/demand/forecast",
params={"region": "ERCOT", "horizon": "2d"},
headers=headers)
data = resp.json()
for point in data["data"]:
print(f"{point['timestamp']}: {point['value_mw']:.0f} MW")cURL
# Forecast
curl "https://api.gramm.ai/v1/demand/forecast?region=CAISO&horizon=7d" \
-H "Authorization: Bearer grmm_your_api_key"
# Historical actuals (no auth needed for regions)
curl "https://api.gramm.ai/v1/regions"OASIS Compatibility (Legacy)
For teams migrating from CAISO OASIS, a compatibility endpoint is available at /v1/oasis. It accepts the same parameters as CAISO OASIS (queryname, tac_area_name, market_run_id, startdatetime, enddatetime, resultformat) and returns OASIS-compatible CSV/XML. We recommend migrating to the v1 REST endpoints above for new integrations.
# OASIS compatibility endpoint
curl "https://api.gramm.ai/v1/oasis?queryname=SLD_FCST&\
market_run_id=DAM&tac_area_name=CISO&resultformat=6" \
-H "Authorization: Bearer grmm_your_api_key"Try the API
Build a request interactively. Select parameters below to generate the URL and code snippets.
API Builder
Select an endpoint and parameters to generate request URLs and code snippets.
https://api.gramm.ai/v1/demand/forecast?region=CAISO&horizon=2dcurl "https://api.gramm.ai/v1/demand/forecast?region=CAISO&horizon=2d" \
-H "Authorization: Bearer grmm_your_api_key"Support
Contact: hello@gramm.ai