Working With Contracted Rates
This How-To describes working with contracted rates in deregulated markets (markets where the end customer has some sort of choice over who they purchase their electricity from).
What are Contracted Rates?
Contracted Rates are useful when a customer is located in a deregulated market that has one set of rates for their energy supply and another set of rates for their transmission and delivery. The phrase "contracted rate" here refers to any situation where a customer's electricity bill is divided into two providers: one for the energy itself (the "supply rate") and one for the right to use the transmission and distribution system to deliver that energy to their premises (the "transmission and distribution" or "T-and-D" rate).
Typically, customers in this situation will have their choice of many different providers for their supply, but not any choice for delivery. The Arcadia API reflects this situation in the way that it handles these contracted rates. The rate for energy supply is provided as a separate tariff input on top of an account's masterTariffId
, replacing some or all of its energy supply components.
Identifying Tariffs with Contracted Rates
How do I know if my customer is on a tariff with contracted rates and which rates are contractable? You can identify tariffs with contracted rates by using the parameter hasContractedRates
when retrieving a list of tariffs. Rates with a chargeClass
of CONTRACTED
are eligible for replacement by third-party suppliers. Here is an example of retrieving tariffs with contracted rates for an account that has an address in New York City (in this case zipCode=10001
and country=US
):
GET /rest/v1/accounts/pid/{providerAccountId}/rates?effectiveOn=2017-11-01&hasContractedRates=true
Here is a snippet of some of the contracted rates returned for ConEd's Small General (EL2) tariff:
{
"tariffRateId": 17827306,
"tariffId": 3282860,
"tariffSequenceNumber": 9,
"rateGroupName": "Merchant Function Charge",
"rateName": "Merchant Function Charge",
"fromDateTime": "2017-04-01T00:00:00-04:00",
"toDateTime": null,
"chargeType": "CONSUMPTION_BASED",
"chargeClass": "SUPPLY,CONTRACTED",
"chargePeriod": "MONTHLY",
"variableRateKey": "2252MerchantFunctionChargeSC2",
"rateBands": [
{
"tariffRateBandId": 11560550,
"tariffRateId": 17827306,
"rateSequenceNumber": 1,
"hasConsumptionLimit": false,
"hasDemandLimit": false,
"hasPropertyLimit": false,
"rateAmount": 0,
"rateUnit": "COST_PER_UNIT",
"isCredit": false,
"prevUpperLimit": null
}
]
},
{
"tariffRateId": 17827307,
"tariffId": 3282860,
"tariffSequenceNumber": 10,
"rateGroupName": "Monthly Adjustment Clause",
"rateName": "Monthly Adjustment Clause",
"fromDateTime": "2017-04-01T00:00:00-04:00",
"toDateTime": null,
"chargeType": "CONSUMPTION_BASED",
"chargeClass": "DISTRIBUTION",
"chargePeriod": "MONTHLY",
"variableRateKey": "MonthlyAdjustmentClause2252",
"rateBands": [
{
"tariffRateBandId": 11560551,
"tariffRateId": 17827307,
"rateSequenceNumber": 1,
"hasConsumptionLimit": false,
"hasDemandLimit": false,
"hasPropertyLimit": false,
"rateAmount": 0,
"rateUnit": "COST_PER_UNIT",
"isCredit": false,
"prevUpperLimit": null
}
]
},
{
"tariffRateId": 17827308,
"tariffId": 3282860,
"tariffSequenceNumber": 11,
"rateGroupName": "Ancillary Service Charge",
"rateName": "Ancillary Service Charge",
"fromDateTime": "2017-04-01T00:00:00-04:00",
"toDateTime": null,
"chargeType": "CONSUMPTION_BASED",
"chargeClass": "SUPPLY,CONTRACTED",
"chargePeriod": "MONTHLY",
"variableRateKey": "ancillaryServiceCharge",
"rateBands": [
{
"tariffRateBandId": 11560552,
"tariffRateId": 17827308,
"rateSequenceNumber": 1,
"hasConsumptionLimit": false,
"hasDemandLimit": false,
"hasPropertyLimit": false,
"rateAmount": 0,
"rateUnit": "COST_PER_UNIT",
"isCredit": false,
"prevUpperLimit": null
}
]
},
Setting a Contracted Rate on a Calculation
To include a contracted rate or rates in your calculation, you will want to pass that rate as a Rate Input with the chargeClass set to "CONTRACTED". This tells the calculation engine to replace all rates with a charge class of CONTRACTED with the rate provided in the rate input. In this example, we are setting a contracted rate of $0.10/kWh for a calculation.
POST /rest/v1/ondemand/calculate/
with the following request body:
{
"fromDateTime": "2018-04-03T00:00:00-04:00",
"toDateTime": "2018-05-02T00:00:00-04:00",
"masterTariffId": "83386",
"groupBy": "MONTH",
"detailLevel": "CHARGE_TYPE_AND_TOU",
"billingPeriod": true,
"rateInputs": [
{
"chargeClass": "CONTRACTED",
"chargePeriod": "MONTHLY",
"chargeType": "CONSUMPTION_BASED",
"rateName": "Contracted Rate",
"transactionType": "NET",
"rateBands": [
{
"hasPropertyLimit": false,
"rateAmount": "0.1",
"rateUnit": "COST_PER_UNIT",
"hasConsumptionLimit": false,
"hasDemandLimit": false
}
]
}
],
"propertyInputs": [
{
"keyName": "consumption",
"fromDateTime": "2018-04-03T00:00:00-04:00",
"duration": 900000,
"dataSeries": [
15.43451690673828,
13.85958480834961,
10.963741302490234,
18.40724182128906,
14.999061584472656,
... /edited for length
18.467796325683594,
14.12566375732422,
12.47233581542969,
11.939910888671875,
10.56745147705078,
15.05100631713867,
9.197296142578125
],
"unit": "kWh"
}
]
}
Setting a Contracted Rate on an Account
For Switch customers, you have the option to set your contracted rate or rates on your Account, and then have it automatically picked up on subsequent calculations. Setting a contracted rate on the Account is just like making an update to the account. This update, though, has some fields that describe the components of your contracted rate. Let's look at an example.
In this example, we're going to set the customer's supply rate to $0.05 per kWh (that's a good rate!). To do this, we'll make an update request to the accounts endpoint:
PUT /rest/v1/accounts
with the following request body:
{
"providerAccountId": "YOUR_PROVIDER_ACCOUNT_ID",
"tariffs": [
{
"masterTariffId": 122972,
"serviceType": "ELECTRICITY",
"rates": [
{
"rateName": "Contracted Rate",
"tariffBookRateName": "Contracted Rate",
"chargeClass": "CONTRACTED",
"chargeType": "CONSUMPTION_BASED",
"transactionType" : "NET",
"rateBands": [
{
"hasConsumptionLimit": true,
"rateAmount": "0.05",
"rateUnit": "COST_PER_UNIT",
"isCredit": false
}
]
}
]
}
]
}
Let's break this request down.
- Since we're making an account update, we have to make sure to supply our
providerAccountId
(or, if you prefer, the Arcadia-generatedaccountId
). - Even though we're setting a special rate for the customer's supply, they still have to pay the t-and-d costs to actually get the energy to their home. This person is a residential customer in Pennsylvania, so they're on the "PD" tariff in PECO territory, which has a
masterTariffId
of122972
. - We want to replace all of this customer's kWh charges with our special $0.05 per kWh rate. To do that, we're specifying in our contracted rate that it only applies to a
chargeType
ofCONSUMPTION_BASED
, which means that it only applies to the customer's energy consumption. There are a number of other charge types, includingFIXED_PRICE
(like service charges),DEMAND_BASED
(kW charges), orQUANTITY
(per meter or per lamp, for certain tariffs). - We have set the
transactionType = NET
meaning that if the customer sends kWh to the grid, they will be credited for kWh at the same rate they buy kWh. You do have the option to indicate that the customer gets no compensation (transactionType=BUY
) when sending kWh to the grid.
Once we've set up the account's tariff in this way, all of their charges for energy consumption will now be at the $0.05 per kWh rate that we specified, rather than whatever was on our original PECO tariff.
Setting a Contracted Rate in a Savings Analysis
Switch customers also have the option to set their contracted rate or rates in the Savings Analysis call. You must first complete steps 1-4 in the Forecasted Savings Tutorial, then the example below can be applied to step 5 Run a Savings Analysis.
In this example we will use typicals for both profiles.
POST /rest/v1/accounts/analysis
{
"providerAccountId": "YOUR_PROVIDER_ACCOUNT_ID",
"fromDateTime": "2024-08-01T00:00:00+00:00",
"toDateTime": "2025-08-01T00:00:00+00:00",
"useIntelligentBaselining": true,
"propertyInputs": [
{
"keyName": "projectDuration",
"dataType": "INTEGER",
"dataValue": "20"
},
{
"keyName": "baselineType",
"dataType": "STRING",
"dataValue": "typicalSolarPv",
"scenarios": "after,solar",
"operator": "-"
},
{
"keyName": "solarPvLoadOffset",
"unit": "%",
"dataValue": "80",
"scenarios": "after,solar"
},
{
"keyName": "rateInflation",
"dataType": "DECIMAL",
"dataValue": "1.9",
"scenarios": "solar"
},
{
"keyName": "baselineType",
"dataType": "STRING",
"dataValue": "typicalElectricity",
"scenarios": "before,after"
},
{
"keyName": "rateInflation",
"dataType": "DECIMAL",
"dataValue": "3",
"scenarios": "before,after"
},
{
"keyName": "masterTariffId",
"displayName": "Residential",
"dataType": "INTEGER",
"dataValue": "522",
"scenarios": "before"
}
],
"rateInputs": [
{
"masterTariffRateId": null,
"tariffBookSequenceNumber": null,
"tariffBookRateGroupName": null,
"tariffBookRateName": null,
"rateName": "Solar PPA Rate",
"fromDateTime": null,
"toDateTime": null,
"chargeType": "CONSUMPTION_BASED",
"chargePeriod": "MONTHLY",
"transactionType": "BUY",
"rateBands": [
{
"tariffRateBandId": null,
"tariffRateId": null,
"rateSequenceNumber": null,
"hasConsumptionLimit": null,
"hasDemandLimit": null,
"hasPropertyLimit": false,
"rateAmount": 0.20,
"rateUnit": null,
"isCredit": null,
"prevUpperLimit": null
}
],
"scenarios": "solar"
},
{
"masterTariffRateId": null,
"tariffBookSequenceNumber": null,
"tariffBookRateGroupName": null,
"tariffBookRateName": null,
"rateName": "Third Party Supply Rate",
"fromDateTime": null,
"toDateTime": null,
"chargeType": "CONSUMPTION_BASED",
"chargeClass": "CONTRACTED",
"chargePeriod": "MONTHLY",
"transactionType": "NET",
"rateBands": [
{
"tariffRateBandId": null,
"tariffRateId": null,
"rateSequenceNumber": null,
"hasConsumptionLimit": null,
"hasDemandLimit": null,
"hasPropertyLimit": false,
"rateAmount": 0.14,
"rateUnit": null,
"isCredit": null,
"prevUpperLimit": null
}
],
"scenarios": "before,after"
}
]
}
- Under
rateInputs
you'll see we have entered 2 rates. The first is our solar PPA cost and the second is our Third Party Supply Rate. - It's important to specify which scenarios the Third Party Supply Rate applies to. In this case, the customer maintains the same supply rate before and after the solar installation. However, this rate does not apply to the solar scenario alone, as the rate inputs section for the solar scenario is specifically reserved for solar costs.
Block and Index Rates
In the last section, we saw a simple example of a contracted rate. In that example, we replaced the customer's normal supply rate with a custom rate of $0.05 per kWh. In deregulated markets, however, there are many different variations on the structure of contracted rates that are much more complicated. One example of a more complicated rate structure is what's known as a "block and index" rate.
A block and index rate has two components: a fixed price for the first part of the customer's monthly energy usage, and then a variable rate that is tied to some index price for the rest. The advantage of this structure is that you usually get a fixed, low rate for most of your energy usage. The downside is that, if you don't use enough energy to consume your entire block allocation, you still have to pay for it. In this next example, we'll see how to set this up using a contracted rate.
Here are the details of the block and index rate that we're going to set up for our account:
- For the first 2,000 kWh of hourly usage, set a flat rate of $0.05 per kWh.
- For the next 600 kWh of hourly usage, the flat rate increases to $0.06 per kWh.
- After that, index the rate to PJM's hourly real-time price.
The calculator request is a little bit more complicated for block and index contracted rates. Below is the snippet that should be passed into the rateInputs
section:
{
"rateInputs": [
{
"rateName": "Multiple Block and Index Rate",
"tariffBookRateName": "Multiple Block and Index Rate",
"chargeClass": "CONTRACTED",
"chargeType": "CONSUMPTION_BASED",
"chargePeriod": "HOURLY",
"transactionType": "BUY",
"variableRateKey": "hourlyPricingRealTimePJM",
"variableRateSubKey": "51291",
"rateBands": [
{
"hasConsumptionLimit": true,
"consumptionUpperLimit": 2000,
"rateAmount": "0.05",
"rateUnit": "BLOCK",
"isCredit": false
},
{
"hasConsumptionLimit": true,
"consumptionUpperLimit": 2600,
"rateAmount": "0.06",
"rateUnit": "BLOCK",
"isCredit": false
},
{
"hasConsumptionLimit": true,
"rateAmount": null,
"rateUnit": "COST_PER_UNIT",
"isCredit": false
}
]
}
]
}
You'll notice a few similarities to the prior example, but also a lot of new fields and parameters. Let's take a look at them. First, there are a few new tariff properties:
"chargePeriod":"HOURLY"
tells the API that, for the block portions of the tariff, the consumption limits are defined hourly, and, once we get to the index portion of the tariff, we're going to update their rate hourly."transactionType":"BUY"
means that we're going to charge the customer for this energy. This is as opposed to the"SELL"
option, which would result in a credit."variableRateKey":"hourlyPricingRealTimePJM"
specifies the particular index that we're going to be buying energy from. In this case, it's PJM. See below for information on how to get a different index."variableRateSubKey":"51291"
. Within PJM's market, there are a number of delivery points. Here, we're specifying the AECO delivery point, which has the identifier51291
. See below for information on how to get a different delivery point.
Second, our rateBands
are more complex than they were before. That makes sense since we have two tiers and an index in this rate instead of a single flat rate for all of our energy usage. We'll go through them one at a time:
"consumptionUpperLimit":2000
(and the subsequent one with a value of2600
) specifies that this block applies only to the first 2,000 kWh of energy usage for each hour in the billing period. Note that our second block has aconsumptionUpperLimit
value of 2,600 even though it only represents 600 kWh of usage. This is because theconsumptionUpperLimit
parameter refers to total consumption, not incremental consumption. So, for example, if you had three blocks of 300 kWh, 200 kWh, and 200 kWh, you would specify theirconsumptionUpperLimit
values as 300, 500, and 700, respectively."rateUnit":"BLOCK"
tells the API that this portion of the bill is fixed. Even if the customer doesn't use all 2,600 kWh that they've been allocated (2,000 + 600), they still have to pay for the entire block.- The final rate band doesn't have a
rateAmount
property, but it does have a differentrateUnit
:COST_PER_UNIT
. This combination of properties indicates that, once the customer has used up their entire allotment of fixed-price energy for the month, we fall back on the index that we defined earlier -- PJM real-time pricing at the AECO delivery point -- for the rest of their energy usage during that billing period.
With that, we've defined our block and index rate.
Getting more Indexes
We defined the index using the variableRateKey
. In the example above we used thehourlyPricingRealTimePJM
and then defined a variableRateSubKey
to specify the appropriate certain delivery point. The combination of these two things -- the index and the delivery point -- determines exactly how much this customer will pay for their energy.
The Arcadia API has more indexes and more delivery points than just these, though. In fact, at the time of writing this How To we had 13 of them, and we add more all the time. To see them all, you can use the following request:
GET /rest/public/properties/?keySpace=market
This will return a list of all indexes in our database.
Delivery Points
Some, though not all, market indexes have different prices for different delivery points. The one that we used in this example, hourlyPricingRealTimePJM
, has 20. To specify your delivery point, you'll need to add the variableRateSubKey
property in addition to the variableRateKey
that we already added. How do you know what to put there? Just use the following request, replacing hourlyPricingRealTimePJM
with the particular index that you're interested in:
GET /rest/public/properties/hourlyPricingRealTimePJM/
This will return a list of all available variableRateSubKey
values for this index. The list looks like this:
{
"status": "success",
"count": 1,
"type": "PropertyKey",
"results": [
{
"keyName": "hourlyPricingRealTimePJM",
"displayName": "Hourly Pricing Real Time PJM",
"family": "pjm",
"keyspace": "market",
"description": "Hourly Pricing Real Time PJM",
"dataType": "LOOKUP",
"choices": [
{
"displayValue": "AECO",
"value": "51291",
"dataValue": "51291",
"likelihood": null
},
/* edited for length */
{
"displayValue": "RECO",
"value": "7633629",
"dataValue": "7633629",
"likelihood": null
}
]
}
To specify your delivery point, use the dataValue
field of that delivery point in the list of choices for the value of your variableRateSubKey
property.
Block and Index Rates with Time of Use
Another flavor of third-party supply contracts are block and index rates with time-of-use pricing. These contracts behave like generic block and index rates but with separate prices and block sizes for each time of use definition (e.g. Summer On-Peak).
The key when creating Time of Use block and index rates is to make sure that all time of use definitions are included.
WARNING: Make sure that you create a rate for all time-of-use definitions in the time-of-use group. If you do not, there will be hours when your customer will not be charged. To get a list of all the time of use definitions in a time of use group, you should reference the Time of Use API endpoint.
The time of use definitions you use for your contracted rates do not have to match the time of use definition used by the utility’s tariff.
Here’s a sample call where there are two on-peak blocks and one off-peak block, in both Summer and Winter. For this, we set up four rates:
Summer On-Peak
- $0.05/kWh up to 10 kWh
- $0.06/kWh up to 20 kWh
- Index price above 20 kWh
Winter On-Peak
- $0.045/kWh up to 10 kWh
- $0.055/kWh up to 20 kWh
- Index price above 20 kWh
Summer Off-Peak
- $0.05/kWh up to 10 kWh
- Index price above 10 kWh
Winter Off-Peak
- $0.04/kWh up to 10 kWh
- Index price above 10 kWh
Below is the rateInputs
snippet of the on-demand calculation request (not the full request).
{
"rateInputs": \[{
"rateName": "Summer On-Peak Block and Index Rate",
"tariffBookRateName": "Summer On-Peak Block and Index Rate",
"chargeClass": "CONTRACTED",
"chargePeriod": "HOURLY",
"transactionType": "BUY",
"variableRateKey": "hourlyPricingRealTimePJM",
"variableRateSubKey": "51291",
"timeOfUse": {
"touId": 628
},
"rateBands": [{
"hasConsumptionLimit": true,
"consumptionUpperLimit": 10,
"rateAmount": "0.05",
"rateUnit": "BLOCK",
"isCredit": false
}, {
"hasConsumptionLimit": true,
"consumptionUpperLimit": 20,
"rateAmount": "0.06",
"rateUnit": "BLOCK",
"isCredit": false
}, {
"hasConsumptionLimit": true,
"rateAmount": null,
"rateUnit": "COST_PER_UNIT",
"isCredit": false
}]
}, {
"rateName": "Winter On-Peak Block and Index Rate",
"tariffBookRateName": "Winter On-Peak Block and Index Rate",
"chargeClass":"CONTRACTED",
"chargeType": "CONSUMPTION_BASED",
"chargePeriod": "HOURLY",
"transactionType": "BUY",
"variableRateKey": "hourlyPricingRealTimePJM",
"variableRateSubKey": "51291",
"timeOfUse": {
"touId": 629
},
"rateBands": [{
"hasConsumptionLimit": true,
"consumptionUpperLimit": 10,
"rateAmount": "0.045",
"rateUnit": "BLOCK",
"isCredit": false
}, {
"hasConsumptionLimit": true,
"consumptionUpperLimit": 20,
"rateAmount": "0.055",
"rateUnit": "BLOCK",
"isCredit": false
}, {
"hasConsumptionLimit": true,
"rateAmount": null,
"rateUnit": "COST_PER_UNIT",
"isCredit": false
}]
}, {
"rateName": "Summer Off-Peak Block and Index Rate",
"tariffBookRateName": "Summer Off-Peak Block and Index Rate",
"chargeClass":"CONTRACTED",
"chargeType": "CONSUMPTION_BASED",
"chargePeriod": "HOURLY",
"transactionType": "BUY",
"variableRateKey": "hourlyPricingRealTimePJM",
"variableRateSubKey": "51291",
"timeOfUse": {
"touId": 636
},
"rateBands": [{
"hasConsumptionLimit": true,
"consumptionUpperLimit": 10,
"rateAmount": "0.05",
"rateUnit": "BLOCK",
"isCredit": false
}, {
"hasConsumptionLimit": true,
"rateAmount": null,
"rateUnit": "COST_PER_UNIT",
"isCredit": false
}]
}, {
"rateName": "Winter Off-Peak Block and Index Rate",
"tariffBookRateName": "Winter Off-Peak Block and Index Rate",
"chargeClass":"CONTRACTED",
"chargeType": "CONSUMPTION_BASED",
"chargePeriod": "HOURLY",
"transactionType": "BUY",
"variableRateKey": "hourlyPricingRealTimePJM",
"variableRateSubKey": "51291",
"timeOfUse": {
"touId": 637
},
"rateBands": [{
"hasConsumptionLimit": true,
"consumptionUpperLimit": 10,
"rateAmount": "0.04",
"rateUnit": "BLOCK",
"isCredit": false
}, {
"hasConsumptionLimit": true,
"rateAmount": null,
"rateUnit": "COST_PER_UNIT",
"isCredit": false
}]
}]
}
Block and Index Rates with Sellback Rates
Some block and index contracts allow the customer to sell any unused kWh back to their energy supplier at the index price. This is called a “sellback” provision. In these contracts, the customer pays the block price and receives a credit for any unused kWh at the index price. The same index price will be used for both kWh in excess of the block and crediting unused kWh within the block.
To create a callback block and index rate, you mirror the rate structure of a standard block and index rate but with a different rate unit: BLOCK_SELL_BACK
.
Here’s an example (again, just the rateInputs
snippet of the full calculator request:
Updated 4 months ago