NAV
Python3

Introduction

WattTime technology—based on real-time grid data, cutting-edge algorithms, and machine learning—provides first-of-its-kind insight into your local electricity grid’s marginal emissions rate.

The WattTime API provides access to real-time, forecast, and historical marginal emissions data for electric grids around the world. For a deeper understanding of these Marginal Operating Emissions Rates (MOERs) please see What is AER and How AER works.

You can access the API by sending standard HTTP requests to the endpoints listed below.

The /data, /historical, and /forecast endpoints are only available to subscribers. However, if you don’t yet have a subscription, you can preview the available data by providing CAISO_NORTH as the ba for your requests. ANALYST and PRO 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. For an example python script that pulls everything together, please see our example code.

Restrictions

There is a strict limit on the rate at which you may query the API. From any single IP address we allow a maximum of 3,000 requests in any 5-minute rolling window (an average of 10 requests per second). If requests exceed this, an HTTP 429 error code returned.

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, query /ba-from-loc to determine the ba (the balancing authority serving the device). Then, query /index with the resulting ba to receive MOER data.

Because balancing authority region boundaries are occasionally updated, it is important to re-query /ba-from-loc at least once a month to ensure devices are receiving the correct signal.

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.

Register New User

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://api2.watttime.org/v2/register'
params = {'username': freddo,
         'password': 'the_frog',
         'email': 'freddo@frog.org',
         'org': 'freds world'}
rsp = requests.post(register_url, json=params)
print(rsp.text)

The above command returns JSON structured like this:

{
  "user": "freddo",
  "ok": "User created"
}

/register

Provide basic information to self register for an account.

HTTP Request

POST https://api2.watttime.org/v2/register

Query Parameters

Parameter Description Example Type
username (required) name of user that will be used in subsequent calls freddo string
password (required) user password the_frog string
email (required) valid email address freddo@frog.org string
org organization name freds world string

Login & Obtain Token

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

import requests
from requests.auth import HTTPBasicAuth
login_url = 'https://api2.watttime.org/v2/login'
rsp = requests.get(login_url, auth=HTTPBasicAuth('freddo', 'the_frog'))
print(rsp.json())

The above command returns your personal token, in JSON structure like this:

{
  "token": "abcdef0123456789fedcabc"
}

/login

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>

HTTP Request

GET https://api2.watttime.org/v2/login

URL Query Parameters

Parameter Description
none uses basic authentication

Response

Attribute Description
token abcdef0123456789fedcabc

Password Reset

To reset your password, use this code:

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

Sample Response:

{
  "ok": "Please check your email for the password reset link"
}

/password

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

HTTP Request

GET https://api2.watttime.org/v2/password

URL Query Parameters

Parameter Example Type
username freddo string

Response

Attribute Description Type
"ok" Message confirming reset link has been sent string

Grid Emissions Information

Determine Grid Region

Make sure to replace the parameters username (e.g. ‘freddo’) and password (e.g. ‘the_frog’) with your registered credentials when using this code. You should not add in your token here. The code automatically generates a new token each time you run it.

import requests
from requests.auth import HTTPBasicAuth

login_url = 'https://api2.watttime.org/v2/login'
token = requests.get(login_url, auth=HTTPBasicAuth(freddo, the_frog)).json()['token']

region_url = 'https://api2.watttime.org/v2/ba-from-loc'
headers = {'Authorization': 'Bearer {}'.format(token)}
params = {'latitude': '42.372', 'longitude': '-72.519'}
rsp=requests.get(region_url, headers=headers, params=params)
print(rsp.text)

Sample Response

{
"id":169,
"abbrev":"ISONE_WCMA",
"name":"ISONE Western/Central Massachusetts"
}

/ba-from-loc

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 balancing authority (BA) serving that location, if known, or an Coordinates not found error if the point lies outside of known/covered BAs. For more information on what a balancing authority is, see this explanation from the EIA.

HTTP Request

GET https://api2.watttime.org/v2/ba-from-loc

URL Query Parameters

Parameter Description Example Type
latitude Latitude of device location 42.372 float
longitude Longitude of device location -72.519 float

Response

Parameter Description Example Type
abbrev Balancing authority abbreviation ISONE_WCMA string
id Unique WattTime id for the region 169 integer
name Human readable name/description for the region ISONE Western/Central Massachusetts string

Real-time Emissions Index

import requests
from requests.auth import HTTPBasicAuth

login_url = 'https://api2.watttime.org/v2/login'
token = requests.get(login_url, auth=HTTPBasicAuth('freddo', 'the_frog')).json()['token']

index_url = 'https://api2.watttime.org/index'
headers = {'Authorization': 'Bearer {}'.format(token)}
params = {'ba': 'CAISO_NORTH'}
rsp=requests.get(index_url, headers=headers, params=params)
print(rsp.text)

Sample Response

{
    "freq": "300",   
    "ba": "CAISO_NORTH",
    "percent": "53",
    "moer": "850.743982",
    "point_time": "2019-01-29T14:55:00.00Z",
}

/index

Provides a real-time signal indicating the marginal carbon intensity for the local grid for the current time (updated every 5 minutes). The current marginal emissions rate of the grid is returned as a raw Marginal Operating Emissions Rate (MOER) value (available only to users with PRO subscriptions), or as an index value (percent), which is available to all users. This value is returned along with a freq value, indicating how long the value is in effect. The type of value returned is set by the style query parameter.

The CO2 MOER value is given in lbs of CO2 per MWh, whereas the reported index value is given as a percentage between the lowest and highest MOER values observed in the past two weeks in the given grid region. A higher index indicates a higher MOER value (i.e. higher carbon intensity).

HTTP Request

GET https://api2.watttime.org/v2/index

URL Query Parameters

Parameter Description Example Type
ba Balancing authority abbreviation. (Optional: provide ba OR provide latitude+longitude, not all three) CAISO_NORTH string
latitude Latitude of device location 42.372 float
longitude Longitude of device location -72.519 float
style (Optional) Units in which to provide realtime marginal emissions. Choices are 'percent', 'moer' or 'all'. If you have PRO access you may use 'moer' to get the latest raw MOER value. Defaults to 'all' if not provided all string

Response

Parameter Description Example Type
freq Duration in seconds for which the data is valid from point_time 300 string
ba Balancing authority abbreviation CAISO_NORTH string
percent A value between 0 (minimum MOER in the last two weeks i.e. clean) and 100 (maximum MOER in the last two weeks i.e. dirty) representing the relative realtime marginal emissions intensity. 53 stringified integer
moer Marginal Operating Emissions Rate (MOER) measured in lbs CO2/MWh. This is only available for PRO subscriptions. 850.743 stringified float
point_time ISO8601 UTC date/time format indicating when this data became valid 2019-01-29T14:55:00.00Z string

Grid Emissions Data

import requests
from requests.auth import HTTPBasicAuth

login_url = 'https://api2.watttime.org/v2/login'
token = requests.get(login_url, auth=HTTPBasicAuth('freddo', 'the_frog')).json()['token']

data_url = 'https://api2.watttime.org/v2/data'
headers = {'Authorization': 'Bearer {}'.format(token)}
params = {'ba': 'CAISO_NORTH', 
          'starttime': '2019-02-20T16:00:00-0800', 
          'endtime': '2019-02-20T16:15:00-0800'}
rsp = requests.get(data_url, headers=headers, params=params)
print(rsp.text)

Sample Response

[
{"point_time": "2019-02-21T00:15:00.000Z", "value": 844, "frequency": 300, "market": "RTM", "ba": "CAISO_NORTH", "datatype": "MOER", "version": "3.0"}, 
{"point_time": "2019-02-21T00:10:00.000Z", "value": 834, "frequency": 300, "market": "RTM", "ba": "CAISO_NORTH", "datatype": "MOER", "version": "3.0"}, 
{"point_time": "2019-02-21T00:05:00.000Z", "value": 834, "frequency": 300, "market": "RTM", "ba": "CAISO_NORTH", "datatype": "MOER", "version": "3.0"}, 
{"point_time": "2019-02-21T00:00:00.000Z", "value": 844, "frequency": 300, "market": "RTM", "ba": "CAISO_NORTH", "datatype": "MOER", "version": "3.0"}
]

/data

Obtain historical marginal emissions for a given area (balancing authority abbreviated code, ba) or location (latitude & longitude pair).

Access to this endpoint is restricted to customers with ANALYST or PRO subscriptions. However, if you don’t yet have a subscription, you can preview the available data by providing CAISO_NORTH as the ba for your requests.

HTTP Request

GET https://api2.watttime.org/v2/data/?ba=CAISO_NORTH&endtime=2019-02-20T16:15:00-0800&style=all&moerversion=3.0

URL Query Parameters

Parameter Description Example Type
ba Balancing authority abbreviation (Optional: provide ba OR provide latitude+longitude, not all three) CAISO_NORTH string
latitude Latitude of device location 42.372 float
longitude Longitude of device location -72.519 float
starttime ISO 8601 timestamp (inclusive) - may be omitted if endtime is also omitted. If both are omitted, returns the most recent data point. 2019-02-20T16:00:00-0800 string
endtime ISO 8601 timestamp (inclusive) - if endtime is omitted, endtime is equal to the current time. 2019-02-20T16:15:00-0800 string
style (Optional) Style of data to provide - can be ‘all’ or ‘moer’. Defaults to ‘all’ if omitted. all string
moerversion (Optional) MOER version. Defaults to the latest version for a given region if omitted. Use this field only to request a particular version. 3.0 string

Response

Parameter Description Example Type
ba Balancing authority abbreviation CAISO_NORTH string
datatype Type of data MOER string
frequency Duration in seconds for which the data is valid from point_time 300 integer
market Market type, only useful for grid data other than MOERs. Some examples are ‘RTM’ (real time market) and ‘DAM’ (day ahead market). Market descriptor may vary by balancing authority. RTM string
point_time ISO8601 UTC date/time format indicating when this data became valid 2019-01-29T14:55:00.00Z string
value Number value of data (corresponding to datatype above) 909.06 float
version MOER version (Not present and not applicable for other datatypes) 3.0 string

Historical Emissions

from os import path
import requests
from requests.auth import HTTPBasicAuth

login_url = 'https://api2.watttime.org/v2/login'
token = requests.get(login_url, auth=HTTPBasicAuth('freddo', 'the_frog')).json()['token']

historical_url = 'https://api2.watttime.org/v2/historical'
headers = {'Authorization': 'Bearer {}'.format(token)}
ba = 'NYISO_NYC'
params = {'ba': ba}
rsp = requests.get(historical_url, headers=headers, params=params)
cur_dir = path.dirname(path.realpath('__file__'))
file_path = path.join(cur_dir, '{}_historical.zip'.format(ba))
with open(file_path, 'wb') as fp:
    fp.write(rsp.content)

print('Wrote historical data for {} to {}'.format(ba, file_path))

Sample Response

Content-Type:application/zip

/historical

Obtain a zip file containing monthly .csv files with the MOER values and timestamps for a given region for (up to) the past two years.

WattTime periodically updates the algorithms used to calculate new MOERs to add new features, incorporate new data sources, or in response to changing grid dynamics. This endpoint provides you with the option to retrieve all the MOER versions published for a given region or to retrieve only the most up-to-date version.

Historical data will be updated on the 2nd day of each month at midnight UTC for the previous month.

Access to this endpoint is restricted to customers with ANALYST or PRO subscriptions. However, if you don’t yet have a subscription, you can preview the available data by providing CAISO_NORTH as the ba for your requests.

HTTP Request

GET https://api2.watttime.org/v2/historical

URL Query Parameters

Parameter Description Example Type
ba Balancing authority abbreviation NYISO_NYC string
version (Optional) Retrieve either the latest MOER version or all MOER versions ever published for this BA.. Provide ‘latest’ for the latest version or ‘all’ for all versions. Defaults to ‘latest’ if omitted. all string

Response

Description Type
A binary zip file payload containing monthly .csv files with MOERs for the specified balancing authority for the past two years. Save the body to disk and unzip it. Binary Data Zip File

Emissions Forecast

import requests
from requests.auth import HTTPBasicAuth

login_url = 'https://api2.watttime.org/v2/login'
token = requests.get(login_url, auth=HTTPBasicAuth('freddo', 'the_frog')).json()['token']

forecast_url = 'https://api2.watttime.org/v2/forecast'
headers = {'Authorization': 'Bearer {}'.format(token)}
params = {'ba': ''NYISO_NYC'', 
          'starttime': '2021-08-05T09:00:00-0400', 
          'endtime': '2021-08-05T09:05:00-0400'}
rsp = requests.get(forecast_url, headers=headers, params=params)
print(rsp.text)

Sample Response

[
  {
    "generated_at": "2021-08-05T09:05:00+00:00", 
    "forecast": 
      [
        {
          "point_time": "2021-08-05T09:10:00+00:00",
          "ba": "NYISO_NYC",
          "value": 887.0946245162808,
          "version": "3.0-1.0.0"
        },
        {
          "point_time": "2021-08-05T09:15:00+00:00",
          "ba": "NYISO_NYC",
          "value": 887.2882214363948,
          "version": "3.0-1.0.0"},

         ..... <24 hours worth of datapoints>
      ]
  }
]

/forecast

Obtain MOER forecast data for a given region. Omitting the starttime and endtime parameters will return the most recently generated forecast for a given region. Use the starttime and endtime parameters to obtain historical forecast data.

Note that starttime and endtime define the time when a forecast was generated. Every five minutes, WattTime generates a new forecast which is 24 hours in duration. So, if you make a request to the /forecast endpoint with starttime of Jan 1, 1:00 and endtime of Jan 1, 1:05, you will receive the forecast (all 288 values in the forecast window) generated at 1:00, and since this query is inclusive the forecast generated at 1:05, on January 1.

Access to this endpoint is restricted to customers with PRO subscriptions. However, if you don’t yet have a subscription, you can preview the available data by providing CAISO_NORTH as the ba for your requests.

HTTP Request

GET https://api2.watttime.org/v2/forecast

URL Query Parameters

Parameter Description Example Type
ba Balancing authority abbreviation NYISO_NYC string
starttime (Optional) ISO 8601 timestamp (inclusive) - Omit to obtain the real-time forecast. If included, those forecasts generated between start and endtime are returned. 2021-08-05T09:00:00-0400 string
endtime (Optional) ISO 8601 timestamp (inclusive)- Omit to obtain the real-time forecast. If included, those forecasts generated between start and endtime are returned. 2021-08-05T09:05:00-0400 string

Response

Attribute Description Example Type
generated_at ISO 8601 timestamp indicating when the forecast was generated 2021-08-05T09:05:00+00:00 string
forecast List of forecasts - see description below object

The value of the forecast key is a list of dictionaries containing the following keys:

Key Description Example Type
ba Balancing authority abbreviation NYISO_NYC string
point_time ISO8601 UTC date/time format indicating when this data became valid 2021-08-05T09:10:00+00:00 string
value MOER forecast value 887.0946245162808 float
version MOER forecast version 3.0-1.0.0 string

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