Download OpenAPI specification:
The API documentation below is intended for software developers. Access to the data is available through this application programming interface, which is typically accessed by writing software code or using an HTTP request tool like Postman. There is not a graphical user interface available to login and view data.
The API can be accessed by sending standard HTTP requests to the endpoints listed below to obtain real-time or historical marginal GHG emissions rates. Units are in kg CO2 per kWh. Each point_time is valid from its point_time for the following 5 minutes.
To start using the API, first create an account, then sign in to obtain an access token. You can then use your access token to access the remainder of our endpoints. Your access token will expire after 30 minutes and you'll need to sign in again to obtain a fresh access token.
For example (Python3) code that can be used to register, log in, and query data, please see https://github.com/WattTime/sgip-api
For questions about SGIP and the GHG requirements please reach out to the Program Administrators: SoCalGas (selfgeneration@socalgas.com), SCE (SGIPgroup@sce.com), CSE (sgip@energycenter.org), or PG&E (selfgen@pge.com). For questions related to this API and real-time emissions data, please contact WattTime at SGIP@WattTime.org.
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.
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.
| username required | string (Username) Example: username=sgip_user name of user that will be used in subsequent calls |
| password required | string (Password) Example: password=i_love_batteries 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) Example: email=sgip_user@my_cool_company.com valid email address |
Org (string) or Org (null) (Org) Example: org=My Cool Company organization name |
# To register, use the code below. Please note that for these code examples we are using filler values for username # (sgip_user), password (i_love_batteries), email (sgip_user@my_cool_company.com), org (My Cool Company) and you should replace each if you are # copying and pasting this code. import requests register_url = 'https://sgipsignal.com/register' params = {'username': 'sgip_user', 'password': 'i_love_batteries', 'email': 'sgip_user@my_cool_company.com', 'org': 'My Cool Company'} rsp = requests.post(register_url, json=params) print(rsp.text)
{- "ok": "User created",
- "user": "sgip_user"
}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.
# To login and obtain an access token, use this code: import requests from requests.auth import HTTPBasicAuth login_url = 'https://sgipsignal.com/login' rsp = requests.get(login_url, auth=HTTPBasicAuth('sgip_user', 'i_love_batteries')) TOKEN = rsp.json()['token'] print(rsp.json())
{- "token": "abcdef0123456789fedcabc"
}Provide your username to request an email be sent to you with password reset instructions.
| username required | string (Username) Example: username=sgip_user name of user that will be used in subsequent calls |
# To reset your password, use this code: import requests password_url = 'https://sgipsignal.com/password/?username=sgip_user' rsp = requests.get(password_url) print(rsp.json())
{- "ok": "Please check your email for the password reset link"
}Data is available for the following grid regions in California. To identify which grid region a project is located in, please refer to the table on the Grid Regions page, which indicates the grid region of each electric utility in California.
| Region | Abbreviation |
|---|---|
| CAISO San Diego Gas & Electric DLAP | SGIP_CAISO_SDGE |
| CAISO San CAISO Pacific Gas & Electric DLAP | SGIP_CAISO_PGE |
| CAISO San CAISO Southern California Edison DLAP | SGIP_CAISO_SCE |
| CAISO San Los Angeles Department of Water & Power | SGIP_LADWP |
| CAISO San BANC Sacramento Municipal Utility District | SGIP_BANC_SMUD |
| CAISO San Balancing Authority of Northern California | SGIP_BANC_P2 |
| CAISO San Imperial Irrigation District | SGIP_IID |
| CAISO San PacifiCorp West | SGIP_PACW |
| CAISO San NV Energy | SGIP_NVENERGY |
| CAISO San Turlock Irrigation District | SGIP_TID |
| CAISO San Western Area Lower Colorado | SGIP_WALC |
Multiple versions of marginal emissions data exist that reflect changes to the Avoided Cost Calculator. Each version is valid for a specific period and each version of the model is available historically through the API. Both marginal emissions and forecasts are available historically outside the validity window for training purposes.
| MOER version | Forecast version | Valid Dates |
|---|---|---|
| '1.0' | '1.0-1.0.0' | April 1, 2020 to December 31, 2021 |
| '2.0' | '2.0-1.0.0' | Starting January 1, 2022 |
Obtain real-time or historical marginal GHG emissions rates. Units are in kg CO2 per kWh. Each point_time is valid from its point_time for the following 5 minutes.
To obtain the latest marginal emissions rate (MOER) available, simply omit the starttime and endtime parameters. Note that MOERs are usually available two to three minutes before the timestamp for which they are valid. For example, the MOER valid from 12:00 to 12:05 will typically become available through the API around 11:58 and will be published no later than 12:00. The availability of the next MOER datapoint is dependent on when CAISO market data becomes available and as such is somewhat variable.
Historical queries are limited to a maximum time span of 31 days - so if you want to query more data than that, please break up your request into multiple queries.
Different versions of the MOER model can be accessed by specifying a version number.
| ba required | string (Ba) Example: ba=SGIP_CAISO_PGE Region abbreviation. |
Starttime (string) or Starttime (string) or Starttime (null) (Starttime) Example: starttime=2018-02-20T16:45:30-0800 ISO 8601 timestamp (inclusive) - Omit to obtain the real-time MOER. If included, those MOER values generated between start and endtime are returned. | |
Endtime (string) or Endtime (string) or Endtime (null) (Endtime) Example: endtime=2018-02-24T16:45:30-0800 ISO 8601 timestamp (inclusive) - Omit to obtain the real-time MOER. If included, those MOER values generated between start and endtime are returned. | |
Version (string) or Version (null) (Version) Example: version=3.2 MOER model version number. May be omitted to receive most current model. |
import requests headers = { 'Authorization': 'Bearer <Access_Token>' } request = requests.get('https://sgipsignal.com/sgipmoer/?ba=SGIP_CAISO_PGE&starttime=2018-02-20T16:45:30-0800&endtime=2018-02-24T16:45:30-0800', headers=headers) response_body = request.json() print(response_body)
[- {
- "ba": "SGIP_CAISO_PGE",
- "freq": 300,
- "moer": 0.223,
- "point_time": "2019-01-29T14:55:00.000Z",
- "version": "1.0"
}
]Obtain MOER forecast data for a given region. Omitting the starttime and endtime parameters will return the entire real-time 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 72 hours in duration. So, if you make a request to the forecast endpoint with starttime of Jan 1, 1:00 and endtime Jan 1, 1:05, you will receive the 72-hour forecast generated at 1:00, and the 72-hour forecast generated at 1:05 on January 1.
This forecast endpoint includes the 5-minute, 15-minute, hour, day, and 3-day forecast in a single endpoint.
Historical forecast queries are limited to a maximum time span of 1 day - so if you want to query more data than that, please break up your request into multiple queries. A year of historical forecast data is available for the CAISO grid regions.
Different versions of the forecast can be accessed by specifying a version number.
| ba required | string (Ba) Example: ba=SGIP_CAISO_PGE Region abbreviation. |
Starttime (string) or Starttime (string) or Starttime (null) (Starttime) Example: starttime=2018-02-20T16:45:30-0800 ISO 8601 timestamp (inclusive) - Omit to obtain the real-time forecast. If included, those forecasts generated between start and endtime are returned. | |
Endtime (string) or Endtime (string) or Endtime (null) (Endtime) Example: endtime=2018-02-24T16:45:30-0800 ISO 8601 timestamp (inclusive) - Omit to obtain the real-time forecast. If included, those forecasts generated between start and endtime are returned. | |
Version (string) or Version (null) (Version) Example: version=3.2-1.0.0 Forecast model version number. May be omitted to receive most current model. |
import requests headers = { 'Authorization': 'Bearer <Access_Token>' } request = requests.get('https://sgipsignal.com/sgipforecast/?ba=SGIP_CAISO_PGE', headers=headers) response_body = request.json() print(response_body)
{- "forecast": [
- {
- "ba": "SGIP_CAISO_PGE",
- "point_time": "2019-01-29T14:55:00.000Z",
- "value": 675,
- "version": "1.0"
}
], - "generated_at": "2020-01-29T15:00:00.000Z"
}Obtain a long-term MOER forecast given region. This endpoint can return one of two forecasts; one with a one year horizon and monthly frequency, and another with a one month horizon and daily frequency. You can specify which forecast you would like through the 'horizon' query parameter. These forecasts are NOT an estimate of realtime moer but are estimate of the 15 percentile and 85th percentile MOER values over a span of time (one month for year long forecasts and 1 day for month long forecasts). The 15th and 85th percentiles of MOER values are given for time of day periods described as 'morning', 'day', 'evening', and 'night'.
So for example, if you request the 'month' horizon forecast, the returned data will provide a prediction of the 15th and 85th percentile MOER values for every 'morning' period (exact hours given below), 'day', 'evening' and 'night' of every day for the next month.
The intent of this endpoint is to help provide some insight into how much carbon savings may be possible on a given day or time period.
Month long forecasts are generated once daily and year long forecasts are generated once per month.
You can retrieve historical forecasts by providing starttime and endtime parameters, which requests all forecasts GENERATED between these times.
The time periods corresponding to 'morning', 'day', 'evening', and 'night' are given as follows (all times in Pacific Standard Time, regardless of time of year). Of note, the 'night' period corresponds to the night starting on the date associated with point_time and running into the next day.
| name | time span |
|---|---|
| morning | 06:00-11:55 PST |
| day | 12:00-15:55 PST |
| evening | 16:00-20:55 PST |
| night | 21:00-5:55 PST |
| ba required | string (Ba) Example: ba=SGIP_CAISO_PGE Region abbreviation. |
| horizon required | string (Horizon) Enum: "year" "month" Example: horizon=year Duration of forecast - can be 'year' or 'month'. There is a span of 1 day between forecast points for the 'month' forecast and a span of 1 month between forecast points for the 'year' forecast. |
Starttime (string) or Starttime (string) or Starttime (null) (Starttime) Example: starttime=2018-02-20T16:45:30-0800 ISO 8601 timestamp (inclusive) - Omit to obtain the real-time forecast. If included, those forecasts generated between start and endtime are returned. | |
Endtime (string) or Endtime (string) or Endtime (null) (Endtime) Example: endtime=2018-02-24T16:45:30-0800 ISO 8601 timestamp (inclusive) - Omit to obtain the real-time forecast. If included, those forecasts generated between start and endtime are returned. |
import requests headers = { 'Authorization': 'Bearer <Access_Token>' } request = requests.get('https://sgipsignal.com/sgiplongforecast/?ba=SGIP_CAISO_PGE', headers=headers) response_body = request.json() print(response_body)
{- "forecast": [
- {
- "15th_percentile": 0.0314292766712486,
- "85th_percentile": 0.13398822875862013,
- "ba": "SGIP_CAISO_SCE",
- "point_time": "2020-03-20T00:00:00+00:00",
- "time_of_day": "day",
- "version": "1.0-0.0.1"
}
], - "generated_at": "2020-01-29T15:00:00.000Z"
}For questions related to this API and real-time emissions data, please contact SGIP@WattTime.org.