Step 6: Generate a Storage-in-Switch Savings Analysis
Run a Savings Analysis with storageProviderProfileId to apply post-storage profiles and model storage effects on project savings.
Run a Savings Analysis with storageProviderProfileId to apply post-storage profiles and model storage effects on project savings.
In this step, you’ll pass a new storageProviderProfileId property input to the Savings Analysis endpoint to reference the profiles that were created in Step 5 and apply them to simulate the effects of storage on savings.
Storage savings analysis workflow
- Use the account from Step 1:
storage-switch-example. - Use the original usage profile from Step 3:
storage-switch-example-usage. - Use the post-storage family ID from Step 5:
storage-switch-example-post-storage. - Send the Savings Analysis request to
POST /rest/v1/accounts/analysis. - Pass
storageProviderProfileIdfor theafter,solarscenarios. - Set
projectDuration. - Optionally set
batteryDegradation. - Review
lifetimeAvoidedCostSolarAndRateChangeandlifetimeAvoidedCostStorageOnlyin the response.
| Input | Value |
|---|---|
| Account | storage-switch-example |
| Original usage profile | storage-switch-example-usage |
| Original solar profile | storage-switch-example-solar |
| Post-storage family ID | storage-switch-example-post-storage |
Set this property to the providerProfileId sent in the storage profile creation step. When passed to the Savings Analysis, as in the example below, Switch runs a series of validations to ensure the optimized profiles exist and include all necessary inputs, then assigns them to the Savings Analysis scenarios defined by the user.
You can override the storage profile values by passing an explicit key to the Savings Analysis. For example, the Savings Analysis uses the following default hierarchy to determine what tariff to use in the calculations:
- Explicit
aftermasterTariffIdpassed in the Savings Analysis. mainTariffIdsaved on the storage profile.- Post-solar
masterTariffIdset on the account. - Solar tariff associated with the account ZIP code, if a post-solar
masterTariffIdis not set on the account or is a non-solar tariff.
Input notes
Our savings projection method for lifetime storage depends strongly on how the battery’s capacity degrades each year. Lifetime calculations with storage support two conventions for capacity fade:
- Percent-based (compounding) degradation: battery capacity reduces by the specified percentage, year over year.
Use"batteryDegradation": { "percentPerYear": 3 }to indicate a 3%-per-year degradation rate. - Linear degradation: battery capacity degrades by the absolute value specified each year.
Use"batteryDegradation": { "kwhPerYear": 0.1 }to indicate a 0.1 kWh-per-year degradation rate.
By default, we assume that the capacity starts at the value of batteryNameplateCapacity you passed during storage profile creation and decays by 2% per year.
Run a storage savings analysis
Request example with 3% battery degradation year-over-year
POST /rest/v1/accounts/analysisInclude the timezone in
fromDateTimeandtoDateTimeso the analysis period aligns with the post-storage profiles created in Step 5. Pass the original usage profile only to thebeforescenario, and passstorage-switch-example-post-storageasstorageProviderProfileIdfor theafter,solarscenarios.
{
"providerAccountId": "storage-switch-example",
"fromDateTime": "2023-05-01T00:00:00-07:00",
"toDateTime": "2024-05-01T00:00:00-07:00",
"propertyInputs": [
{
"scenarios": "before",
"keyName": "masterTariffId",
"dataValue": "522"
},
{
"scenarios": "before",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-usage"
},
{
"scenarios": "after,solar",
"keyName": "storageProviderProfileId",
"dataValue": "storage-switch-example-post-storage"
},
{
"scenarios":"solar,after,before",
"keyName": "projectDuration",
"dataValue": 10
}
],
"batteryDegradation": { "percentPerYear": 3 }
}| Field | Purpose |
|---|---|
providerAccountId | Account created in Step 1. |
fromDateTime / toDateTime | Savings Analysis period. |
before.masterTariffId | Pre-solar tariff used for the before scenario. |
before.providerProfileId | Original usage profile created in Step 3. |
storageProviderProfileId | Post-storage family ID created in Step 5. |
projectDuration | Number of years to model. |
batteryDegradation.percentPerYear | Annual battery capacity degradation rate. |
You do not need to run the solar-only request to complete the Storage-in-Switch workflow. The following example is included only to show how the storage request differs from a standard solar Savings Analysis. In the solar-only pattern, you pass an explicit after masterTariffId, use the original usage profile for both before and after, and pass the original solar profile instead of the post-storage profile family ID.
{
"providerAccountId": "storage-switch-example",
"fromDateTime": "2023-05-01T00:00:00-07:00",
"toDateTime": "2024-05-01T00:00:00-07:00",
"propertyInputs": [
{
"scenarios": "before",
"keyName": "masterTariffId",
"dataValue": "522"
},
{
"scenarios": "after",
"keyName": "masterTariffId",
"dataValue": "3424821"
},
{
"scenarios": "before,after",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-usage"
},
{
"scenarios": "after,solar",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-solar"
},
{
"scenarios":"solar,after,before",
"keyName": "projectDuration",
"dataValue": 10
}
]
}Response notes
Savings Analyses with more than a one-year duration contain two new series and summary parameters representing the avoided costs attributable directly to solar and to storage, respectively. These parameters help you understand how much value storage adds on top of solar.
At the summary level, these fields are reported under the following two fields:
lifetimeAvoidedCostSolarAndRateChangelifetimeAvoidedCostStorageOnly
The sum of the two should equal lifetimeAvoidedCost.
{
"summary": {
"lifeTimeUtilityAfterCost": 3710.174779,
"lifeTimeUtilityAvoidedRate": 0.295616,
"lifetimeAvoidedCost": 22265.625221,
"lifetimeAvoidedCostSolarAndRateChange": 13463.303221,
"lifetimeAvoidedCostStorageOnly": 8802.322
}
}At the series level, these fields are given in the final two series, which might look something like this:
[
{
"seriesId": 13,
"fromDateTime": "2023-01-01T00:00:00-08:00",
"toDateTime": "2033-01-01T00:00:00-08:00",
"scenario": "storageOnlySavings",
"displayLabel": "Storage Contribution to Total Savings (Annual/Lifetime)",
"seriesPeriod": "YEAR",
"seriesDuration": 10,
"designId": null,
"key": null,
"cost": 8802.322
},
{
"seriesId": 14,
"fromDateTime": "2023-01-01T00:00:00-08:00",
"toDateTime": "2033-01-01T00:00:00-08:00",
"scenario": "solarOnlySavings",
"displayLabel": "Solar Contribution to Total Savings (Annual/Lifetime)",
"seriesPeriod": "YEAR",
"seriesDuration": 10,
"designId": null,
"key": null,
"cost": 13463.303221
}
]How qty and rate approximations are calculated in after series
Most of the series summaries and seriesData yearly details in a lifetime response contain the three fields:
cost: the projected average cost of the electricityqty: the projected total number of units of electricity purchased over the intervalrate: the projected average price of electricity purchased over the interval
For solar-only analyses, cost is computed from quantity and rate (cost = qty * rate) for each year of the calculation.
However, our savings projection for solar + storage projects the cost savings directly. Because we expect both the total quantity and average rate to change over time with the introduction of storage (due to arbitrage and peak-shifting), we don’t use qty and rate in the computation. Instead, we approximate these values going backward from our estimated cost, first computing the yearly storage after rate by interpolating between the year-1 storage value and the yearly solar value (starting at the year-1 storage value but decaying to the yearly solar value as the battery capacity degrades), then finally inferring qty as cost / rate.
Finally, we use these inferred qty values to estimate lifeTimeUtilityAvoidedRate in the top-level summary.
Optional: Handle consumption-based solar costs
Savings Analyses can model costs for power purchase agreement (PPA) solar installations using “CONSUMPTION_BASED” charge types (see documentation example). For these installations, customers can be charged per kWh of solar generated by the panel rather than per kWh exported to the grid.
In such cases, omitting the original solar profile and passing only "after,solar" for the storage scenarios can undercount costs. Some generated solar will be used to power the home or get stored in the battery, so the post-storage solar profile will have smaller kWh values than the original solar profile.
To fix this, remove solar from the list of storage scenarios, and separately pass the original solar profile with only solar as its scenario. In this pattern, the solar scenario uses storage-switch-example-solar, and the after scenario uses storage-switch-example-post-storage.
{
"propertyInputs": [
{
"scenarios": "before",
"keyName": "masterTariffId",
"dataValue": "522"
},
{
"scenarios": "before",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-usage"
},
{
"scenarios": "solar",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-solar"
},
{
"scenarios": "after",
"keyName": "storageProviderProfileId",
"dataValue": "storage-switch-example-post-storage"
},
{
"scenarios":"solar,after,before",
"keyName": "projectDuration",
"dataValue": 1
}
]
}Appendix
Optional: Reference generated post-storage profiles directly
As described in Step 5, the storage profile creation endpoint creates three profiles:
- Usage: an updated consumption profile representing remaining site consumption not covered by solar generation or storage discharge. This profile’s kWh values should be less than or equal to the original consumption kWh values at all timesteps.
- Solar: an updated solar profile representing solar exports to the grid. This profile’s kWh values should also be less than or equal to the original solar kWh values at all timesteps, since some of the solar goes to charge the battery or meet site consumption.
- Battery: a storage-specific profile representing grid imports and exports directly attributable to the battery. This profile can have both positive and negative values, with positive values representing kWh purchased from the grid to charge the battery and negative values representing kWh sold back to the grid from the battery. If
allowGridToBatteryandallowBatteryToGridare both set tofalse, all kWh values for this profile should be 0.
If the providerProfileId passed during profile creation was storage-switch-example-post-storage, then these profiles will have provider profile IDs of storage-switch-example-post-storage-usage, storage-switch-example-post-storage-solar, and storage-switch-example-post-storage-storage.
Instead of passing the "storage-switch-example-post-storage" family name to storageProviderProfileId during Savings Analyses, you can, though it is more verbose, construct a Savings Analysis request by referencing each profile individually using its providerProfileId, along with the after tariff:
{
"propertyInputs": [
{
"scenarios": "before",
"keyName": "masterTariffId",
"dataValue": "522"
},
{
"scenarios": "after",
"keyName": "masterTariffId",
"dataValue": "3424821"
},
{
"scenarios": "before",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-usage"
},
{
"scenarios": "after",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-post-storage-usage"
},
{
"scenarios": "after,solar",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-post-storage-solar"
},
{
"scenarios": "after",
"keyName": "providerProfileId",
"dataValue": "storage-switch-example-post-storage-storage"
},
{
"scenarios":"solar,after,before",
"keyName": "projectDuration",
"dataValue": 1
}
]
}
This workflow is no longer recommended because it is unnecessarily verbose and more error-prone for users, but we include it here to provide a clearer sense of what is happening under the hood when running Savings Analyses or Account Cost Calculations over storage profiles.
Optional: Account Cost Calculations on storage profiles
Account Cost Calculation can be used to determine granular costs for storage calculations. For example, it can be used to determine the cost of electricity at specific times, such as 12 PM on June 13th.
Example request
Only pass the storage profile family ID in storageProviderProfileId for this calculation.
{
"fromDateTime": "2024-06-01T00:00:00",
"toDateTime": "2025-06-01T00:00:00",
"includeDefaultProfile": "false",
"minimums": "true",
"detailLevel": "CHARGE_TYPE",
"groupBy": "HOUR",
"fields": "EXT",
"autoBaseline": true,
"useIntelligentBaselining": true,
"propertyInputs": [
{
"keyName": "storageProviderProfileId",
"dataType": "STRING",
"dataValue": "storage-switch-example-post-storage"
}
]
}Notes
- Account Cost Calculation will use the tariff set on the storage profile, regardless of the
masterTariffIdyou pass into the Account Cost Calculation request. - When running an account cost calculation for storage, you must only include the storage provider profile ID in your request.
- Any of the following detail levels are supported for account cost calculations with storage profiles. However,
CHARGE_TYPE_AND_TOUis not compatible with NEM3 tariffs.
| Detail Level Value | Description |
|---|---|
| TOTAL | Return only the overall total, without any item breakdown. |
| CHARGE_TYPE | Group the rates by charge type, such as FIXED, CONSUMPTION, QUANTITY. |
| CHARGE_TYPE_AND_TOU | Group the rates by charge type, quantity type, season, tariff version, time of use, and tiers. NOT COMPATIBLE WITH NEM3 TARIFFS |
| RATE | Group the items by rates. |
| ALL | Group the calculation results by distinct calculation interval (full details). |
Summary
You have completed the Storage-in-Switch workflow. You created an account, confirmed the utility and tariff, created usage and solar profiles, generated post-storage profiles, and ran a Savings Analysis using storageProviderProfileId.
Updated about 5 hours ago
