Retrieving Variable Rate Values from Arcadia APIs
⚠️ Disclaimer: This guide was generated by an LLM (Claude Opus 4.5) based on Arcadia API documentation and the model's understanding of the API structure. The content looks reasonable but has not been verified by domain experts. Please verify any claims and test API calls before relying on them for production use.
You Have a Tariff—Now What?
You downloaded a tariff (like ConEd EL1) and see rates with variableRateKey:
{
"rateName": "MSC Rate - Zone J",
"rateAmount": 0.0,
"variableRateKey": "marketSupplyChargeResidentialZoneJ"
}
The rateAmount: 0.0 is a placeholder. The actual values change over time (monthly, in most cases). To get them, you have two options:
| Approach | How It Works | What You Get |
|---|---|---|
| Lookups API | Extract variableRateKey values from tariff → query each one |
Raw rate values, exactly what you asked for |
| Calculate API | Use tariff metadata to set up a billing scenario → run calculation | All applicable rates resolved for that scenario |
Key difference: These approaches don't always give the same results.
⚠️ Important: The Two Approaches Are Not Equivalent
Lookups API = Raw Data, You Control What You Query
- You explicitly request specific
variableRateKeyvalues - You get exactly those values, regardless of whether they apply to a specific customer
- Zone H, Zone I, Zone J rates? You can query all of them
- Solar-only rates? You get them even if you're not modeling a solar customer
Calculate API = Scenario-Based, API Filters for Applicability
- You specify a billing scenario: territory, consumption, solar system size, etc.
- The API returns only rates that apply to that scenario
- Zone J customer? You only get Zone J rates
- No solar (
systemSize: 0)? You won't get the CBC charge
When Results Match
If you:
1. Query Lookups for only the variableRateKey values that apply to your scenario
2. Use Calculate with the same scenario parameters
...you'll get the same variable rate values.
When Results Differ
| Scenario | Lookups API | Calculate API |
|---|---|---|
| Query all zone-specific MSC rates | Returns H, I, and J values | Returns only the zone you specified |
| Customer without solar | Returns CBC rate if you query it | Won't include CBC (doesn't apply) |
| Query a key that doesn't apply | Returns data anyway | Won't appear in results |
Bottom line: Lookups gives you raw data; Calculate gives you scenario-specific data.
Workflow: From Tariff to Variable Rates
Method 1: Lookups API
Step 1: Extract all variableRateKey values from the tariff
Parse the tariff JSON and collect every unique variableRateKey:
import json
def extract_variable_rate_keys(tariff_json):
"""Extract all variableRateKey values from a tariff."""
keys = set()
for tariff in tariff_json:
for rate in tariff.get('rates', []):
if 'variableRateKey' in rate:
keys.add(rate['variableRateKey'])
return list(keys)
# Load your tariff
with open('coned_el1_tariff.json') as f:
tariff = json.load(f)
variable_keys = extract_variable_rate_keys(tariff)
print(f"Found {len(variable_keys)} variable rate keys")
For ConEd EL1, this returns keys like:
[
"marketSupplyChargeResidentialZoneH",
"marketSupplyChargeResidentialZoneI",
"marketSupplyChargeResidentialZoneJ",
"mscIResidentialWestchester2252",
"mscIResidentialNewYork2252",
"mscIIAdjustmentFactor",
"monthlyAdjustmentClauseResidential",
# ... 15+ more
]
Step 2: Query Lookups API for each key
import requests
def get_lookups(property_key, from_date, to_date, api_key):
"""Get lookup values for a single variableRateKey."""
response = requests.get(
f"https://api.arcadia.com/rest/public/properties/{property_key}/lookups",
params={
"fromDateTime": from_date,
"toDateTime": to_date
},
headers={"Authorization": f"Bearer {api_key}"}
)
return response.json().get('results', [])
# Get 2024 data for all keys
all_lookups = {}
for key in variable_keys:
all_lookups[key] = get_lookups(
key,
"2024-01-01T00:00:00-05:00",
"2025-01-01T00:00:00-05:00",
"YOUR_API_KEY"
)
print(f"Retrieved data for {len(all_lookups)} variable rates")
Step 3: Organize by time period
def organize_by_month(all_lookups):
"""Reorganize lookup data by month."""
monthly = {}
for key, entries in all_lookups.items():
for entry in entries:
# Extract month from fromDateTime
month = entry['fromDateTime'][:7] # "2024-01"
if month not in monthly:
monthly[month] = {}
monthly[month][key] = entry['bestValue']
return monthly
monthly_rates = organize_by_month(all_lookups)
# Result:
# {
# "2024-01": {"marketSupplyChargeResidentialZoneJ": 0.0823, ...},
# "2024-02": {"marketSupplyChargeResidentialZoneJ": 0.0791, ...},
# ...
# }
Calls required: One per variableRateKey (typically 15-20 for ConEd EL1)
Method 2: Calculate API
Step 1: Extract scenario parameters from the tariff
The tariff tells you what parameters the Calculate API needs:
def get_calculate_params(tariff_json):
"""Extract parameters needed for Calculate API from tariff."""
tariff = tariff_json[0] # First tariff in array
return {
"masterTariffId": tariff['masterTariffId'],
"lseId": tariff['lseId'],
# Get available territories from properties
"territories": [
choice['value']
for prop in tariff.get('properties', [])
if prop['keyName'] == 'territoryId'
for choice in prop.get('choices', [])
]
}
params = get_calculate_params(tariff)
# Result:
# {
# "masterTariffId": 809,
# "lseId": 2252,
# "territories": ["3632", "3633", "3634"] # H, I, J
# }
Step 2: Call Calculate API for each billing period
def calculate_bill(master_tariff_id, territory_id, from_date, to_date, consumption, api_key):
"""Run a bill calculation and return line items."""
response = requests.post(
"https://api.arcadia.com/rest/public/calculate",
json={
"masterTariffId": master_tariff_id,
"fromDateTime": from_date,
"toDateTime": to_date,
"territoryId": int(territory_id),
"detailLevel": "CHARGE_TYPE_AND_TOU",
"propertyInputs": [
{"keyName": "consumption", "dataValue": consumption}
]
},
headers={"Authorization": f"Bearer {api_key}"}
)
return response.json()
# Get 2024 data for Zone J
monthly_results = {}
for month in range(1, 13):
from_date = f"2024-{month:02d}-01"
to_date = f"2024-{month+1:02d}-01" if month < 12 else "2025-01-01"
result = calculate_bill(
master_tariff_id=809,
territory_id=3634, # Zone J
from_date=from_date,
to_date=to_date,
consumption=500, # Arbitrary—we just want rate values
api_key="YOUR_API_KEY"
)
monthly_results[f"2024-{month:02d}"] = result
Step 3: Extract rate values from responses
def extract_rate_values(calculate_response):
"""Extract rate values from Calculate API response."""
rates = {}
for item in calculate_response['results'][0]['items']:
rate_name = item['tariffRateName']
rate_amount = item['rateAmount']
rates[rate_name] = rate_amount
return rates
monthly_rates = {
month: extract_rate_values(result)
for month, result in monthly_results.items()
}
# Result:
# {
# "2024-01": {"Customer Charge": 20.0, "MSC Rate - Zone J": 0.0823, ...},
# "2024-02": {"Customer Charge": 20.0, "MSC Rate - Zone J": 0.0791, ...},
# ...
# }
Calls required: One per billing period (12 for a year of monthly data)
Filtering Calculate API Results to Just Variable Rates
The Calculate API returns ALL charges (fixed and variable). To get just variable rates, cross-reference with the tariff:
def filter_to_variable_rates(tariff_json, calculate_response):
"""Filter Calculate results to only variable rates."""
# Build set of rate names that have variableRateKey
variable_rate_names = set()
for tariff in tariff_json:
for rate in tariff.get('rates', []):
if 'variableRateKey' in rate:
variable_rate_names.add(rate['rateName'])
# Filter calculate results
all_rates = extract_rate_values(calculate_response)
variable_only = {
name: value
for name, value in all_rates.items()
if name in variable_rate_names
}
return variable_only
Can Calculate API Give the Same Results as Lookups?
Short answer: Yes, but only if you're careful about scenario matching.
To Get Equivalent Results:
-
Match the territory: If you queried
marketSupplyChargeResidentialZoneJvia Lookups, useterritoryId: 3634in Calculate -
Match applicability conditions: Some rates only apply in certain scenarios:
- CBC only appears if
systemSize > 0 -
Supply charges only appear if customer uses ConEd supply (not ESCO)
-
Cross-reference by rate name: The Calculate API uses
tariffRateNamewhich matches therateNamein the tariff JSON
What Calculate API Cannot Do:
- Return rates for multiple zones in one call: You must call once per territory
- Return rates that don't apply to your scenario: If you set
systemSize: 0, you won't get CBC - Give you forecast vs. actual breakdown: Lookups has
bestValue,actualValue,forecastValue; Calculate just gives you the resolved value
When to Use Each:
| Goal | Use |
|---|---|
| Get all variable rates for a specific customer scenario | Calculate API |
| Get one rate's full history with forecast/actual breakdown | Lookups API |
| Discover what variable rates exist without knowing keys | Calculate API |
| Get raw data regardless of applicability | Lookups API |
API Reference Summary
Lookups API
Endpoint: GET /rest/public/properties/{propertyKey}/lookups
Parameters:
| Parameter | Required | Description |
|---|---|---|
propertyKey |
Yes | The variableRateKey |
fromDateTime |
Recommended | Start of date range (ISO 8601) |
toDateTime |
Recommended | End of date range (ISO 8601) |
Default date behavior: Last 72 hours if not specified.
Response fields:
- bestValue: Use this (best available value)
- actualValue: Finalized value (may be null)
- forecastValue: Arcadia's forecast
- lseForecastValue: Utility's forecast
Calculate API
Endpoint: POST /rest/public/calculate
Key request fields:
| Field | Required | Description |
|---|---|---|
masterTariffId |
Yes | From tariff JSON |
fromDateTime |
Yes | Billing period start |
toDateTime |
Yes | Billing period end |
territoryId |
Depends | Required if tariff has multiple territories |
detailLevel |
Yes | Use CHARGE_TYPE_AND_TOU or RATE |
propertyInputs |
Yes | At minimum, consumption |
Response structure:
- results[0].items[]: Array of line items
- Each item has tariffRateName, rateAmount, itemQuantity, cost
Lookup Stats API
Endpoint: GET /rest/public/properties/{propertyKey}/stats
Returns: Date range available, count, mean value, last updated date.
Complete Example: 2024 Variable Rates, Both Methods
Setup
import json
import requests
from datetime import datetime
API_KEY = "YOUR_API_KEY"
TARIFF_FILE = "coned_el1_tariff.json"
with open(TARIFF_FILE) as f:
tariff = json.load(f)
Method 1: Lookups API
# Extract variable rate keys
variable_keys = []
for t in tariff:
for rate in t.get('rates', []):
if 'variableRateKey' in rate:
variable_keys.append({
'key': rate['variableRateKey'],
'name': rate['rateName']
})
# Deduplicate
unique_keys = {k['key']: k['name'] for k in variable_keys}
# Query each key
lookups_results = {}
for key, name in unique_keys.items():
response = requests.get(
f"https://api.arcadia.com/rest/public/properties/{key}/lookups",
params={
"fromDateTime": "2024-01-01T00:00:00-05:00",
"toDateTime": "2025-01-01T00:00:00-05:00"
},
headers={"Authorization": f"Bearer {API_KEY}"}
)
lookups_results[name] = response.json().get('results', [])
print(f"Lookups API: {len(unique_keys)} calls made")
Method 2: Calculate API (Zone J)
calculate_results = {}
for month in range(1, 13):
from_date = f"2024-{month:02d}-01"
to_date = f"2024-{month+1:02d}-01" if month < 12 else "2025-01-01"
response = requests.post(
"https://api.arcadia.com/rest/public/calculate",
json={
"masterTariffId": 809,
"fromDateTime": from_date,
"toDateTime": to_date,
"territoryId": 3634,
"detailLevel": "CHARGE_TYPE_AND_TOU",
"propertyInputs": [
{"keyName": "consumption", "dataValue": 500}
]
},
headers={"Authorization": f"Bearer {API_KEY}"}
)
calculate_results[f"2024-{month:02d}"] = response.json()
print(f"Calculate API: 12 calls made")
Compare Results
# Get January 2024 MSC Rate - Zone J from both methods
# From Lookups
for entry in lookups_results.get("MSC Rate - Zone J", []):
if entry['fromDateTime'].startswith("2024-01"):
print(f"Lookups API: {entry['bestValue']}")
# From Calculate
for item in calculate_results["2024-01"]['results'][0]['items']:
if item['tariffRateName'] == "MSC Rate - Zone J":
print(f"Calculate API: {item['rateAmount']}")
# These should match!
Summary
| Aspect | Lookups API | Calculate API |
|---|---|---|
| Input needed | variableRateKey from tariff |
masterTariffId, territoryId, consumption |
| Output | Raw rate values with forecast/actual | Resolved rates for specific scenario |
| Calls for 1 year, all rates | ~16 (one per key) | 12 (one per month) |
| Includes non-applicable rates | Yes (if you query them) | No (filtered by scenario) |
| Forecast vs. actual breakdown | Yes | No |
| Discovers rates for you | No (you must know keys) | Yes (returns all applicable) |
Use Lookups when: You know exactly which rates you want and need raw historical data.
Use Calculate when: You want all applicable rates for a billing scenario without knowing the keys upfront.