A flexible API for demand forecasting data that can output local CSV files, serve a local API (OpenAPI 3.1), or deploy to cloud services.
The Demand Toolkit API provides endpoints for accessing demand forecasting data across multiple temporal resolutions and geographic boundaries. It's designed to work with the Python-based generator and Svelte explorer components of the Demand Toolkit.
- Multiple Output Formats: JSON and GeoJSON support
- Flexible Temporal Resolution: From hourly to yearly data
- Geographic Boundaries: Configurable geography support
- Scenario Management: Multiple forecasting scenarios
- Parameter Validation: OpenAPI 3.1 specification compliance
- Local & Cloud Deployment: Works locally or on AWS
GET /geographies- List of geographic boundaries (JSON or GeoJSON)GET /config- Configuration metadata including units configuration (SI prefixes for energy/power display)GET /scenarios- Available forecasting scenariosGET /parameters- Valid parameter combinationsGET /aggregations- Available aggregation methodsGET /globals- Pre-computed global statistics and bounds for visualization scaling
GET /demand- Time-series demand data with flexible aggregation (uses DuckDB)
The API uses a nested Parquet file structure for efficient querying:
data/
├── base/
│ └── current-policy/
│ └── data.parquet # Base scenario (21 geographies × 5 segments × 8760 hours × 26 years)
├── scenarios/
│ ├── housing_electrification=0/
│ │ └── transport_electrification=0/
│ │ └── industry_transition=0/
│ │ └── data.parquet # Parametric scenario files
│ └── ... (75 scenario combinations)
└── aggregated/ # Pre-computed aggregations for fast queries
├── geography_yearly.parquet # Yearly totals per geography
├── segment_yearly.parquet # Yearly totals per segment
├── national_yearly.parquet # Yearly national totals
└── scenario_metadata.parquet # Scenario parameter combinations
- Dynamic queries: DuckDB scans Parquet files with predicate pushdown
- Pre-aggregated tables: 50-100x faster for common yearly queries
- UNION queries: Combines base and scenario data with schema normalization
-
Install dependencies:
npm install
-
Generate data (requires Python generator):
# Run generator first to create Parquet files cd ../generator jupyter notebook notebooks/behovskartan2.ipynb
-
Generate static endpoints and globals:
cd ../api node generate-api.js --defaults -
Start local server:
npm start # API available at http://localhost:4010 -
Test the API:
# Static endpoints (baked at startup, 1-hour cache): curl http://localhost:4010/globals curl http://localhost:4010/parameters curl http://localhost:4010/_health # /demand takes a nested `period` object. Encode it with bracket # notation in the query string (`qs` library format): curl -G http://localhost:4010/demand \ --data-urlencode 'period[start]=2030' \ --data-urlencode 'period[end]=2031' \ --data-urlencode 'period[resolution]=1Y' \ --data-urlencode 'period[aggregation]=sum' \ --data-urlencode 'geography=total' \ --data-urlencode 'segment=total' \ --data-urlencode 'baseScenario=beslutad-policy' # Same request as CSV (RFC 4180 quoted, Content-Disposition attachment): curl -G http://localhost:4010/demand \ --data-urlencode 'period[start]=2030' \ --data-urlencode 'period[end]=2031' \ --data-urlencode 'period[resolution]=1Y' \ --data-urlencode 'period[aggregation]=sum' \ --data-urlencode 'geography=total' \ --data-urlencode 'segment=total' \ --data-urlencode 'baseScenario=beslutad-policy' \ --data-urlencode 'format=csv' \ -o demand.csv
-
Access API documentation:
npm run docs:build npm run docs:serve
npm test # Run tests
npm run test:coverage # Run with coverage
npm run test:watch # Watch modeThis API uses TypeDoc to generate comprehensive documentation from JSDoc comments. The documentation includes:
- Function References: Complete API for all modules
- Usage Examples: Code examples for common operations
- Type Definitions: Parameter and return types
- Integration Guides: How to use with other toolkit components
The API follows a modular architecture with:
- Core Utilities (
utils.js) - Date parsing and period handling - Endpoint Generators (
scripts/endpoints/) - Static data generation - OpenAPI Specification (
openapi.yaml) - API contract definition - Local Server (
local-server.js) - Express + OpenAPI Backend + DuckDB - API Generation (
generate-api.js) - Orchestrates static endpoint generation and globals computation
Local Server (local-server.js):
- Uses OpenAPI Backend for request validation and routing
- Serves static JSON files for
/config,/parameters,/scenarios,/geographies,/aggregations,/globals - Uses DuckDB for dynamic
/demandqueries against Parquet files - Supports CORS for local development with Explorer frontend
API Generation (generate-api.js):
- Validates data directory exists and contains Parquet files
- Generates all static JSON endpoints from config files
- Computes global statistics with DuckDB analysis of Parquet data
- Creates
globals.jsonwith aggregation-specific bounds
Static endpoints are generated from configuration files:
parameters.json←/api/parameters.yaml+/api/openapi.yamlgeographies.json/geographies.geojson←/config.yamlscenarios.json←/config.yaml(scenario parameter combinations)aggregations.json←/config.yaml(resolution-aggregation combinations)config.json←/config.yaml(filtered for public access, includes units configuration)globals.json← DuckDB analysis of Parquet files (computed bounds for visualizations)
See the TypeDoc generated documentation for detailed API references and usage examples.