Power Demand API v1
Generated from
core.contract.describe_power_demand_v1()and checked fixture-backed examples. Do not hand-edit the example JSON files.
Capability
- Capability:
power.demand - Primitive:
query_power_demand_v1 - Status:
available - Current source:
energy.eia.eia930 - Source publisher: U.S. Energy Information Administration
- Snapshot behavior:
as_of = latestresolves to an exact snapshot date in every response.
What It Can Answer
- Hourly observed electricity demand (MW) for a balancing authority — EIA's Adjusted series, cited to the source row.
- The day-ahead demand forecast for the same BA-hours, and forecast-vs-actual misses.
- Which hours EIA imputed rather than metered (
is_imputed). - BA-level demand shape over time (daily/seasonal profiles at BA grain).
- Row-level detail records when
include_recordsis true. - Raw CSV row evidence for any returned row-level citation.
Represented Facts
EIA-930 reports hourly observed electricity demand (MW) by balancing authority — EIA's Adjusted series, with the raw value and imputation flag preservedEIA-930 reports the day-ahead demand forecast (MW) on the same balancing-authority-hour rows
Data Point Contract
- Data point:
power.demand - Product spec:
blocks/power_demand/card.md - Grain:
ba_hourly_flow - Source basis:
energy.eia.eia930 - Represented fact: EIA-930 reports hourly observed electricity demand (MW) by balancing authority — EIA's Adjusted series as the canonical value, with the raw series and the imputation flag preserved — plus the same row's day-ahead demand forecast, as a continuously revised hourly time series (history to 2015 H2).
Does not answer:
plant, generator, county, or lat/lon attribution (structural — EIA-930 carries no such IDs; permanent refusal)state-level demand (BA footprints do not follow state lines)US48 or region totals as source rows (computed rollups; BA additivity is an open PD — gen-only BAs report no demand and the BA set is time-varying)installed capacity (EIA-860M), monthly plant generation (EIA-923), retail sales/customers (EIA-861)wholesale prices or transmission projectslong-horizon demand forecasts (FERC-714, parked; the EIA-930 forecast is day-ahead only)reconciliation against EIA-923 or EIA-861 (different atoms by Rule 1/Rule 2; a discrepancy is a finding, never a canonical value)finality (the current half-year file is preliminary and continuously revisable)
REST Surface
GET /v1/healthGET /v1/capabilitiesGET /v1/power/demand/schemaPOST /v1/power/demand/queryPOST /v1/evidence/source-row
MCP Surface
list_capabilities_v1describe_power_demand_v1query_power_demand_v1get_source_evidence_v1
Local MCP Setup
Some MCP clients launch servers from the user's home directory or ignore a configured cwd. Use uv run --directory so the server always starts from the repository project.
{
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/OSINT",
"python",
"-m",
"core.mcp_server"
]
}
Leave EXASCALE_PARQUET_BASE / EXASCALE_RAW_BASE unset: the one server hosts every data point's tools, and with no override it resolves each block's promoted snapshots and raw archive from the repository layout. Setting either env var points ALL tools at one directory — a per-block path breaks every other block's tools. They exist only for single-source sandboxes and tests.
Request Schema
Filters:
as_ofbalancing_authority_coderegiondata_datehour_numberis_imputed
Input field semantics:
| Field | Answer Label | Source Field | Semantics | Definition | Counting Definition |
|---|---|---|---|---|---|
is_imputed |
EIA-imputed hour | Demand (MW) (Imputed) |
eia930_adjusted_demand_origin_flag | True where EIA's Adjusted demand came from EIA's Imputed series (fills AND overrides of reported raw values — PD-018); false where the Adjusted value passed through the reported raw value; null on forecast-only rows that carry no demand value yet. The filter accepts true, false, or {"is_null": true} for the forecast-only rows. | A count of is_imputed=true rows counts BA-hours whose served demand is EIA-imputed, including EIA overrides of reported raw values, not just fills of missing ones. |
Group by:
balancing_authority_coderegiondata_datehour_numberdatetime_utcis_imputed
Date range parameters:
data_date_fromdata_date_to
Controls:
include_recordsinclude_evidencelimitorder_bytop_norderrollup_other
Ranking (how order_by / top_n / order join — order_by ranks groups by a metric, never a group_by dimension; top_n needs both a group_by and an order_by):
{
"no_ranking": "Omit order_by and top_n to return all groups in group-key order.",
"order": {
"default": "desc",
"valid_values": [
"desc",
"asc"
]
},
"order_by": {
"accepts": "one of output.metrics",
"note": "Ranks the groups by a metric (a measure). Not a group_by dimension \u2014 rows already come back grouped by each group_by field.",
"requires": [
"group_by"
],
"valid_values": [
"demand_mw",
"demand_forecast_mw",
"source_record_count"
]
},
"top_n": {
"note": "Keeps the top N groups by order_by; the rest fold into one (other) remainder (additive metrics sum into it, non-additive ones are nulled) so the result still reconciles to summary.totals.",
"requires": [
"group_by",
"order_by"
],
"type": "positive integer"
}
}
Output Schema
Aggregate metrics:
demand_mwdemand_forecast_mwsource_record_count
Metric groups:
{
"demand_mw": [
"demand_mw",
"demand_forecast_mw"
],
"records": [
"source_record_count"
]
}
Response summary fields:
group_counttotals
Accepted fact policy:
- Query responses contain accepted, gate-passed facts only.
- Gate, monitor, and audit quality signals are internal controls, not agent-facing answer caveats.
- If a source snapshot is not fit to serve, the source must fail closed before it reaches this API.
Metric metadata:
| Metric | Category | Unit | Aggregation | Additive Across Groups | Authoritative Total | Definition |
|---|---|---|---|---|---|---|
demand_mw |
demand_mw | MW | sum | false | summary.totals.demand_mw |
Sum of EIA-930 hourly demand (MW, EIA's Adjusted series) within the current result scope. |
demand_forecast_mw |
demand_mw | MW | sum | false | summary.totals.demand_forecast_mw |
Sum of EIA-930 day-ahead hourly demand forecast (MW) within the current result scope. |
source_record_count |
records | count | count source records | true | summary.totals.source_record_count |
Count of normalized source rows (BA-hours) contributing to the current result scope. |
Rollup rules:
summary.totals.<metric>is the authoritative total for the full matched query.- Grouped row metrics may be summed only when
additive_across_groupsistrue. - Do not sum grouped values for these non-additive metrics:
demand_mw,demand_forecast_mw.
Detail record fields returned when include_records is true:
source_idsheet_namesource_record_keyreport_periodbalancing_authority_coderegiondata_datehour_numberdatetime_localdatetime_utcdemand_mwdemand_mw_rawis_imputeddemand_forecast_mwsource_row_numberas_ofraw_file_sha256citation
Row-level citation fields:
source_idsource_urlsource_filesheetsource_rowraw_file_sha256as_of
Aggregate citation fields:
source_idpublishersource_urlsource_fileraw_file_sha256as_ofsource_rows_countsource_rows_sampleverifylineage_filter
Codebooks
| Field | Coverage | Codes | Examples | Note |
|---|---|---|---|---|
balancing_authority_code |
complete_for_gated_eia930_balance_rows | 72 | AEC = PowerSouth Energy Cooperative, AECI = Associated Electric Cooperative, Inc., AVA = Avista Corporation, AVRN = Avangrid Renewables, LLC, AZPS = Arizona Public Service Company |
EIA-930's BA code is the reporting entity itself, valid only inside its [activation, retirement) window (PD-020) — a retired BA's later months are honestly empty, never zero, and successor folds are not stitched. generation_only BAs report no demand (PD-021). A balancing authority is not a state. ERCO (ERCOT) lies wholly within Texas and covers ~90% of its load, but state=TX is the larger jurisdiction — it also includes non-ERCOT El Paso (WECC), the Panhandle (SPP), and East Texas (MISO), a material (~20%+) difference. Use balancing_authority_code for a grid and state for a jurisdiction; they are not interchangeable. When a phrase like 'the Texas grid' is ambiguous between the two, report both readings rather than guessing one (PD-009). |
region |
complete_for_gated_eia930_balance_rows | 13 | CAL = California, CAR = Carolinas, CENT = Central, FLA = Florida, MIDA = Mid-Atlantic |
EIA's 13 display regions for the lower-48 grid. A region is a display grouping of BAs, not a jurisdiction; region demand sums carry the same PD-021 non-additivity note as any other cross-BA sum. |
The complete machine-readable codebooks are included in capability-schema.json.
Checked Examples
| Agent question | Request params | Checked output |
|---|---|---|
| What was PJM's hourly demand on 2026-03-07? | {"balancing_authority_code": "PJM", "data_date": "2026-03-07", "group_by": ["datetime_utc"]} |
hourly-demand-curve.json |
| How does daily demand compare across balancing authorities for 2026-03-07 through 2026-03-09? | {"data_date_from": "2026-03-07", "data_date_to": "2026-03-09", "group_by": ["balancing_authority_code", "data_date"]} |
demand-by-ba.json |
| How did PJM's day-ahead forecast compare to actual demand, hour by hour, on 2026-03-08? | {"balancing_authority_code": "PJM", "data_date": "2026-03-08", "group_by": ["hour_number"]} |
forecast-vs-actual-day.json |
| Which IID hours on 2026-05-20 carry EIA-imputed demand? | {"balancing_authority_code": "IID", "data_date": "2026-05-20", "group_by": ["datetime_utc"], "is_imputed": true} |
imputed-hours-only.json |
| Return one PJM demand row with a row-level citation. | {"balancing_authority_code": "PJM", "data_date": "2026-03-07", "include_records": true, "limit": 1} |
demand-detail-with-citation.json |
| Verify the raw workbook row behind a returned citation | citations[ref].verify (aggregate) or records[0].citation (detail) |
source-row-evidence.json |
| Dogfood the tool sequence as an agent | list -> describe -> query -> evidence |
agent-dogfood-transcript.json |
The checked schema output is capability-schema.json.
Agent Workflow
- Call
list_capabilities_v1and selectpower.demand. - Call
describe_power_demand_v1to inspect valid filters, groupings, metrics, and citation fields. - Call
query_power_demand_v1with bounded JSON params. - If the answer needs proof, pass a returned row-level
citationobject toget_source_evidence_v1. - Answer with the resolved
as_ofand relevant citations. Present returned metrics as authoritative for their declared source, snapshot, grain, and aggregation.