# Request a sandbox-only agent credential
Source: https://docs.wattshift.com/api-reference/agent-credentials/request-a-sandbox-only-agent-credential
/api-reference/openapi.json post /v1/agent-credentials
# Revoke a sandbox agent credential
Source: https://docs.wattshift.com/api-reference/agent-credentials/revoke-a-sandbox-agent-credential
/api-reference/openapi.json post /v1/agent-credentials/{credentialId}/revoke
# calculate period bill impact from inline context
Source: https://docs.wattshift.com/api-reference/calculate/calculate-period-bill-impact-from-inline-context
/api-reference/openapi.json post /v1/calculate/impact
Calculates period bill impact using rate plan, zipcode, and optional carbon settings supplied in the request body. Does not require a persisted home. Inline usage is required when useDefaultUsage is false or omitted; set useDefaultUsage to true to derive usage from Palmetto baseline data instead of supplying inline usage arrays.
# calculate period bill using a specific rate plan
Source: https://docs.wattshift.com/api-reference/calculate/calculate-period-bill-using-a-specific-rate-plan
/api-reference/openapi.json post /v1/calculate/impact/rateplan/{ratePlanId}
Bill calculation for a MongoDB rate plan id only (no home). Carbon and grid revenue are omitted without a home zipcode.
# Request a sandbox-only agent credential
Source: https://docs.wattshift.com/api-reference/endpoint/agent-credentials/request-a-sandbox-only-agent-credential
api-reference/openapi.json POST /v1/agent-credentials
# Revoke a sandbox agent credential
Source: https://docs.wattshift.com/api-reference/endpoint/agent-credentials/revoke-a-sandbox-agent-credential
api-reference/openapi.json POST /v1/agent-credentials/{credentialId}/revoke
# calculate period bill impact from inline context
Source: https://docs.wattshift.com/api-reference/endpoint/calculate/calculate-period-bill-impact-from-inline-context
api-reference/openapi.json POST /v1/calculate/impact
Calculates period bill impact using rate plan, zipcode, and optional carbon settings supplied in the request body. Does not require a persisted home. Inline usage is required when useDefaultUsage is false or omitted; set useDefaultUsage to true to derive usage from Palmetto baseline data instead of supplying inline usage arrays.
# calculate period bill using a specific rate plan
Source: https://docs.wattshift.com/api-reference/endpoint/calculate/calculate-period-bill-using-a-specific-rate-plan
api-reference/openapi.json POST /v1/calculate/impact/rateplan/{ratePlanId}
Bill calculation for a MongoDB rate plan id only (no home). Carbon and grid revenue are omitted without a home zipcode.
# Submit structured feedback or a question
Source: https://docs.wattshift.com/api-reference/endpoint/feedback/submit-structured-feedback-or-a-question
api-reference/openapi.json POST /v1/feedback
# [Beta] Get bill upload processing status
Source: https://docs.wattshift.com/api-reference/endpoint/homes/beta-get-bill-upload-processing-status
api-reference/openapi.json POST /v1/homes/bill-upload/{id}/status
# [Beta] Onboard a site by uploading utility bill PDFs
Source: https://docs.wattshift.com/api-reference/endpoint/homes/beta-onboard-a-site-by-uploading-utility-bill-pdfs
api-reference/openapi.json POST /v1/homes/bill-upload
# calculate monthly bill impact
Source: https://docs.wattshift.com/api-reference/endpoint/homes/calculate-monthly-bill-impact
api-reference/openapi.json POST /v1/homes/{id}/bill/monthly
Calculates monthly bill cost and includes grid-services revenue and carbon impact when home context and signal data are available.
# calculate period bill impact
Source: https://docs.wattshift.com/api-reference/endpoint/homes/calculate-period-bill-impact
api-reference/openapi.json POST /v1/homes/{id}/bill/period
Calculates bill cost for a custom date range and includes optional grid-services revenue and carbon impact when home context and signal data are available.
# calculate period bill impact
Source: https://docs.wattshift.com/api-reference/endpoint/homes/calculate-period-bill-impact-1
api-reference/openapi.json POST /v1/homes/{id}/calculate/impact
Calculates bill cost for a custom date range and includes optional grid-services revenue and carbon impact when home context and signal data are available.
# calculate period bill using a specific rate plan
Source: https://docs.wattshift.com/api-reference/endpoint/homes/calculate-period-bill-using-a-specific-rate-plan
api-reference/openapi.json POST /v1/homes/bill/period/rateplan/{ratePlanId}
Bill calculation for a MongoDB rate plan id only (no home). Carbon and grid revenue are omitted without a home zipcode.
# calculate period bill with inline home context
Source: https://docs.wattshift.com/api-reference/endpoint/homes/calculate-period-bill-with-inline-home-context
api-reference/openapi.json POST /v1/homes/bill/period
Calculates period bill impact using inline home context instead of a persisted home id.
# create home
Source: https://docs.wattshift.com/api-reference/endpoint/homes/create-home
api-reference/openapi.json POST /v1/homes/create
# create solar
Source: https://docs.wattshift.com/api-reference/endpoint/homes/create-solar
api-reference/openapi.json POST /v1/homes/solar/create
# find home
Source: https://docs.wattshift.com/api-reference/endpoint/homes/find-home
api-reference/openapi.json POST /v1/homes/{id}/get
# get battery estimated savings
Source: https://docs.wattshift.com/api-reference/endpoint/homes/get-battery-estimated-savings
api-reference/openapi.json POST /v1/homes/{id}/battery/estimate_savings
Estimates annual solar+battery savings for a home. Month inputs use calendar month numbers 1-12.
# get HVAC estimated savings (monthly or annual)
Source: https://docs.wattshift.com/api-reference/endpoint/homes/get-hvac-estimated-savings-monthly-or-annual
api-reference/openapi.json POST /v1/homes/{id}/hvac/estimate_savings
# get price signal
Source: https://docs.wattshift.com/api-reference/endpoint/homes/get-price-signal
api-reference/openapi.json POST /v1/homes/{id}/price_signal
Returns a home-context price signal. Omit the body for the default home window, or provide both ISO 8601 startTime and endTime.
# get price signal open adr
Source: https://docs.wattshift.com/api-reference/endpoint/homes/get-price-signal-open-adr
api-reference/openapi.json POST /v1/homes/{id}/price_signal/open_adr
# list home hvac devices
Source: https://docs.wattshift.com/api-reference/endpoint/homes/list-home-hvac-devices
api-reference/openapi.json POST /v1/homes/{id}/devices/hvac/list
# list homes
Source: https://docs.wattshift.com/api-reference/endpoint/homes/list-homes
api-reference/openapi.json POST /v1/homes/list
# remove home
Source: https://docs.wattshift.com/api-reference/endpoint/homes/remove-home
api-reference/openapi.json POST /v1/homes/{id}/remove
Removes a sandbox/test home owned by the API credential. Uses the same homes:write scope as createHome.
# update home
Source: https://docs.wattshift.com/api-reference/endpoint/homes/update-home
api-reference/openapi.json POST /v1/homes/{id}/update
# find HVAC
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/find-hvac
api-reference/openapi.json POST /v1/devices/hvac/{id}/get
# get set point schedule
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/get-set-point-schedule
api-reference/openapi.json POST /v1/devices/hvac/{id}/set_point_schedule/get
# get user preference
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/get-user-preference
api-reference/openapi.json POST /v1/devices/hvac/{id}/user_preferences/get
# preview
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/preview
api-reference/openapi.json POST /v1/devices/hvac/{id}/preview
# record thermostat behavior
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/record-thermostat-behavior
api-reference/openapi.json POST /v1/devices/hvac/{id}/thermostat_behavior/record
# remove HVAC
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/remove-hvac
api-reference/openapi.json POST /v1/devices/hvac/{id}/remove
# remove HVAC
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/remove-hvac-1
api-reference/openapi.json POST /v1/devices/hvac/{id}/unlink
# set user preference
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/set-user-preference
api-reference/openapi.json POST /v1/devices/hvac/{id}/user_preferences/set
# set webhook thermostat behavior
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/set-webhook-thermostat-behavior
api-reference/openapi.json POST /v1/devices/hvac/thermostat_behavior/webhook/set
# update HVAC
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/update-hvac
api-reference/openapi.json POST /v1/devices/hvac/{id}/linked
# url for today view
Source: https://docs.wattshift.com/api-reference/endpoint/hvac/url-for-today-view
api-reference/openapi.json POST /v1/devices/hvac/{id}/today-url/generate
# check eligibility for zipcode
Source: https://docs.wattshift.com/api-reference/endpoint/onboarding/check-eligibility-for-zipcode
api-reference/openapi.json POST /v1/onboarding/eligibility/check
# generate onboarding url
Source: https://docs.wattshift.com/api-reference/endpoint/onboarding/generate-onboarding-url
api-reference/openapi.json POST /v1/onboarding/url/generate
# generate session token
Source: https://docs.wattshift.com/api-reference/endpoint/onboarding/generate-session-token
api-reference/openapi.json POST /v1/onboarding/session-token/generate
# get onboarding status
Source: https://docs.wattshift.com/api-reference/endpoint/onboarding/get-onboarding-status
api-reference/openapi.json POST /v1/onboarding/status/get
# list utilities
Source: https://docs.wattshift.com/api-reference/endpoint/utility/list-utilities
api-reference/openapi.json POST /v1/utility/get
Discover utilities and rate plans without creating a home. A request requires utilityId, zipcode, or both lat and long. Pass utilityId (EIA utility ID) when you already know the utility; use zipcode or lat/long to discover utilities for a location. Response utilityId is that same EIA ID. Send ratePlans[].id as ratePlanId; ratePlans[].udId repeats that WattShift plan ID, while ratePlans[].rateID is the semantic tariff reference (not an EIA ID).
Pass `utilityId` (EIA utility ID) when you already know the utility; use `zipcode` (or lat/long) to discover utilities for a location. The response `utilityId` is that same EIA ID. It is not a rate plan id — send `ratePlans[].id` as `ratePlanId`, `ratePlans[].udId` repeats that WattShift plan ID, and `ratePlans[].rateID` is the semantic tariff reference.
## Lookup by utility EIA ID
When you already know the utility's EIA ID (for example, `14328` for PG\&E), request rate plans directly:
```json theme={null}
{
"utilityId": "14328",
"detailLevel": "minimal"
}
```
# Set or update the price signal webhook for the organization
Source: https://docs.wattshift.com/api-reference/endpoint/webhook/set-or-update-the-price-signal-webhook-for-the-organization
api-reference/openapi.json POST /v1/webhook/price_signal/set
Each organization may have at most one price signal webhook. If one already exists, this endpoint updates it.
# set webhook for optimized HVAC set-point schedules
Source: https://docs.wattshift.com/api-reference/endpoint/webhook/set-webhook-for-optimized-hvac-set-point-schedules
api-reference/openapi.json POST /v1/webhook/set_point_schedule/set
# trigger price signal webhook for organization homes
Source: https://docs.wattshift.com/api-reference/endpoint/webhook/trigger-price-signal-webhook-for-organization-homes
api-reference/openapi.json POST /v1/webhook/price_signal/trigger
# trigger set-point schedule webhook
Source: https://docs.wattshift.com/api-reference/endpoint/webhook/trigger-set-point-schedule-webhook
api-reference/openapi.json POST /v1/webhook/set_point_schedule/trigger
# Submit structured feedback or a question
Source: https://docs.wattshift.com/api-reference/feedback/submit-structured-feedback-or-a-question
/api-reference/openapi.json post /v1/feedback
# [Beta] Get bill upload processing status
Source: https://docs.wattshift.com/api-reference/homes/[beta]-get-bill-upload-processing-status
/api-reference/openapi.json post /v1/homes/bill-upload/{id}/status
# [Beta] Onboard a site by uploading utility bill PDFs
Source: https://docs.wattshift.com/api-reference/homes/[beta]-onboard-a-site-by-uploading-utility-bill-pdfs
/api-reference/openapi.json post /v1/homes/bill-upload
# calculate monthly bill impact
Source: https://docs.wattshift.com/api-reference/homes/calculate-monthly-bill-impact
/api-reference/openapi.json post /v1/homes/{id}/bill/monthly
Calculates monthly bill cost and includes grid-services revenue and carbon impact when home context and signal data are available.
# calculate period bill impact
Source: https://docs.wattshift.com/api-reference/homes/calculate-period-bill-impact
/api-reference/openapi.json post /v1/homes/{id}/bill/period
Calculates bill cost for a custom date range and includes optional grid-services revenue and carbon impact when home context and signal data are available.
# calculate period bill impact
Source: https://docs.wattshift.com/api-reference/homes/calculate-period-bill-impact-1
/api-reference/openapi.json post /v1/homes/{id}/calculate/impact
Calculates bill cost for a custom date range and includes optional grid-services revenue and carbon impact when home context and signal data are available.
# calculate period bill using a specific rate plan
Source: https://docs.wattshift.com/api-reference/homes/calculate-period-bill-using-a-specific-rate-plan
/api-reference/openapi.json post /v1/homes/bill/period/rateplan/{ratePlanId}
Bill calculation for a MongoDB rate plan id only (no home). Carbon and grid revenue are omitted without a home zipcode.
# calculate period bill with inline home context
Source: https://docs.wattshift.com/api-reference/homes/calculate-period-bill-with-inline-home-context
/api-reference/openapi.json post /v1/homes/bill/period
Calculates period bill impact using inline home context instead of a persisted home id.
# create home
Source: https://docs.wattshift.com/api-reference/homes/create-home
/api-reference/openapi.json post /v1/homes/create
# create solar
Source: https://docs.wattshift.com/api-reference/homes/create-solar
/api-reference/openapi.json post /v1/homes/solar/create
# find home
Source: https://docs.wattshift.com/api-reference/homes/find-home
/api-reference/openapi.json post /v1/homes/{id}/get
# get battery estimated savings
Source: https://docs.wattshift.com/api-reference/homes/get-battery-estimated-savings
/api-reference/openapi.json post /v1/homes/{id}/battery/estimate_savings
Estimates annual solar+battery savings for a home. Month inputs use calendar month numbers 1-12.
# get HVAC estimated savings (monthly or annual)
Source: https://docs.wattshift.com/api-reference/homes/get-hvac-estimated-savings-monthly-or-annual
/api-reference/openapi.json post /v1/homes/{id}/hvac/estimate_savings
# get price signal
Source: https://docs.wattshift.com/api-reference/homes/get-price-signal
/api-reference/openapi.json post /v1/homes/{id}/price_signal
Returns a home-context price signal. Omit the body for the default home window, or provide both ISO 8601 startTime and endTime.
# get price signal open adr
Source: https://docs.wattshift.com/api-reference/homes/get-price-signal-open-adr
/api-reference/openapi.json post /v1/homes/{id}/price_signal/open_adr
# list home hvac devices
Source: https://docs.wattshift.com/api-reference/homes/list-home-hvac-devices
/api-reference/openapi.json post /v1/homes/{id}/devices/hvac/list
# list homes
Source: https://docs.wattshift.com/api-reference/homes/list-homes
/api-reference/openapi.json post /v1/homes/list
# remove home
Source: https://docs.wattshift.com/api-reference/homes/remove-home
/api-reference/openapi.json post /v1/homes/{id}/remove
Removes a sandbox/test home owned by the API credential. Uses the same homes:write scope as createHome.
# update home
Source: https://docs.wattshift.com/api-reference/homes/update-home
/api-reference/openapi.json post /v1/homes/{id}/update
# find HVAC
Source: https://docs.wattshift.com/api-reference/hvac/find-hvac
/api-reference/openapi.json post /v1/devices/hvac/{id}/get
# get set point schedule
Source: https://docs.wattshift.com/api-reference/hvac/get-set-point-schedule
/api-reference/openapi.json post /v1/devices/hvac/{id}/set_point_schedule/get
# get user preference
Source: https://docs.wattshift.com/api-reference/hvac/get-user-preference
/api-reference/openapi.json post /v1/devices/hvac/{id}/user_preferences/get
# preview
Source: https://docs.wattshift.com/api-reference/hvac/preview
/api-reference/openapi.json post /v1/devices/hvac/{id}/preview
# record thermostat behavior
Source: https://docs.wattshift.com/api-reference/hvac/record-thermostat-behavior
/api-reference/openapi.json post /v1/devices/hvac/{id}/thermostat_behavior/record
# remove HVAC
Source: https://docs.wattshift.com/api-reference/hvac/remove-hvac
/api-reference/openapi.json post /v1/devices/hvac/{id}/remove
# remove HVAC
Source: https://docs.wattshift.com/api-reference/hvac/remove-hvac-1
/api-reference/openapi.json post /v1/devices/hvac/{id}/unlink
# set user preference
Source: https://docs.wattshift.com/api-reference/hvac/set-user-preference
/api-reference/openapi.json post /v1/devices/hvac/{id}/user_preferences/set
# set webhook thermostat behavior
Source: https://docs.wattshift.com/api-reference/hvac/set-webhook-thermostat-behavior
/api-reference/openapi.json post /v1/devices/hvac/thermostat_behavior/webhook/set
# update HVAC
Source: https://docs.wattshift.com/api-reference/hvac/update-hvac
/api-reference/openapi.json post /v1/devices/hvac/{id}/linked
# url for today view
Source: https://docs.wattshift.com/api-reference/hvac/url-for-today-view
/api-reference/openapi.json post /v1/devices/hvac/{id}/today-url/generate
# Introduction
Source: https://docs.wattshift.com/api-reference/introduction
API Reference for WattShift
All our endpoints use `POST` method and the request and response are in JSON
format.
## Welcome
If you haven't already, visit our Quick Start guide to get started with WattShift API.
Get Started with WattShift API
## Authentication
All API endpoints are authenticated using an API key.
Follow the [Get API Key](/docs/get_started/get-api-keys) guide to obtain keys for sandbox and production environments.
# check eligibility for zipcode
Source: https://docs.wattshift.com/api-reference/onboarding/check-eligibility-for-zipcode
/api-reference/openapi.json post /v1/onboarding/eligibility/check
# generate onboarding url
Source: https://docs.wattshift.com/api-reference/onboarding/generate-onboarding-url
/api-reference/openapi.json post /v1/onboarding/url/generate
# generate session token
Source: https://docs.wattshift.com/api-reference/onboarding/generate-session-token
/api-reference/openapi.json post /v1/onboarding/session-token/generate
# get onboarding status
Source: https://docs.wattshift.com/api-reference/onboarding/get-onboarding-status
/api-reference/openapi.json post /v1/onboarding/status/get
# list utilities
Source: https://docs.wattshift.com/api-reference/utility/list-utilities
/api-reference/openapi.json post /v1/utility/get
Discover utilities and rate plans without creating a home. A request requires utilityId, zipcode, or both lat and long. Pass utilityId (EIA utility ID) when you already know the utility; use zipcode or lat/long to discover utilities for a location. Response utilityId is that same EIA ID. Send ratePlans[].id as ratePlanId; ratePlans[].udId repeats that WattShift plan ID, while ratePlans[].rateID is the semantic tariff reference (not an EIA ID).
# Set or update the price signal webhook for the organization
Source: https://docs.wattshift.com/api-reference/webhook/set-or-update-the-price-signal-webhook-for-the-organization
/api-reference/openapi.json post /v1/webhook/price_signal/set
Each organization may have at most one price signal webhook. If one already exists, this endpoint updates it.
# set webhook for optimized HVAC set-point schedules
Source: https://docs.wattshift.com/api-reference/webhook/set-webhook-for-optimized-hvac-set-point-schedules
/api-reference/openapi.json post /v1/webhook/set_point_schedule/set
# trigger price signal webhook for organization homes
Source: https://docs.wattshift.com/api-reference/webhook/trigger-price-signal-webhook-for-organization-homes
/api-reference/openapi.json post /v1/webhook/price_signal/trigger
# trigger set-point schedule webhook
Source: https://docs.wattshift.com/api-reference/webhook/trigger-set-point-schedule-webhook
/api-reference/openapi.json post /v1/webhook/set_point_schedule/trigger
# Querying Homes and Devices
Source: https://docs.wattshift.com/docs/advanced_options/query-homes
List homes and HVAC devices after onboarding so you can store home IDs and target device operations.
Check out our [onboarding guide](/docs/onboard_sites/prepare-onboarding) to
learn how to onboard users. The rest of this quick start guide will
walkthrough how to use the API once you have onboarded users.
The onboarding flow should provide a `homeId` for each user.
However, we also expose endpoints to list out all homes.
```typescript theme={null}
// Fetch all homes.
const homes = await wattshiftApiCall("/homes/list");
const home = homes[0];
```
It is recommended to store the `homeId` against the user
during the onboarding flow.
## Querying Devices
We can list out all the devices for a given home.
```typescript theme={null}
// Fetch devices for the home.
const homeId = home.id;
const devices = await wattshiftApiCall(`/homes/${homeId}/devices/hvac/list`);
const hvac = devices[0];
```
# Rate Plan ID Intro & Usage
Source: https://docs.wattshift.com/docs/advanced_options/rate-plan-Id-Intro&usage
How to find, use, and understand WattShift rate plan IDs
Rate Plan IDs help you select the correct tariff for a home and make sure price signals, savings estimates, and related calculations use the intended utility rate.
## How to Use Rate Plan IDs
1. Fetch available rate plans with `/v1/utility/get`.
2. Choose the plan that matches the home.
3. Use that plan's returned `ratePlans[].id` value as `ratePlanId` when creating or updating a home.
4. Reuse that same `ratePlanId` in API calls that ask for it.
Example:
```json theme={null}
{
"utilityId": "14328",
"utilityName": "Pacific Gas & Electric",
"ratePlans": [
{
"id": "6915de3f881cbc6041e4c887",
"rateID": "",
"ratePlanName": "TOU-D"
}
]
}
```
The `ratePlans[]` response includes:
* `id`: the rate plan ID to send as `ratePlanId`
* `rateID`: the semantic normalized tariff reference
* `ratePlanName`
* `supportedType`
Use the two ID fields like this:
* `ratePlans[].id`: the WattShift plan identifier you pass as `ratePlanId` to home endpoints.
* `ratePlans[].rateID`: the semantic normalized rate identifier you can use as a human-readable tariff reference.
### Typical Flow
1. Call `/v1/utility/get`.
2. Pick a plan from the returned `ratePlans` array.
3. Send that plan's `ratePlans[].id` value as `ratePlanId` to `/v1/homes/create` or `/v1/homes/{homeId}/update`.
4. Use the same home for price signals, impact calculations, and optimization workflows.
Example:
```json theme={null}
{
"name": "My Home",
"zipcode": "95313",
"utilityId": "14328",
"ratePlanId": "",
"solarSystemSizeKw": 5,
"isNonNetMetered": false
}
```
For solar homes, include both `solarSystemSizeKw` and `isNonNetMetered` on create or update. These fields create or update the home's solar info using WattShift's standard solar defaults.
## Understanding the Semantic Rate ID
WattShift's normalized rate data also includes a semantic rate ID that captures plan characteristics directly in the identifier. That format is useful when you want a deeper reference for plan structure, eligibility, climate region, or effective dates.
`POST /v1/utility/get` returns that semantic identifier separately as `ratePlans[].rateID`, while `ratePlans[].id` remains the value to send as `ratePlanId`.
The semantic RateID schema uses sector-specific formats. Residential plans use a long-form 13-segment structure, and non-residential sectors use an extended format. Both include four separate time/version fields:
* `effective_start`
* `vintage_year`
* `enrollment_close`
* `effective_end`
For API usage, you usually do not need to parse `rateID`. Use it as a structured reference for the normalized tariff, while continuing to send `ratePlans[].id` as `ratePlanId`.
Example:
```text theme={null}
USA-CA-14328-14328-R-TNNNNN-N????E-B4-01012025-????-????????-????????-BES
```
See [Rate Plan ID - Full Specification and Examples](/docs/advanced_options/rate-plan-Id-full-Spec\&Examples) for the sector-by-sector schema breakdown, including residential and non-residential `C` / `I` / `A` formats.
# Rate Plan ID - Full Specification and Examples
Source: https://docs.wattshift.com/docs/advanced_options/rate-plan-Id-full-Spec&Examples
Semantic rate ID schema used by normalized WattShift tariff data
This page documents the semantic rate ID schema used in WattShift’s normalized rate data.
If you are onboarding a home through the public API, the usual flow is still simple: choose a plan from `/v1/utility/get` and pass that returned `ratePlans[].id` as `ratePlanId`. This page is the deeper reference for understanding the semantic structure behind a normalized rate ID.
In `/v1/utility/get`:
* Use `ratePlans[].id` as `ratePlanId` in other API requests.
* Use `ratePlans[].rateID` when you want the semantic normalized tariff identifier described on this page.
## Rate ID Schema by Sector
Residential plans use this 13-segment format:
```text theme={null}
COUNTRY-STATE-DIST_UTILITY-ENERGY_PROVIDER-SECTOR-STRUCTURE_FLAGS-EQUIPMENT_FLAGS-CLIMATE-EFFECTIVE_START-VINTAGE_YEAR-ENROLLMENT_CLOSE-EFFECTIVE_END-NAME_CODE
```
Commercial (`C`), industrial (`I`), and agricultural (`A`) plans use this extended format:
```text theme={null}
COUNTRY-STATE-DIST_UTILITY-ENERGY_PROVIDER-SECTOR-STRUCTURE_FLAGS-PHASE-VOLTAGE_CLASS-DEMAND_MIN-DEMAND_MAX-DEMAND_UNIT-METERING-USAGE_MIN-USAGE_MAX-CLIMATE-EFFECTIVE_START-VINTAGE_YEAR-ENROLLMENT_CLOSE-EFFECTIVE_END-NAME_CODE
```
Example:
```text theme={null}
USA-CA-14328-14328-R-TNNNNN-N????E-B4-01012025-????-????????-????????-BES
```
## Residential Segment Breakdown
| Segment | Meaning | Notes |
| ------------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `COUNTRY` | ISO 3166-1 alpha-3 country code | Example: `USA`, `CAN` |
| `STATE` | ISO 3166-2 state or province code | Example: `CA`, `TX`, `ON` |
| `DIST_UTILITY` | Distribution utility identifier | Usually the 5-digit EIA utility ID |
| `ENERGY_PROVIDER` | Retail energy provider identifier | Bundled plans usually repeat the distribution utility ID; unknown can be `?????` |
| `SECTOR` | Customer sector | Usually the first letter of the sector, such as `R`, `C`, or `I` |
| `STRUCTURE_FLAGS` | 6-character plan-structure block | Encodes structure, demand, export, medical baseline, low-income, and demand-response signals |
| `EQUIPMENT_FLAGS` | 6-character applicability block | For residential plans, this block identifies solar/export participation, full-electric eligibility, electric water heating, electric space heating, EV eligibility, and dwelling type |
| `CLIMATE` | Climate or baseline region code | Two characters, such as `B4` |
| `EFFECTIVE_START` | Effective start date | `MMDDYYYY` or `????????` if unknown |
| `VINTAGE_YEAR` | Vintage year | Usually a 4-digit year or `????` |
| `ENROLLMENT_CLOSE` | Closed-to-new-customer date | `MMDDYYYY` or `????????` |
| `EFFECTIVE_END` | Effective end date | `MMDDYYYY` or `????????` |
| `NAME_CODE` | Sanitized plan code or short name | Often derived from the source plan name, plus differentiating suffixes |
## `STRUCTURE_FLAGS` Character Map
The `STRUCTURE_FLAGS` segment is six characters long:
```text theme={null}
[structure][demand][export][medical][low_income][demand_response]
```
| Position | Meaning | Current Values |
| -------- | ---------------- | ----------------------------------------------------------------------------------------------------------- |
| 1 | Structure | `T` = tiered/TOU structure present, `F` = flat, `?` = unknown |
| 2 | Demand | `T` = TOU/tiered demand, `F` = flat demand, `M` = mixed demand types, `N` = no demand charge, `?` = unknown |
| 3 | Export | `1` = NEM1, `2` = NEM2, `3` = NEM3/NBT, `N` = no export program |
| 4 | Medical baseline | `M` = enrolled, `N` = not enrolled |
| 5 | Low income | `L` = enrolled, `N` = not enrolled |
| 6 | Demand response | `Y` = enrolled, `N` = not enrolled, `?` = unknown |
## `EQUIPMENT_FLAGS` Character Map
For residential plans, the `EQUIPMENT_FLAGS` segment is a six-character applicability block:
```text theme={null}
[rooftop_solar][full_electric][electric_water_heating][electric_space_heating][ev][dwelling_type]
```
| Position | Meaning | Current Values |
| -------- | ------------------------------------ | --------------------------------------------------------------- |
| 1 | Rooftop solar / export participation | `R` = export-enabled / solar-enrolled, `N` = not export-enabled |
| 2 | Full electric | `R` = required, `D` = disqualifying, `?` = unknown |
| 3 | Electric water heating | `R` = required, `D` = disqualifying, `?` = unknown |
| 4 | Electric space heating | `R` = required, `D` = disqualifying, `?` = unknown |
| 5 | EV | `R` = required, `D` = disqualifying, `?` = unknown |
| 6 | Dwelling type | Usually first-character shorthand such as `S`, `M`, `E`, or `?` |
## Example Breakdown
For this example:
```text theme={null}
USA-CA-14328-14328-R-TNNNNN-N????E-B4-01012025-????-????????-????????-BES
```
* `USA-CA-14328-14328-R`: U.S. residential plan for utility `14328`
* `TNNNNN`: tiered/TOU-style structure, no demand charge, no export program, no medical baseline, no low-income flag, no demand-response flag
* `N????E`: no rooftop-solar/export requirement, unknown equipment flags, dwelling type `E`
* `B4`: climate or baseline region code
* `01012025`: effective start date of January 1, 2025
* `????`: unknown vintage year
* `????????`: unknown enrollment close date
* `????????`: unknown effective end date
* `BES`: sanitized name code
## Notes
* Date segments use UTC formatting in `MMDDYYYY`.
* Unknown date segments are intentionally serialized as `????????`.
* Related vintages of the same tariff often differ only in the date segments.
## Non-Residential Segment Breakdown
For commercial (`C`), industrial (`I`), and agricultural (`A`) plans, the residential `EQUIPMENT_FLAGS` block is replaced by dedicated eligibility segments that capture the main splitters used in non-residential tariffs.
In the non-residential shape:
* `R` keeps the residential format shown above.
* `C`, `I`, and `A` use the extended non-residential format.
* `NAME_CODE` remains tariff-family oriented and should not carry phase, voltage, demand, metering, or usage variants that already have dedicated segments.
| Segment | Meaning | Notes |
| ------------------ | -------------------------------------- | ---------------------------------------------------------------- |
| `PHASE` | Service phase eligibility | One-character normalized phase code |
| `VOLTAGE_CLASS` | Voltage eligibility class | One-character normalized voltage class |
| `DEMAND_MIN` | Minimum demand eligibility threshold | Five-character encoded threshold |
| `DEMAND_MAX` | Maximum demand eligibility threshold | Five-character encoded threshold |
| `DEMAND_UNIT` | Demand threshold unit | One-character unit code such as `K` for `kW` |
| `METERING` | Metering requirement | One-character metering requirement code |
| `USAGE_MIN` | Minimum usage eligibility threshold | Six-character encoded threshold with one shared usage-basis code |
| `USAGE_MAX` | Maximum usage eligibility threshold | Five-character encoded threshold |
| `CLIMATE` | Climate or baseline region code | Same role as in the current format |
| `EFFECTIVE_START` | Effective start date | Same role as in the current format |
| `VINTAGE_YEAR` | Vintage year | Same role as in the current format |
| `ENROLLMENT_CLOSE` | Closed-to-new-customer date | Same role as in the current format |
| `EFFECTIVE_END` | Effective end date | Same role as in the current format |
| `NAME_CODE` | Sanitized plan code or tariff short id | Same role as in the current format |
## Non-Residential Enums
### `PHASE`
| Code | Meaning |
| ---- | ---------------------- |
| `S` | `single_phase` |
| `T` | `three_phase` |
| `B` | `single_or_three` |
| `?` | unknown or unspecified |
### `VOLTAGE_CLASS`
| Code | Meaning |
| ---- | ---------------------- |
| `S` | `secondary` |
| `P` | `primary` |
| `U` | `subtransmission` |
| `T` | `transmission` |
| `O` | `other` |
| `?` | unknown or unspecified |
The RateID uses normalized voltage classes for stability. Exact legal voltage thresholds should remain available in the underlying tariff object.
### `DEMAND_UNIT`
| Code | Meaning |
| ---- | ---------------------- |
| `K` | `kW` |
| `A` | `kVA` |
| `R` | `kVAR` |
| `O` | `other` |
| `?` | unknown or unspecified |
### `METERING`
| Code | Meaning |
| ---- | -------------------------- |
| `N` | `none` |
| `S` | `single_meter` |
| `D` | `demand_metered` |
| `E` | `energy_only / non_demand` |
| `I` | `interval_or_idr` |
| `P` | `special` |
| `?` | unknown or unspecified |
The `METERING` field is meant to capture eligibility conditions such as demand-metered service, energy-only or non-demand service, single-meter service, or interval or IDR requirements.
## Threshold Encoding
`DEMAND_MIN`, `DEMAND_MAX`, and `USAGE_MAX` use this five-character format:
```text theme={null}
[exp][strictness][ddd]
```
`USAGE_MIN` uses this six-character format so the usage pair shares one basis code:
```text theme={null}
[basis][exp][strictness][ddd]
```
### Threshold Fields
* `exp`: power-of-10 exponent
* `strictness`: `I` for inclusive and `S` for strict
* `ddd`: three-digit mantissa
### Threshold Interpretation
* In a `MIN` field:
* `I` means `>=`
* `S` means `>`
* In a `MAX` field:
* `I` means `<=`
* `S` means `<`
Examples:
* `0S020` in `DEMAND_MIN` means `> 20`
* `1I100` in `DEMAND_MIN` means `>= 1,000`
* `2I250` in `DEMAND_MAX` means `<= 25,000`
Use the largest power of 10 that preserves an integer three-digit mantissa. The middle character is `I` or `S` depending on whether the tariff rule is inclusive or strict:
* `20` -> `0I020` or `0S020`
* `1,000` -> `1I100` or `1S100`
* `12,500` -> `2I125` or `2S125`
* `250,000` -> `3I250` or `3S250`
Unknown threshold fields use fixed-width unknown values:
* `DEMAND_MIN`, `DEMAND_MAX`, `USAGE_MAX` -> `?????`
* `USAGE_MIN` -> `??????`
## Usage Basis Codes
| Code | Meaning |
| ---- | -------------------------- |
| `M` | monthly / billing month |
| `Y` | annual |
| `R` | rolling or latest 12-month |
| `O` | other complex period |
| `?` | unknown or unspecified |
Examples:
* `M2S125` in `USAGE_MIN` means monthly `> 12,500 kWh`
* `R2I150` in `USAGE_MIN` means rolling-12-month `>= 15,000 kWh`
The RateID should preserve the normalized usage basis, while the exact legal timing rule remains in the tariff object.
## Non-Residential Examples
Example 1:
```text theme={null}
USA-CA-14328-14328-C-TNNNNN-S-P-0I020-1S100-K-D-M2S125-2I250-B4-01012026-2026-????????-????????-GS2
```
Meaning:
* commercial tariff
* single-phase service
* primary voltage class
* demand eligibility from `>= 20 kW` to `< 1,000 kW`
* demand-metered service
* monthly usage from `> 12,500 kWh` to `<= 25,000 kWh`
Example 2:
```text theme={null}
USA-WI-20856-20856-I-TM1NNN-B-S-3I250-?????-A-E-R2S150-?????-B4-01012025-2025-????????-????????-GENERAL
```
Meaning:
* industrial tariff
* single-phase or three-phase service
* secondary voltage class
* demand eligibility of `>= 250,000 kVA`
* no encoded maximum demand threshold
* energy-only or non-demand metering requirement
* rolling-12-month usage threshold of `> 15,000 kWh`
This non-residential structure is part of the documented semantic RateID schema for non-residential sectors. Residential plans continue to use the residential format documented earlier on this page.
# Authenticating API Calls
Source: https://docs.wattshift.com/docs/get_started/authentication
Authentication and Making API Calls
All our requests use `POST`. Here's a quick example of what an API client would look like.
```typescript theme={null}
const baseUrl = "https://api.wattshift.com/v1";
const options = {
method: "POST",
headers: {
"x-ws-api-key": "",
},
};
const wattshiftApiCall = async (
path: `/${string}`,
body?: Record,
) => {
const res = await fetch(`${baseUrl}${path}`, {
...options,
body: JSON.stringify(body ?? {}),
});
return res.json();
};
```
### Example API Call
```typescript theme={null}
await wattShiftApiCall(`/homes/${user.wsHomeId}/update`, {
name: "updated home name",
solarSystemSizeKw: 6.4,
isNonNetMetered: true,
});
```
# Environments
Source: https://docs.wattshift.com/docs/get_started/environments
Testing out WattShift on sandbox
WattShift supports a sandbox environment for testing and development purposes.
Here are the base URLs for each environment:
**Sandbox**:
`https://api-sandbox.wattshift.com/v1`
**Production**:
`https://api.wattshift.com/v1`
## Domain Map
Understanding the different domains in the WattShift ecosystem:
| Domain | Description |
| ------------------------------- | ------------------------------------------------------------------------------------------ |
| `api.wattshift.com` | **Production API**: The main API endpoint for production applications. |
| `api-sandbox.wattshift.com` | **Sandbox API**: The API endpoint for testing and development. |
| `partner.wattshift.com` | **Production Dashboard**: The web dashboard for managing your production account and keys. |
| `partner-sandbox.wattshift.com` | **Sandbox Dashboard**: The web dashboard for managing your sandbox account and keys. |
| `app.wattshift.com` | **User Onboarding App**: The user-facing application for the onboarding flow. |
# Get API Key
Source: https://docs.wattshift.com/docs/get_started/get-api-keys
How to obtain API keys for sandbox and production environments
To use the WattShift API, you'll need to obtain API keys for your chosen environment. Follow the instructions below based on whether you're using the sandbox or production environment.
## Sandbox Environment
For testing and development purposes, use the sandbox environment:
1. Navigate to [https://partner-sandbox.wattshift.com/](https://partner-sandbox.wattshift.com/)
2. Signup / Log in to your sandbox account
3. Click on the **Keys** menu in the navigation
4. Generate your sandbox API keys
Sandbox API keys are for testing purposes only and should not be used in
production applications.
## Production Environment
For production applications, use the production environment:
1. Navigate to [https://partner.wattshift.com/](https://partner.wattshift.com/)
2. Signup / Log in to your production account
3. Click on the **Keys** menu in the navigation
4. Generate your production API keys
Production API keys have access to real user data and should be kept secure.
Never commit API keys to version control or share them publicly.
## Using Your API Keys
Once you have your API keys, you can use them to authenticate your API calls as shown in the [authentication guide](/docs/get_started/authentication).
```typescript theme={null}
const options = {
method: "POST",
headers: {
"x-ws-api-key": "",
},
};
```
Make sure to use the correct base URL for your environment as described in the
[environments guide](/docs/get_started/environments).
# Quickstart Guide
Source: https://docs.wattshift.com/docs/get_started/quickstart
From Zero to Price Signal in 5 Minutes
Welcome to WattShift! This guide will walk you through the fastest way to get your first Price Signal using our API.
WattShift separates **discovery** from **evaluation**:
* **Discovery** — Find supported utilities and rate plans with [`POST /v1/utility/get`](/api-reference/endpoint/utility/list-utilities). No home is required.
* **Evaluation** — Retrieve normalized pricing and impact outputs. Use a Home as a lightweight evaluation context when a workflow needs persisted context; home-free impact routes are also available.
## Prerequisites
Before you begin, make sure you have your **API Key**.
If you haven't obtained one yet, follow the [Get API Key](/docs/get_started/get-api-keys) guide.
## Step 1: Onboard a Home
For this quickstart, we'll use the **API Based Onboarding** method to programmatically create a home. This is the fastest way to test the flow.
### 1.1 Find a Utility and Rate Plan
First, discover a valid utility and rate plan for a test zip code (e.g., `95313`). Pass `utilityId` (EIA utility ID) when you already know the utility; use `zipcode` (or lat/long) to discover utilities for a location.
```bash theme={null}
curl -X POST "https://api.wattshift.com/v1/utility/get" \
-H "x-ws-api-key: " \
-H "Content-Type: application/json" \
-d '{ "zipcode": "95313" }'
```
Or look up by EIA utility ID when you already know the utility (for example, `14328` for PG\&E):
```bash theme={null}
curl -X POST "https://api.wattshift.com/v1/utility/get" \
-H "x-ws-api-key: " \
-H "Content-Type: application/json" \
-d '{ "utilityId": "14328" }'
```
Copy the returned `utilityId` (the EIA utility ID; for example, `14328` for PG\&E) and choose one of the returned entries in `ratePlans`. Send that plan's `ratePlans[].id` value as `ratePlanId` in the next step. `ratePlans[].udId` repeats that WattShift plan ID; the companion `ratePlans[].rateID` field is the semantic normalized tariff reference — not an EIA ID and not the value to send as `ratePlanId`.
```json theme={null}
[
{
"utilityId": "14328",
"utilityName": "Pacific Gas & Electric",
"ratePlans": [
{
"id": "6915de3f881cbc6041e4c887",
"udId": "6915de3f881cbc6041e4c887",
"rateID": "",
"ratePlanName": "TOU-D"
}
]
}
]
```
### 1.2 Create the Home
Now, [create a home](/api-reference/endpoint/homes/create-home) using the IDs you just found.
```bash theme={null}
curl -X POST "https://api.wattshift.com/v1/homes/create" \
-H "x-ws-api-key: " \
-H "Content-Type: application/json" \
-d '{
"name": "My Test Home",
"zipcode": "95313",
"utilityId": "14328",
"ratePlanId": "",
"solarSystemSizeKw": 5,
"isNonNetMetered": false
}'
```
Omit `solarSystemSizeKw` and `isNonNetMetered` for non-solar homes. If you add solar later, send those same fields to `POST /v1/homes//update`.
**Response:**
```json theme={null}
{
"id": "ws_home_123456789"
}
```
Save the response `id`. This is the home ID, shown as `homeId` in the examples below.
## Step 2: Get Price Signal
Now that you have a home with a utility and rate plan, you can immediately generate a home-based price signal.
```bash theme={null}
curl -X POST "https://api.wattshift.com/v1/homes//price_signal" \
-H "x-ws-api-key: " \
-H "Content-Type: application/json" \
-d '{}'
```
**Response:**
You will receive a JSON object containing the price signal data for the current day, including 15-minute interval prices.
```json theme={null}
{
"prices": [
{
"start": "2023-10-27T00:00:00Z",
"price": 0.24
},
...
]
}
```
For more detail on time-window requests, see the [Price Signals guide](/docs/optimize_shifts_calculate_impacts/price_signal).
## Congratulations!
You've successfully onboarded a home and retrieved your first price signal.
## Next Steps
* **Explore Onboarding Options**: Learn about our [UI Based Onboarding](/docs/onboard_sites/onboarding) for a user-friendly experience.
* **Calculate Impacts**: Use the [Impact Calculations](/docs/optimize_shifts_calculate_impacts/impact_calculations) endpoint to estimate bill savings.
* **Automate with Webhooks**: Set up [Webhooks](/docs/optimize_shifts_calculate_impacts/receiving-updates) to receive price signals automatically.
₹
# Solar + Storage Proposal Sandbox
Source: https://docs.wattshift.com/docs/get_started/solar-storage-proposal-sandbox
Run a quote-stage solar and battery proposal flow with public sandbox APIs
Use this sandbox flow to evaluate proposal-stage solar and storage economics before creating production customer records. It uses public WattShift APIs, public sandbox credentials, and live utility/rate-plan discovery.
## Sandbox Scope Matrix
| Scope | Public sandbox grant | Unlocks | Notes |
| ------------------- | -------------------- | ---------------------------------------- | ------------------------------------------------------- |
| `utility:read` | Yes | `POST /v1/utility/get` | Look up utilities and rate plans. |
| `homes:read` | Yes | Home lookup and list routes | Requires a sandbox home. |
| `homes:write` | Yes | Create, update, and remove sandbox homes | Use only non-production test records. |
| `price_signal:read` | Yes | Home-backed price signals | Public price signals require home context. |
| `bill_impact:read` | Yes | Home-backed and no-home bill routes | The no-home route supports quote-stage rate-plan bills. |
| `battery:estimate` | Yes | Battery estimated savings | Estimate solar+battery savings for sandbox homes. |
| `feedback:write` | Yes | `POST /v1/feedback` | Send implementation feedback from tests. |
## 1. Request Sandbox Access
Create or sign in to a sandbox account from [Get API Key](/docs/get_started/get-api-keys), then create a sandbox key with the scopes needed for the flow. For an automated agent credential flow, request these scopes:
```json theme={null}
[
"utility:read",
"homes:read",
"homes:write",
"price_signal:read",
"bill_impact:read",
"battery:estimate",
"feedback:write"
]
```
If `battery:estimate` is granted, continue through the battery savings step after creating or selecting a sandbox home with the chosen rate plan.
## 2. Look Up Utility And Rate Plans
Use a ZIP code in the target service territory and ask for solar-aware ordering.
```bash theme={null}
curl -s https://api.wattshift.com/v1/utility/get \
-H "x-ws-api-key: " \
-H "content-type: application/json" \
-d '{
"zipcode": "95313",
"detailLevel": "minimal",
"isSolarPrioritizedOrder": true
}'
```
Choose the PG\&E E-ELEC or NBT plan from `ratePlans[]`.
* Use `ratePlans[].id` as `ratePlanId` in WattShift API paths and request bodies.
* Use `ratePlans[].rateID` as the semantic tariff reference for display and audit trails.
* Inspect `solarBillingProgram` and `exportCompensationRefs` to confirm export compensation coverage.
## 3. Calculate A Quote-Stage Bill
Use the no-home rate-plan period route when the proposal has a selected tariff but should not persist a home yet. Quote-stage requests must cover complete calendar months or complete calendar years: `startDate` must be the first day of a month, and `endDate` must be the first day of a later month.
```bash theme={null}
POST /v1/homes/bill/period/rateplan/{ratePlanId}
```
```bash theme={null}
curl -s "https://api.wattshift.com/v1/homes/bill/period/rateplan/" \
-H "x-ws-api-key: " \
-H "content-type: application/json" \
--data-binary @july-period-bill.json
```
`july-period-bill.json` must be strict JSON with one 96-value daily array for every day in July:
```jsonc theme={null}
{
"usage": [
[0.3125, 0.3125, 0.3125 /* 93 more 15-minute values */],
/* one daily array for every day in July */
],
"export": [
[0, 0, 0 /* 93 more 15-minute values */],
/* optional; same number of daily arrays as usage */
],
"startDate": "2026-07-01",
"endDate": "2026-08-01",
"debug": true,
}
```
Expected response fields:
```json theme={null}
{
"billTotal": 268.37,
"exportCompensationCredit": 0,
"startDate": "2026-07-01",
"endDate": "2026-08-01"
}
```
The exact `billTotal` depends on the selected live rate plan and interval profile. Treat the response shape as the stable contract and refresh fixture totals when updating sandbox docs.
## 4. Calculate Battery Savings
Battery estimated savings is home-backed:
```bash theme={null}
curl -s "https://api.wattshift.com/v1/homes//battery/estimate_savings" \
-H "x-ws-api-key: " \
-H "content-type: application/json" \
-d '{
"days": 1,
"solarCapacity": 7.2,
"maxCapacityKiloWattHours": 13.5,
"chargingPowerKiloWatts": 5,
"dischargingPowerKiloWatts": 5,
"chargingEfficiency": 0.95,
"dischargingEfficiency": 0.95,
"currentSOC": 0.5,
"minPreferredSOC": 0.2,
"maxPreferredSOC": 0.9,
"months": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}'
```
Use calendar month numbers for `months`, where `1` is January and `12` is December. The sandbox credential must include `battery:estimate` for this step.
# Integration Overview
Source: https://docs.wattshift.com/docs/home/integration-overview
Understand the three-stage WattShift integration flow: pre-onboarding context, user onboarding, and optimized energy shifts.
Integrating with WattShift requires three simple steps.
### 1) Pre-Onboarding Context
Providing previously collected information about the users' preferences, homes, and devices,
allows WattShift to provide a personalized onboarding experience.
### 2) User Onboarding Flow
The onboarding flow collects user information not provided during the pre-onboarding stage.
WattShift has a pre-built, portable onboarding flow that easily integrates into partner
companies' UI or can take in information by API.
### 3) Shift Watts!
Now WattShift will provide optimized device behavior schedules that generate
grid revenue, lower customer electric bills, and reduce partner companies' scope 3 emissions!
# Welcome!
Source: https://docs.wattshift.com/docs/home/welcome
Welcome to WattShift Documentation
## Development
WattShift provides a developer-friendly API to help you optimize
your device's energy consumption against electric grid incentive schemes.
Our API is designed to be easy to use and integrate into your existing systems.
Explore the capabilities of WattShift API
Get started with WattShift in minutes
Review all our API endpoints and their parameters
# API Based Onboarding
Source: https://docs.wattshift.com/docs/onboard_sites/api-based-onboarding
Onboard homes programmatically
## Authentication
Authentication can be done in two different ways. Session tokens
are useful for frontend calls, while API keys are useful for backend calls.
1. **API Key:**
Add your API key in the header `x-ws-api-key`\
-> `{ 'x-ws-api-key': '{apiKey}' }`
2. **Session Token:**
Add the token in the header `Authorization` as: `Bearer {sessionToken}`\
-> `{ 'Authorization': 'Bearer {sessionToken}' }`
### How to Get a Session Token
Use this endpoint to [get a session token](/api-reference/endpoint/onboarding/generate-session-token) (helpful for frontend calls):
`[POST] /v1/onboarding/session-token/generate`
```json theme={null}
// Response Body
{ "sessionToken": "your_session_token" }
```
***
***
## Onboarding Flow
WattShift separates **discovery** from **evaluation**:
* **Discovery** — [`POST /v1/utility/get`](/api-reference/endpoint/utility/list-utilities) returns supported utilities and rate plans. No home is required.
* **Evaluation** — Retrieve normalized pricing and impact outputs. This onboarding flow uses a Home as a lightweight evaluation context, not necessarily a real customer or installation; home-free impact routes are also available.
```mermaid theme={null}
sequenceDiagram
participant Backend as Your Backend
participant WattShift as WattShift API
Backend->>WattShift: POST /v1/utility/get (zipcode or utilityId)
WattShift-->>Backend: Returns utilities and ratePlans
Backend->>WattShift: POST /v1/homes/create (utilityId, ratePlans[].id as ratePlanId)
WattShift-->>Backend: Returns home ID
opt Solar System
Backend->>WattShift: POST /v1/homes/solar/create
WattShift-->>Backend: Returns success
end
```
## Steps to Onboard a Home
### 1. Fetch Utilities and Rate Plans
Fetch utilities and rate plans for a location, or look up plans for a known utility.
[`[POST] /v1/utility/get`](/api-reference/endpoint/utility/list-utilities)
Pass `utilityId` (EIA utility ID) when you already know the utility; use `zipcode` (or lat/long) to discover utilities for a location.
```tsx theme={null}
// Request (by zip code)
{ "zipcode": "95313" }
// Or lookup by EIA utility ID
{ "utilityId": "14328" }
// Response
[
{
"utilityId": "14328",
"utilityName": "Pacific Gas & Electric",
"ratePlans": [
{
"id": "6915de3f881cbc6041e4c887",
"udId": "6915de3f881cbc6041e4c887",
"rateID": "",
"ratePlanName": "TOU-D"
},
{
"id": "",
"udId": "",
"rateID": "",
"ratePlanName": "TOU-C"
},
{
"id": "",
"udId": "",
"rateID": "",
"ratePlanName": "E-6"
}
]
}
]
```
The response `utilityId` is the EIA utility ID. Choose the matching entry from `ratePlans`, then use that plan's `ratePlans[].id` value as `ratePlanId` when calling the home endpoints. `ratePlans[].udId` repeats that WattShift plan ID; the companion `ratePlans[].rateID` field is the semantic normalized tariff identifier for reference and troubleshooting — not an EIA ID and not the value to send as `ratePlanId`.
***
### 2. Create a Home
Create Home with basic details, connecting to the utility, and select a rate plan.
[`[POST] /v1/homes/create`](/api-reference/endpoint/homes/create-home)
```json theme={null}
// Request
{
"name": "Your Home Name",
"zipcode": "95313",
"utilityId": "14328",
"ratePlanId": "",
"solarSystemSizeKw": 5,
"isNonNetMetered": false
}
// Response
{ "id": "ws_home_123456789" }
```
The response field is named `id`; use that value as the `homeId` in later requests.
For solar homes, the recommended fields are `solarSystemSizeKw` and `isNonNetMetered`. When both are present, WattShift creates solar info using standard defaults for module type, array type, efficiency, azimuth, and tilt. If you need to supply the full solar model yourself, use the advanced `solarInfo` object in the API reference.
***
### 3. Add or Update Solar Later (if needed)
If the home already exists, send the same solar fields to Update Home.
[`[POST] /v1/homes/{homeId}/update`](/api-reference/endpoint/homes/update-home)
```json theme={null}
// Request
{
"solarSystemSizeKw": 6.4,
"isNonNetMetered": true
}
```
You can also continue to use the dedicated Create Solar endpoint.
[`[POST] /v1/homes/solar/create`](/api-reference/endpoint/homes/create-solar)
```json theme={null}
// Request
{
"homeId": "ws_home_123456789",
"solarSystemSizeKw": 5,
"isNonNetMetered": false
}
// Response
{ "homeId": "ws_home_123456789" }
```
### 4. Get Price Signal Data
See the [Price Signal](/docs/optimize_shifts_calculate_impacts/price_signal) documentation for more details.
# [Beta] Bill Upload Auto Onboarding
Source: https://docs.wattshift.com/docs/onboard_sites/bill_upload_auto_onboard
Onboard sites by uploading utility bills
The Bill Upload Auto Onboarding API endpoint simplifies the onboarding process by allowing you to upload utility bill PDFs instead of asking users to identify a rate plan themselves. This single API call replaces the need to call `utility/get`, `homes/create`, and `solar/create` separately.
## When to Use Bill Upload
The bill ingestion API is particularly useful if:
1. **You prefer to collect utility bill PDFs** instead of going through the utility and rate-plan lookup process
2. **You or your customer are having trouble determining which rate plan they are on**
3. **Our listed confidence level for that site's rate plan is less than you are comfortable with**
4. **We don't yet list the rate plan your customer is on**
## Rate Plan Database Updates
For any rate plan in the U.S. or Canada, if you upload a bill, we will ensure that rate plan is in our database and accurate. We often get this updated within an hour (but in no cases slower than 24 hours).
## API Endpoint
`[POST] /v1/homes/bill-upload`
## Request
```json theme={null}
{
"name": "Your Site Name",
"zipcode": "95313",
"customerClass": "residential", // residential | commercial | industrial
"billPDFs": [
"https://example.com/bill1.pdf",
"https://example.com/bill2.pdf"
],
"solarSystemSizeKw": 5,
"isNonNetMetered": false,
// Optional fields
"utilityEIAId": "14328",
"ratePlanId": "",
// Optional fields (residential)
"hasEvCharger": true, // boolean | null | undefined
"hasElectricHeater": false,
"hasSmartWaterHeater": null,
"hasElectricWaterHeater": true,
"hasAC": true,
"acType": "central", // central | window | split | other
// Optional fields (commercial & industrial)
"peakDemand": 250 // kW
}
```
### Request Fields
#### Required Fields
* **name**: The name of the site/home
* **zipcode**: The zip code of the site (5-digit; ZIP+4 like `53717-1125` is accepted and normalized)
* **customerClass**: The customer class - `residential`, `commercial`, or `industrial`
* **billPDFs**: Array of URLs pointing to the utility bill PDF(s). URLs must be `https://` and publicly reachable, each PDF 10MB or smaller, maximum 5 PDFs per request
#### Solar Fields
* **solarSystemSizeKw**: Size of the solar system in kilowatts
* **isNonNetMetered**: Boolean indicating if the solar system is non-net metered
#### Optional Fields
* **utilityEIAId**: The utility EIA ID (if known)
* **ratePlanId**: Optional. If you already called `/v1/utility/get`, choose the correct entry from `ratePlans` and pass that plan's `ratePlans[].id` value. The returned `ratePlans[].rateID` field is the semantic tariff reference; `ratePlans[].id` is the value to send here.
#### Residential Optional Fields
* **hasEvCharger**: Boolean indicating if the site has an EV charger
* **hasElectricHeater**: Boolean indicating if the site has an electric heater
* **hasSmartWaterHeater**: Boolean indicating if the site has a smart water heater
* **hasElectricWaterHeater**: Boolean indicating if the site has an electric water heater
* **hasAC**: Boolean indicating if the site has air conditioning
* **acType**: Type of AC system - `central`, `window`, `split`, or `other`
#### Commercial & Industrial Optional Fields
* **peakDemand**: Peak demand in kilowatts (kW)
## Response
```json theme={null}
{
"id": "ws_home_7bc31940df8a4615b2dc9e84f3a92c51",
"status": "processing" // processing | completed | failed
}
```
The response field `id` is the newly created home ID, shown as `homeId` in later requests. The status indicates whether the bill processing is complete. Once processing is complete, you can immediately start receiving [Price Signal data](/docs/optimize_shifts_calculate_impacts/price_signal).
## Checking Processing Status
Poll the status endpoint with the returned home ID:
`[POST] /v1/homes/bill-upload/{homeId}/status`
```json theme={null}
{
"id": "ws_home_7bc31940df8a4615b2dc9e84f3a92c51",
"status": "completed", // processing | completed | failed
"utilityId": "14328",
"ratePlanId": "",
"pendingReason": null,
"failureReason": null,
"warnings": ["BILL_PDF_DROPPED:https://example.com/bill2.pdf:FILE_TOO_LARGE"]
}
```
While the rate plan is still being identified (or being added to our database), `status` stays `processing` and `pendingReason` explains why (for example `RATE_PLAN_NOT_MATCHED` during the 24-hour resolution window) — a populated `pendingReason` is informational, not an error. `failed` is reserved for unrecoverable problems with the uploaded files (for example, a URL that does not return a readable PDF); `failureReason` is only non-null when `status` is `failed`. The optional `warnings` array lists non-fatal anomalies, such as individual PDFs that were skipped while the rest of the upload succeeded.
## Important Notes
**Privately Negotiated Rate Plans**: If the rate plan is privately negotiated (either PPA or with a retailer/ESCO in a deregulated context), we may need additional information to generate accurate tariff data. In such cases, our support team will reach out for clarification.
**Bill Processing Time**: While we typically process bills within an hour, it can take up to 24 hours in some cases. During this time, the site status will be `processing`. Once complete, the status will update to `completed` and you can begin using the site for price signals and optimizations.
## Comparison with Multi-Step Onboarding
This single API call replaces the traditional multi-step onboarding process:
| Traditional Process | Bill Upload Process |
| ------------------------------------------------------- | ----------------------------------------------- |
| 1. Call `utility/get` to fetch utilities and rate plans | Single API call with bill PDFs |
| 2. Call `homes/create` to create the home | |
| 3. Call `solar/create` (if applicable) | |
| 4. Wait for rate plan verification | Automatic rate plan extraction and verification |
The bill upload method is especially valuable when you want to streamline the user experience or when rate plan identification is challenging.
# UI-Based Onboarding Flow
Source: https://docs.wattshift.com/docs/onboard_sites/onboarding
Display our onboarding UI in your app
## Display Onboarding Flow
## Onboarding Flow
```mermaid theme={null}
sequenceDiagram
participant User
participant Frontend as Your Frontend
participant Backend as Your Backend
participant WattShift as WattShift API
User->>Frontend: Clicks "Connect Utility"
Frontend->>Backend: Request Onboarding URL
Backend->>WattShift: POST /onboarding/url/generate
WattShift-->>Backend: Returns URL
Backend-->>Frontend: Returns URL
Frontend->>User: Redirects to WattShift URL
User->>WattShift: Completes Onboarding
WattShift->>Backend: Redirects to redirectUrl
```
## Generating Onboarding URL
To onboard the user, you will need to redirect them to our onboarding flow.
The following endpoint will generate an onboarding URL for the user–
```typescript theme={null}
async function getWattshiftOnboardingUrl() {
const { url, homeId } = await wattshiftApiCall(
"https://api.wattshift.com/v1/onboarding/url/generate",
{
userId: "user_123",
redirectUrl: "https://yourbackend.com/redirecturi",
enableThirdPartyDevice: false, // set to false if you control your own devices.
hvacs: [
{
name: "Primary thermostat",
enabled: true,
defaultMode: "HEAT",
tempUnits: "F",
maxTemp: "75",
minTemp: "65",
defaultTemp: "70",
deviceType: "Hvac",
canHeat: true,
canCool: false,
targetTemp: 70,
currentTemp: 70,
},
],
},
);
return { url, homeId };
}
```
The URL's domain will always be `https://app.wattshift.com` but this endpoint
will provide a sessionToken that is temporary and tied to your API Key
The `userId` is the unique identifier of the user in your system,
which will be used to query the user's data once the onboarding flow is complete.
Your frontend should invoke the onboarding URL in a webview or a new tab.
```javascript theme={null}
const { url } = await getWattshiftOnboardingUrl();
const webview = document.createElement("webview");
webview.src = url;
document.body.appendChild(webview);
```
The user will be then be prompted to onboard onto WattShift and
we will redirect to your redirect URL once the onboarding flow is complete.
## Query Onboarding Status
You can query for the onboarding status with the following url
```bash theme={null}
curl -X POST "https://api.wattshift.com/v1/onboarding/status/get"
-d '{ "homeId": "ws_home_123456789" }'
-H "x-ws-api-key: your api key"
```
Now you need to ensure you are responding to optimized schedules sent out by WattShift!
# Onboarding Options
Source: https://docs.wattshift.com/docs/onboard_sites/prepare-onboarding
Generate Onboarding URL with User Context
## Introduction
Onboarding users onto WattShift is an important part of our optimization services.
Each user should be onboarded in order for us to account for rate plans, DER programs, and other relevant data.
## Onboarding Options
WattShift offers three ways to onboard users:
1. **API Based Onboarding**: Programmatically onboard homes using our API endpoints. See the [API Based Onboarding](/docs/onboard_sites/api-based-onboarding) guide for details.
2. **User-Interface Based Onboarding**: Redirect users to WattShift's onboarding flow where they complete the process through our user interface. See the [User-Interface Based Onboarding](/docs/onboard_sites/onboarding) guide for details.
3. **Bill UploadAuto Onboarding**: Automatically onboard homes by providing a utility bill to our API endpoint. See the [Auto Onboarding](/docs/onboard_sites/bill_upload_auto_onboard) guide for details.
# Estimate Savings
Source: https://docs.wattshift.com/docs/optimize_shifts_calculate_impacts/estimate-savings
Calculate potential savings for HVAC and Battery systems
WattShift's Estimate Savings endpoints enable you to calculate potential cost savings and optimization opportunities for HVAC systems and battery storage systems. These endpoints help you understand the financial impact of different optimization strategies before implementing them.
## Overview
The Estimate Savings feature provides two main capabilities:
1. **HVAC Estimate Savings**: Calculate potential savings from optimizing HVAC temperature setpoints and operation schedules
2. **Battery Estimate Savings**: Calculate potential savings from battery storage optimization, including wholesale market participation
Both endpoints support detailed analysis with hourly data for monthly calculations or annualized estimates for long-term planning.
In these guide examples, `{homeId}` is the home ID returned as `id` by onboarding. The API reference labels the same path parameter `{id}`.
## HVAC Estimate Savings
The HVAC Estimate Savings endpoint helps you understand how optimizing your HVAC system's temperature setpoints and operation can reduce energy costs.
### Request Parameters
**Required Fields:**
* `type`: Calculation type - `"monthly"` or `"annual"`
* `mode`: HVAC mode - `"AUTO"`, `"COOL"`, `"HEAT"`, or `"OFF"`
**Optional Configuration:**
* `targetTemp`: Target temperature in Fahrenheit (default: 72)
* `targetCoolSetpoint`: Cooling setpoint (default: targetTemp + 1)
* `targetHeatSetpoint`: Heating setpoint (default: targetTemp - 1)
* `minTemp`: Minimum allowed temperature (default: 70)
* `maxTemp`: Maximum allowed temperature (default: 74)
* `heatTransferCoefficient`: Heat transfer coefficient (default: 1)
* `irradianceCoefficient`: Solar irradiance coefficient (default: 0.5)
* `coolingRate`: Cooling rate multiplier (default: 1)
* `heatingRate`: Heating rate multiplier (default: 1)
* `days`: Number of days to simulate (default: 1)
**Monthly Type:**
* `start`: Start time configuration - either `{month: number}` (1-12) or `{startTime: Date}`
**Annual Type:**
* `months`: Array of month indices (1-12) to include. If `null`, all 12 months are included
### Key Features
* **Monthly Analysis**: Get detailed hourly data showing temperature profiles, energy consumption, and cost savings
* **Annual Estimates**: Get annualized savings projections for long-term planning
* **Flexible Configuration**: Customize target temperatures, setpoints, and HVAC modes
* **Weather Integration**: Automatically fetch outdoor temperature data from weather service
### Use Cases
* **Pre-Purchase Analysis**: Estimate potential savings before installing a smart thermostat
* **Optimization Strategy**: Compare different temperature setpoint strategies
* **Energy Efficiency Programs**: Demonstrate potential savings to customers
* **Seasonal Planning**: Analyze savings across different months of the year
### API Endpoint
```http theme={null}
POST /v1/homes/{homeId}/hvac/estimate_savings
```
For detailed API documentation, see the [HVAC Estimate Savings API Reference](/api-reference/endpoint/homes/get-hvac-estimated-savings-monthly-or-annual).
### Quick Example
Calculate monthly savings with optimized temperature setpoints:
```json theme={null}
{
"type": "monthly",
"targetTemp": 72,
"targetCoolSetpoint": 73,
"targetHeatSetpoint": 71,
"minTemp": 70,
"maxTemp": 74,
"mode": "AUTO",
"start": {
"month": 7
},
"days": 1
}
```
Calculate annual savings across all months:
```json theme={null}
{
"type": "annual",
"targetTemp": 72,
"minTemp": 70,
"maxTemp": 74,
"mode": "AUTO",
"days": 1,
"months": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
```
The response includes:
* Percentage and dollar savings
* Hourly temperature and consumption data (for monthly type)
* Baseline vs. optimized comparisons
* Energy consumption metrics (for annual type)
## Battery Estimate Savings
The Battery Estimate Savings endpoint helps you calculate potential savings from battery storage systems through time-of-use rate arbitrage.
### Request Parameters
**Required Fields:**
* `days`: Number of days to simulate per month
* `maxCapacityKiloWattHours`: Maximum battery capacity in kWh
* `chargingPowerKiloWatts`: Maximum charging power in kW
* `dischargingPowerKiloWatts`: Maximum discharging power in kW
* `chargingEfficiency`: Charging efficiency (0-1), typical value: 0.95
* `dischargingEfficiency`: Discharging efficiency (0-1), typical value: 0.95
* `currentSOC`: Current state of charge (0-1), typical value: 0.5
* `minPreferredSOC`: Minimum preferred state of charge (0-1)
* `maxPreferredSOC`: Maximum preferred state of charge (0-1)
**Optional Fields:**
* `solarCapacity`: Solar panel capacity in kW. Set to `null` if no solar
* `months`: Array of month indices (1-12) to include. If `null`, all 12 months are included
### Key Features
* **Standard Rate Optimization**: Calculate savings from time-of-use rate arbitrage
* **Solar Integration**: Include solar generation in calculations
* **Detailed Breakdowns**: Get monthly and daily savings breakdowns
* **Carbon Impact**: Calculate carbon emissions reductions
### Use Cases
* **Battery ROI Analysis**: Evaluate return on investment for battery storage systems
* **Solar + Battery Planning**: Optimize solar and battery sizing together
* **Energy Arbitrage**: Calculate savings from charging during low-rate periods and discharging during high-rate periods
* **Seasonal Analysis**: Compare battery performance across different months
### API Endpoint
```http theme={null}
POST /v1/homes/{homeId}/battery/estimate_savings
```
For detailed API documentation, see the [Battery Estimate Savings API Reference](/api-reference/endpoint/homes/get-battery-estimated-savings).
### Quick Example
Calculate annual savings with standard rate optimization:
```json theme={null}
{
"days": 1,
"solarCapacity": 5.0,
"maxCapacityKiloWattHours": 13.5,
"chargingPowerKiloWatts": 5.0,
"dischargingPowerKiloWatts": 5.0,
"chargingEfficiency": 0.95,
"dischargingEfficiency": 0.95,
"currentSOC": 0.5,
"minPreferredSOC": 0.2,
"maxPreferredSOC": 0.9,
"months": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
```
For a home without solar, set `solarCapacity` to `null`:
```json theme={null}
{
"days": 1,
"solarCapacity": null,
"maxCapacityKiloWattHours": 13.5,
"chargingPowerKiloWatts": 5.0,
"dischargingPowerKiloWatts": 5.0,
"chargingEfficiency": 0.95,
"dischargingEfficiency": 0.95,
"currentSOC": 0.5,
"minPreferredSOC": 0.2,
"maxPreferredSOC": 0.9,
"months": null
}
```
The response includes:
* Annual savings and costs
* Monthly and daily breakdowns with detailed statistics
* Carbon emissions reductions
* Optimized vs. baseline comparisons
## Prerequisites
Before using the Estimate Savings endpoints, ensure [onboarding](/docs/onboard_sites/prepare-onboarding) is completed successfully. When a request asks for `ratePlanId`, use the selected `ratePlans[].id` from `/v1/utility/get`; `ratePlans[].rateID` is the semantic tariff reference.
## Understanding the Results
### HVAC Results
**Monthly Response:**
* **Percentage Saved**: The percentage reduction in energy costs (0-1 scale)
* **Dollars Saved**: Total dollar amount saved over the analysis period
* **Temperature Data**: Hourly indoor temperatures showing optimization strategy
* **Consumption Data**: Hourly energy consumption comparing baseline vs. optimized
* **Setpoint List**: Array of setpoint temperatures for each hour
**Annual Response:**
* **Dollars Saved**: Annual dollar amount saved
* **Percentage Saved**: Annual percentage saved (0-1 scale)
* **Optimized Energy**: Annual optimized energy consumption (kWh)
* **Baseline Energy**: Annual baseline energy consumption (kWh)
* **Energy Reduction**: Annual energy reduction (kWh)
### Battery Results
* **Annual Savings**: Total dollars saved and percentage saved
* **Carbon Impact**: Carbon emissions saved (kg CO2) and reduction percentage
* **Monthly Breakdowns**: Detailed monthly results with:
* Monthly costs and savings
* Daily breakdowns within each month
* Statistics for dollars saved, percentage saved, and carbon impact
* **Optimized vs. Baseline**: Compare optimized costs and consumption with baseline scenarios
## Best Practices
1. **Start with Annual Estimates**: Use annual calculations for high-level planning, then drill down with monthly analysis for specific periods
2. **Compare Scenarios**: Run multiple calculations with different parameters to compare strategies:
* Different temperature setpoints for HVAC
* Different battery sizes or configurations
* With and without solar generation
* Different months or seasonal periods
3. **Month Indices**: Note that month indices are 1-12 (January = 1, December = 12) for both HVAC and Battery endpoints
4. **Battery Specifications**: For battery calculations, use accurate specifications matching your physical system:
* Capacity (kWh)
* Charging/discharging power (kW)
* Efficiency ratings
* State of charge preferences
# Impact Calculations
Source: https://docs.wattshift.com/docs/optimize_shifts_calculate_impacts/impact_calculations
Calculate bill cost, grid-services revenue, and carbon impact from interval usage data
WattShift Impact Calculations turn interval energy data into customer-facing impact metrics. Send 15-minute import usage, optionally include solar export, and receive calculated bill cost plus available grid-services revenue and carbon impact.
These endpoints are useful when you need to compare actual and counterfactual scenarios, validate a device-control strategy, estimate EV charging cost, or show the value of solar, storage, and load shifting under the customer's actual tariff.
The home-backed period route is available when the home is already onboarded. Use the direct `calculate` route when you want to calculate from inline home context without creating a persisted home first.
For quote-stage workflows that have selected a rate plan but should not create a persistent home yet, use the no-home rate-plan period bill route. It calculates tariff bill cost from the selected `ratePlans[].id` and interval import/export arrays. Because no home ZIP code is attached to that request, carbon and grid-services revenue are omitted.
## Endpoints
| Use case | Endpoint | When to use it |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| Custom-period impact calculation | [`POST /v1/homes/{homeId}/calculate/impact`](/api-reference/endpoint/homes/calculate-period-bill-impact-1) | You have a billing period or scenario window that does not line up exactly with a calendar month. |
| Inline-context impact calculation | [`POST /v1/calculate/impact`](/api-reference/endpoint/calculate/calculate-period-bill-impact-from-inline-context) | You have rate plan and ZIP code context, but do not want to create a home before calculating. |
| Quote-stage rate-plan bill | [`POST /v1/homes/bill/period/rateplan/{ratePlanId}`](/api-reference/endpoint/homes/calculate-period-bill-using-a-specific-rate-plan) | You have a selected rate plan and complete calendar-month or calendar-year interval arrays, but no persistent home yet. |
In the API reference, the home path parameter is named `{id}`. In the examples below, `{homeId}` means the same value: the ID of the home you are calculating impacts for.
## Prerequisites
Home-backed impact calculations require the home to have a stored `utilityId` and `ratePlanId`.
* Set these during [API-based onboarding](/docs/onboard_sites/api-based-onboarding).
* Use [Update Home](/api-reference/endpoint/homes/update-home) if you need to change them later.
* When a request asks for `ratePlanId`, send the selected `ratePlans[].id` from [`POST /v1/utility/get`](/api-reference/endpoint/utility/list-utilities). The companion `ratePlans[].rateID` is the semantic tariff reference, not the value to send as `ratePlanId`.
See [Rate Plan IDs](/docs/advanced_options/rate-plan-Id-Intro\&usage) for the full rate-plan selection flow.
## Usage Data
Both impact-calculation endpoints expect daily arrays of 15-minute interval values.
* Each day must contain exactly 96 numeric values.
* `usage` is import consumption in kWh.
* `export` is optional solar or battery export in kWh, using the same daily shape as `usage`.
* If `export` is provided, it must contain the same number of days as `usage`.
## Period Bills
Use the period endpoint when the analysis window is a customer billing period or scenario window.
```bash theme={null}
POST /v1/homes/{homeId}/calculate/impact
```
Send `startDate` and `endDate` as `YYYY-MM-DD` or ISO 8601 timestamps. The usage array must include one daily array for each date from `startDate` up to, but not including, `endDate`. For example, `2025-01-07` through `2025-02-08` requires 32 daily arrays.
```jsonc theme={null}
{
"usage": [
[0.18, 0.16, 0.11 /* 93 more 15-minute values */],
/* one daily array for each day in the period */
],
"export": [
[0, 0, 0 /* 93 more 15-minute values */],
/* optional; same number of daily arrays as usage */
],
"startDate": "2025-01-07",
"endDate": "2025-02-08",
}
```
## Inline Context
Use the direct calculate endpoint when you can provide the rate plan and ZIP code in the request body instead of referencing an onboarded home.
```bash theme={null}
POST /v1/calculate/impact
```
```jsonc theme={null}
{
"home": {
"ratePlanId": "64f1...",
"zipcode": "94612",
"carbonSignalImportance": "MEDIUM",
"solarCapacityKw": 6.4,
},
"usage": [
[0.18, 0.16, 0.11 /* 93 more 15-minute values */],
/* one daily array for each day in the period */
],
"startDate": "2025-01-07",
"endDate": "2025-02-08",
}
```
Set `useDefaultUsage` to `true` to generate usage from Palmetto baseline data using the supplied ZIP code and optional `solarCapacityKw`.
## Quote-Stage Rate-Plan Bills
Use the rate-plan period endpoint when the proposal or quote workflow has selected a tariff but should not create a home record. Quote-stage calculations require complete calendar months or complete calendar years: `startDate` must be the first day of a month, and `endDate` must be the first day of a later month.
```bash theme={null}
POST /v1/homes/bill/period/rateplan/{ratePlanId}
```
Send `ratePlanId` as the selected `ratePlans[].id` from [`POST /v1/utility/get`](/api-reference/endpoint/utility/list-utilities). Do not send `ratePlans[].rateID`; that field is the semantic tariff reference for display and troubleshooting.
```jsonc theme={null}
{
"usage": [
[0.3125, 0.3125, 0.3125 /* 93 more 15-minute values */],
/* one daily array for every day in July */
],
"export": [
[0, 0, 0 /* 93 more 15-minute values */],
/* optional; same number of daily arrays as usage */
],
"startDate": "2026-07-01",
"endDate": "2026-08-01",
"debug": true,
}
```
This route returns `billTotal`, `startDate`, `endDate`, optional `debugInfo`, and `exportCompensationCredit` when export compensation applies or is explicitly reported as zero.
## Response
Home-backed period calculations return impact fields for the requested window:
```json theme={null}
{
"billTotal": 132.56,
"gridServicesRev": 25.34,
"CO2e": 300,
"startDate": "2025-01-07",
"endDate": "2025-02-08"
}
```
* `billTotal`: Total tariff bill cost in local currency.
* `exportCompensationCredit`: Export compensation credit applied under NEM/NBT export pricing, when available.
* `gridServicesRev`: Estimated grid-services revenue in local currency, when available from the home's meter, ZIP code, and price-signal context.
* `CO2e`: Carbon dioxide equivalent emissions in pounds of marginal greenhouse gas, when available from the home's ZIP code and carbon-signal context.
## Notes
**Billing period matching**: Queries that do not precisely match a customer's billing period are still useful for relative bill and scenario calculations, but they will not exactly match the customer's utility bill total.
**Scenario comparison**: To show the value of a shift, run the same endpoint twice: once with the baseline usage profile and once with the shifted or optimized profile. Compare `billTotal`, `gridServicesRev`, and `CO2e` across the two responses.
**Solar export**: Include `export` when the customer has solar or battery exports that should offset import usage under the selected tariff.
# Price Signals for Shifting Optimization
Source: https://docs.wattshift.com/docs/optimize_shifts_calculate_impacts/price_signal
Getting price signals for onboarded homes
As an alternative to [optimized device outputs](/docs/optimize_shifts_calculate_impacts/receiving-updates), WattShift provides detailed
price signals for those who prefer to independently manage and optimize energy usage.
These signals incorporate a comprehensive range of factors, including tariffs,
wholesale price impacts, carbon prices, and non-net solar pricing.
To receive price signals for an onboarded home or site, use the following endpoint:\
`[POST] /v1/homes//price_signal`
Price signals are home-backed in the public API. The older direct rate-plan price-signal route is not published in public OpenAPI and is not available for public sandbox keys. For proposal-stage bill calculations before home creation, use [`POST /v1/homes/bill/period/rateplan/{ratePlanId}`](/api-reference/endpoint/homes/calculate-period-bill-using-a-specific-rate-plan); create a sandbox or partner home when you need a full price signal.
```json theme={null}
// Request Body
// [POST] /v1/homes/ws_home_7bc31940df8a4615b2dc9e84f3a92c51/price_signal
{
"startTime": "2025-02-25T16:13:37.902Z",
"endTime": "2025-02-26T16:13:37.902Z"
}
```
With this example output
```typescript theme={null}
{
"homeId":"ws_home_7bc31940df8a4615b2dc9e84f3a92c51",
"startTime":"2025-02-25T16:13:37.902Z",
"endTime":"2025-02-26T16:13:37.902Z",
"data":[
{
"startTime":"2025-02-25T16:13:37.902Z",
"endTime":"2025-02-26T01:13:37.902Z",
"price":0.42625,
"import":0.42625,
"export":0
},
{
"startTime":"2025-02-26T01:13:37.902Z",
"endTime":"2025-02-26T04:13:37.902Z",
"price":0.46486,
"import":0.46486,
"export":0
},
{
"startTime":"2025-02-26T04:13:37.902Z",
"endTime":"2025-02-26T16:13:37.902Z",
"price":0.42625,
"import":0.42625,
"export":0
}
],
"prices":[
0.42625,
0.42625,
...
0.42625,
0.46486,
...
0.46486,
0.46486,
0.46486,
0.42625,
0.42625,
...
0.42625,
0.42625
],
"imports":[
0.42625,
0.42625,
...
0.42625,
0.46486,
...
0.46486,
0.46486,
0.46486,
0.42625,
0.42625,
...
0.42625,
0.42625
],
"exports":[
0.0,
0.0,
...
0.0,
0.0
]
}
```
The `prices` represents \$ / kWh for a 15-minute interval, starting at
`startTime` until `endTime`.
## Price Signal Webhooks
Use a price signal webhook when WattShift should push price signals for all homes in your organization.
Register or update the destination URL with [`POST /v1/webhook/price_signal/set`](/api-reference/endpoint/webhook/set-or-update-the-price-signal-webhook-for-the-organization):
```json theme={null}
{
"webhookUrl": "https://example.com/wattshift/price-signals",
"securityKey": "replace-with-your-shared-secret",
"openAdr": false
}
```
Trigger a delivery window with [`POST /v1/webhook/price_signal/trigger`](/api-reference/endpoint/webhook/trigger-price-signal-webhook-for-organization-homes):
```json theme={null}
{
"startTime": "2025-02-25T16:13:37.902Z",
"endTime": "2025-02-26T16:13:37.902Z"
}
```
## OpenADR 3.0
We also make this data available in OpenADR 3.0 format.
```typescript theme={null}
await wattshiftApiCall(
`/homes/ws_home_7bc31940df8a4615b2dc9e84f3a92c51/price_signal/open_adr`,
);
```
```typescript theme={null}
{
"id": "12227765-47a7-4441-b9c4-215c779938e7",
"programID": "wattshift-open-adr",
"createdDateTime": "2024-12-22T23:38:09.218Z",
"modificationDateTime": "2024-12-22T23:38:09.218Z",
"eventName": "Price Event 2024-12-22",
"intervalPeriod": {
"start": "2024-12-22T23:38:09.218Z",
"duration": "PT24H"
},
"intervals": [
{
"id": 0,
"intervalPeriod": {
"start": "2024-12-22T23:38:09.218Z",
"duration": "PT1H"
},
"payloads": [
{
"type": "PRICE",
"values": [
0.4007
]
}
]
},
{
"id": 1,
"intervalPeriod": {
"start": "2024-12-23T00:38:09.218Z",
"duration": "PT4H"
},
"payloads": [
{
"type": "PRICE",
"values": [
0.3897
]
}
]
},
{
"id": 2,
"intervalPeriod": {
"start": "2024-12-23T04:38:09.218Z",
"duration": "PT1H"
},
"payloads": [
{
"type": "PRICE",
"values": [
0.4007
]
}
]
},
{
"id": 3,
"intervalPeriod": {
"start": "2024-12-23T05:38:09.218Z",
"duration": "PT2H"
},
"payloads": [
{
"type": "PRICE",
"values": [
0.4118
]
}
]
},
{
"id": 4,
"intervalPeriod": {
"start": "2024-12-23T07:38:09.218Z",
"duration": "PT1H"
},
"payloads": [
{
"type": "PRICE",
"values": [
0.3938
]
}
]
},
{
"id": 5,
"intervalPeriod": {
"start": "2024-12-23T08:38:09.218Z",
"duration": "PT14H"
},
"payloads": [
{
"type": "PRICE",
"values": [
0.3758
]
}
]
},
{
"id": 6,
"intervalPeriod": {
"start": "2024-12-23T22:38:09.218Z",
"duration": "PT1H"
},
"payloads": [
{
"type": "PRICE",
"values": [
0.3938
]
}
]
}
]
}
```
# Shift Watts!
Source: https://docs.wattshift.com/docs/optimize_shifts_calculate_impacts/receiving-updates
Responding to Optimized Schedules
After onboarding a user, WattShift will regularly send optimized set-point schedules.
Updating the device behavior accordingly will generate
grid revenue, lower customer electric bills,
and reduce partner companies' scope 3 emissions!
During development, rather than having to wait, you can also
query the following endpoint to receive the data for the most recently sent webhook.
```typescript theme={null}
const hvacId = hvac.id;
const schedules = await wattshiftApiCall(
`/devices/hvac/${hvacId}/set_point_schedule/get`,
);
```
See: [`/devices/hvac/:hvacId/set_point_schedule/get`](/api-reference/endpoint/hvac/get-set-point-schedule)
Here is an example output from a webhook.
```typescript theme={null}
{
eventType: 'SET_POINT_SCHEDULE',
data: {
'ws_device_123efg': {
blocks: [
{
startDatetime: '2024-08-03T12:00:00.000Z',
endDatetime: '2024-08-04T00:00:00.000Z',
targetTemp: '70',
targetMode: 'AUTO', // AUTO, HEAT, COOL
},
{
startDatetime: '2024-08-04T00:00:00.000Z',
endDatetime: '2024-08-04T12:00:00.000Z',
targetTemp: '68',
targetMode: 'COOL',
},
],
startDatetime: '2024-08-03T12:00:00.000Z',
endDatetime: '2024-08-04T12:00:00.000Z',
tempUnits: 'F', // F, C
},
},
}
```
# Updating User Preferences
Source: https://docs.wattshift.com/docs/optimize_shifts_calculate_impacts/user-preferences
Preview and save HVAC user preferences so WattShift can create schedules that respect comfort settings.
Once a user has onboarded, you can set and get user preferences for their devices.
The examples below assume `wattshiftApiCall` is your authenticated WattShift API helper.
## Previewing Schedules
Before saving user preferences, you can preview the suggested set-point schedules.
```typescript theme={null}
const userPreferences = {
tempUnits: "F",
defaultMode: "AUTO",
defaultMaxTemp: "75",
defaultMinTemp: "65",
scheduleBlocks: [
{
daysOfWeek: [1, 2, 3, 4, 5],
startTimeMinutes: "0",
endTimeMinutes: "1439",
targetTemp: "70",
},
{
daysOfWeek: [0, 6],
startTimeMinutes: "0",
endTimeMinutes: "1439",
targetTemp: "68",
},
],
};
// Preview the data.
const hvacId = "ws_device_123efg";
const { blocks } = await wattshiftApiCall(
`/devices/hvac/${hvacId}/preview`,
userPreferences,
);
const tempData = blocks.map((b) => ({
startTime: b.startTime,
endTime: b.endTime,
targetTemp: b.targetTemp,
}));
```
## Saving Preferences
If all looks good, you can save the user preferences.
```typescript theme={null}
const hvacId = "ws_device_123efg";
const userPreferences = {
tempUnits: "F",
defaultMode: "AUTO",
defaultMaxTemp: "75",
defaultMinTemp: "65",
scheduleBlocks: [
{
daysOfWeek: [1, 2, 3, 4, 5],
startTimeMinutes: "0",
endTimeMinutes: "1439",
targetTemp: "70",
},
],
};
await wattshiftApiCall(
`/devices/hvac/${hvacId}/user_preferences/set`,
userPreferences,
);
```