WattTime Data API (V3)

Download OpenAPI specification:

Introduction

The WattTime API provides access to real-time, forecast, and historical data for electric grids around the world, including marginal emissions data. For the different signals we provide, see the data signals page.

If you’re curious about what you can do with this data, see the solutions we support, where you can dive into the various use cases. A common example of how to use the MOER value is to schedule load at the cleanest times of day.

You can access the API by sending standard HTTP requests to the endpoints listed below. The /v3/historical, /v3/forecast, and /v3/maps endpoints are only available to subscribers. However, if you don’t yet have a subscription, you can preview all of the available region-specific data by providing CAISO_NORTH as the region for your requests. A comparison of the different available data plans can be found here.

Python3 example code is provided in the right pane of this documentation which shows how to interact with the API endpoints. You can kick start your development by using our python client/SDK.

Restrictions

There is a strict limit on the rate at which you may query the API. From any user, we allow a maximum of 3,000 requests in any 5-minute rolling window (an average of 10 requests per second). There is also a lower limit specific to the /login endpoint, which is 100 requests in 5 minutes. If requests exceed this, an HTTP 429 error code is returned.

The API rate limit is a total of 3,000 requests in 5 minutes (an average of 10 per second). The limit for /login is 100 requests in 5 minutes.

API Status Page and User Alerts

WattTime publishes the current and historical uptime on the API Status Page. This page shows upcoming scheduled maintenance and provides updates during outages or maintenance. Users should subscribe to alerts via the status page to be kept up to date. This page is our method of communicating updates to our users related to maintenance, outages, and announcements related to version upgrades. Follow these instructions to subscribe to alerts:

  1. Navigate to the WattTime API Status Page
  2. Click the 'subscribe to updates' button in the top right corner
  3. Select your preferred means of notification (email, SMS, Slack, webhook)
  4. Enter your contact information (this will not be used for any other purpose)

Best Practices for API Usage

If using this API to control many smart devices in different locations, we suggest the following protocol. For each device location, use GPS lat/lon to query /v3/region-from-loc in order to determine the region for the desired signal_type. Then, query the other endpoints (e.g. /v3/forecast, /v3/historical, etc.) with the resulting region to receive signal data.

Because grid region boundaries are occasionally updated, it is important to re-query /v3/region-from-loc at least once a month to ensure devices are receiving the signal corresponding to their location. The /v3/maps endpoint provides a GeoJSON that can be used for offline geocoding. The GeoJSON file includes a last_updated field that changes whenever the grid regions change.

Authentication

To start using the API, first register for an account by using the /register endpoint. Then use the /login endpoint to obtain an access token. You can then use your token to access the remainder of our endpoints. You must include your token in an authorization (bearer) header in subsequent requests to retrieve data. Your access token will expire after 30 minutes and you'll need to sign in again to obtain a new one. Subsequent requests with an invalid, missing, or expired token will return an HTTP 401 error.

Register New User

Provide basic information to self-register for an account.

Note: The /register endpoint accepts the parameters in the body of the request. It does not accept them in the URL as a query string, because that isn't as secure. The input parameters should be included as a JSON object (in the body), as shown in the sample code on the right.

query Parameters
username
required
string (Username)
Examples: username=freddo

name of user that will be used in subsequent calls

password
required
string (Password)
Examples: password=the_frog

user password. Password must be at least 8 characters, with at least 1 of each alpha, number and special characters.

email
required
string <email> (Email)
Examples: email=freddo@frog.org

valid email address. The email address used to register will only be used for communication regarding API outages and updates. The email address will not be shared or used for any other promotional purpose. For others in your organization who would like these updates, they can subscribe to our Status Page.

Org (string) or Org (null) (Org)
Examples: org=freds world

organization name

Responses

Request samples


# To register, use the code below. Please note that for these code examples we are using filler values for username
# (freddo), password (the_frog), email (freddo@frog.org), org (freds world) and you should replace each if you are
# copying and pasting this code.

import requests
register_url = 'https://api.watttime.org/register'
params = {'username': 'freddo',
         'password': 'the_frog',
         'email': 'freddo@frog.org',
         'org': 'freds world'}
rsp = requests.post(register_url, json=params)
print(rsp.text)

Response samples

Content type
application/json
{
  • "ok": "User created",
  • "user": "freddo"
}

Login & Obtain Token

Use HTTP basic auth to exchange username and password for an access token. Remember that you need to include this token in an authorization bearer header for all subsequent data calls. This header has the form: Authorization: Bearer <your_token>

Note: Token expires after 30 minutes. If a data call returns HTTP 401 error code, you will need to call /login again to receive a new token.

Responses

Request samples


# To login and obtain an access token, use this code:

import requests
from requests.auth import HTTPBasicAuth
login_url = 'https://api.watttime.org/login'
rsp = requests.get(login_url, auth=HTTPBasicAuth('freddo', 'the_frog'))
TOKEN = rsp.json()['token']
print(rsp.json())

Response samples

Content type
application/json
{
  • "token": "abcdef0123456789fedcabc"
}

Password Reset

Provide your username to request an email be sent to you with password reset instructions.

query Parameters
username
required
string (Username)
Examples: username=freddo

name of user that will be used in subsequent calls

Responses

Request samples


# To reset your password, use this code:

import requests
password_url = 'https://api.watttime.org/password/?username=freddo'
rsp = requests.get(password_url)
print(rsp.json())

Response samples

Content type
application/json
{
  • "ok": "Please check your email for the password reset link"
}

GET Account Access

Get information about what your account can access

This endpoint describes the data that your account has access to. You can use it to plan your data queries or to programmatically monitor for updates (e.g. new regions, new models, etc.).

Returns a nested JSON response containing each combination of signal_type, region, endpoint, and model along with additional metadata that applies to each combination.

query Parameters
Region (string) or Region (null) (Region)
Examples: region=CAISO_NORTH

Region abbreviation associated with location, from result of query to /v3/region-from-loc

V3Signals (string) or V3HistoricalSignals (string) or Signal Type (any) or Signal Type (null) (Signal Type)
Examples: signal_type=co2_moer

Use to select any available signal_type which is authorized for your account

Responses

Request samples

import requests

url = "https://api.watttime.org/v3/my-access"

# Provide your TOKEN here, see https://docs.watttime.org/#tag/Authentication/operation/get_token_login_get for more information
TOKEN = ""
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())

Response samples

Content type
application/json
{
  • "signal_types": [
    ]
}

GET Regions and Maps

Determine Grid Region

Emissions intensity varies by location, specifically the location where an energy-using device is interconnected to the grid. This endpoint, provided with latitude and longitude parameters, returns the details of the grid region serving that location, if known, or a Coordinates not found error if the point lies outside of known/covered regions.

query Parameters
required
V3Signals (string) or V3HistoricalSignals (string) (Signal Type)
Examples: signal_type=co2_moer

signal_type for which to look up region

latitude
required
number (Latitude)
Examples: latitude=-72.519

Latitude of desired location

longitude
required
number (Longitude)
Examples: longitude=42.372

Longitude of desired location

Responses

Request samples


import requests

url = "https://api.watttime.org/v3/region-from-loc"

# Provide your TOKEN here, see https://docs.watttime.org/#tag/Authentication/operation/get_token_login_get for more information
TOKEN = ""
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {"latitude": "42.372", "longitude": "-72.519", "signal_type": "co2_moer"}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())

Response samples

Content type
application/json
{
  • "region": "ISONE_WCMA",
  • "region_full_name": "ISONE Western/Central Massachusetts",
  • "signal_type": "co2_moer"
}

Grid Region Map Geometry

Provides a geojson of the grid region boundary for all regions that WattTime covers globally. Check when the geojson was last updated using the last_updated value in the meta object of the geojson. Access to this endpoint is restricted to customers with ANALYST or PRO subscriptions. The response is a geojson response, that is a Feature Collection with properties that describe each region, and multipolygon geometry made up of coordinates which define the boundary for each region. The meta object contains the date-time that the geojson was last updated and the associated signal_type.

query Parameters
required
V3Signals (string) or V3HistoricalSignals (string) or Signal Type (any) (Signal Type)
Examples: signal_type=co2_moer

Use to select any available signal_type which is authorized for your account

Responses

Request samples

import requests

url = "https://api.watttime.org/v3/maps"

# Provide your TOKEN here, see https://docs.watttime.org/#tag/Authentication/operation/get_token_login_get for more information
TOKEN = ""
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {
    "signal_type": "co2_moer",
}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())

Response samples

Content type
application/json
{
  • "type": "FeatureCollection",
  • "features": [
    ],
  • "meta": {
    }
}

GET Forecast

Get the most recent forecast

Returns the most recently generated forecast for the specified region and signal_type. Forecasts are generated periodically (e.g. at 5-minute frequency, this frequency is described in the generated_at_period_seconds metadata), and there is a data list made up of point_time and value pairs in the forecast horizon (e.g. a 24-hr forecast horizon with 5-min frequency results in 288 values). Each forecast response is valid starting from its generated_at time until it is superseded by a new forecast with a new generated_at time, and each point_time in the data list is valid from its point_time for the duration described in data_point_period_seconds.

query Parameters
region
required
string (Region)
Examples: region=CAISO_NORTH

Region abbreviation associated with location, from result of query to /v3/region-from-loc

required
V3Signals (string) or Signal Type (any) (Signal Type)
Examples: signal_type=co2_moer

Use to select any available signal_type which is authorized for your account

Model (string) or Model (null) (Model)
Examples: model=2023-03-31

Use to return different models from defaults.

horizon_hours
integer (Horizon Hours) [ 0 .. 72 ]
Default: 24

Length of forecast horizon in hours. Setting this parameter to 0 will return a single value of the most recently produced forecast

Responses

Request samples

import requests

url = "https://api.watttime.org/v3/forecast"

# Provide your TOKEN here, see https://docs.watttime.org/#tag/Authentication/operation/get_token_login_get for more information
TOKEN = ""
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {
    "region": "CAISO_NORTH",
    "signal_type": "co2_moer",
}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

Get a range of historical forecasted data

Returns forecast data for the specified region, signal_type, and time period. The response contains a data list made up of generated_at and forecast pairs that cover the requested time period. The forecast list here includes all the values that were generated at the generated_at time.start and end are used to specify which generated_at forecasts will be returned. Individual queries are limited to 24 hours of generated_at forecasts (the range of start to end; this limit equals 288 generated_at times).

query Parameters
start
required
string <date-time> (Start)
Examples: start=2023-03-31T13:42:00Z

(inclusive) ISO8601-compliant timezone-aware date string indicating earliest desired forecast, used to select the first generated_at time

end
required
string <date-time> (End)
Examples: end=2023-03-31T13:42:00Z

(inclusive) ISO8601-compliant timezone-aware date string indicating latest desired forecast, used to select the last generated_at time

region
required
string (Region)
Examples: region=CAISO_NORTH

Region abbreviation associated with location, from result of query to /v3/region-from-loc

required
V3Signals (string) or Signal Type (any) (Signal Type)
Examples: signal_type=co2_moer

Use to select any available signal_type which is authorized for your account

Model (string) or Model (null) (Model)
Examples: model=2023-03-31

Use to return different models from defaults.

horizon_hours
integer (Horizon Hours) [ 0 .. 72 ]
Default: 24

Length of forecast horizon in hours. Setting this parameter to 0 will return a single value of the most recently produced forecast

Responses

Request samples

import requests

url = "https://api.watttime.org/v3/forecast/historical"

# Provide your TOKEN here, see https://docs.watttime.org/#tag/Authentication/operation/get_token_login_get for more information
TOKEN = ""
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {
    "region": "CAISO_NORTH",
    "start": "2023-07-15T00:00Z",
    "end": "2023-07-15T01:00Z",
    "signal_type": "co2_moer",
}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

GET Historical

Get a range of historical signal data

Returns signal data (e.g. CO₂ MOER in lbs/MWh) for the specified region, signal_type, and time period. Values are published in near real-time, periodically (e.g. at 5-minute frequency), and each value is valid starting from its point_time for the duration described in data_point_period_seconds. The publishing delay (the difference between the point_time for the value and the time that value is available in the API) varies by grid region. In some regions the data will be available within one minute after a certain point_time, in other regions there may be a delay of up to a few hours. Each query is limited to 32 days of data. Individual data point values may be updated at any time after publishing (e.g. if better source data is obtained).

query Parameters
start
required
string <date-time> (Start)
Examples: start=2023-03-31T13:42:00Z

(inclusive) ISO8601-compliant timezone-aware date string indicating earliest desired data, used to select the first point_time included in the response

end
required
string <date-time> (End)
Examples: end=2023-03-31T13:42:00Z

(inclusive) ISO8601-compliant timezone-aware date string indicating latest desired data, used to select the last point_time included in the response

region
required
string (Region)
Examples: region=CAISO_NORTH

Region abbreviation associated with location, from result of query to /v3/region-from-loc

required
V3Signals (string) or V3HistoricalSignals (string) (Signal Type)
Examples: signal_type=co2_moer

Use to select any available signal_type which is authorized for your account

Model (string) or Model (null) (Model)
Examples: model=2022-10-01

Use to return different models from defaults.

include_imputed_marker
boolean (Include Imputed Marker)
Default: false
Examples: include_imputed_marker=true

Use to return whether or not the value associated with a point_time is generated with imputed data.

Updated Since (string) or Updated Since (null) (Updated Since)
Examples: updated_since=2022-01-01T00:00:00Z

Filter results for data newer than the provided datetime.

Responses

Request samples

import requests

url = "https://api.watttime.org/v3/historical"

# Provide your TOKEN here, see https://docs.watttime.org/#tag/Authentication/operation/get_token_login_get for more information
TOKEN = ""
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {
    "region": "CAISO_NORTH",
    "start": "2022-07-15T00:00+00:00",
    "end": "2022-07-15T00:05+00:00",
    "signal_type": "co2_moer",
}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

GET Index

Get the current CO2 MOER index

Returns the current index value for the specified region for the co2_moer signal type. This 0-100 value is the statistical percentile of the current MOER relative to the upcoming 24 hours of forecast MOER values for the specified location (100=dirtiest, 0=cleanest). Values are updated periodically (e.g. at 5-minute frequency), and each value is valid starting from its point_time for the duration described in data_point_period_seconds. No historical query is available for this endpoint.

Data from this endpoint is available for free to all users in all covered regions.

query Parameters
region
required
string (Region)
Examples: region=CAISO_NORTH

Region abbreviation associated with location, from result of query to /v3/region-from-loc

signal_type
required
string (Signal Type)
Examples: signal_type=co2_moer

Only co2_moer indices are currently available.

Value: "co2_moer"

Responses

Request samples

import requests

url = "https://api.watttime.org/v3/signal-index"

# Provide your TOKEN here, see https://docs.watttime.org/#tag/Authentication/operation/get_token_login_get for more information
TOKEN = ""
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {
    "region": "CAISO_NORTH",
    "signal_type": "co2_moer",
}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

Technical Support

For technical questions related to this API and real-time emissions data, please contact support@WattTime.org

If you are experiencing an outage, please check the WattTime API Status Page to get the status of known outages, and if none are shown, please proceed to contact support@WattTime.org

For the fastest resolution of your issue, please also include the following along with your inquiry:

  • HTTP error codes received
  • The code snippet for your query/API request
  • Any relevant screen capture images
  • A short description of what you are trying to accomplish
  • Is this the first attempt? Or, a new error for something that used to work?