Skip to content

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 variableRateKey values
  • 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:

  1. Match the territory: If you queried marketSupplyChargeResidentialZoneJ via Lookups, use territoryId: 3634 in Calculate

  2. Match applicability conditions: Some rates only apply in certain scenarios:

  3. CBC only appears if systemSize > 0
  4. Supply charges only appear if customer uses ConEd supply (not ESCO)

  5. Cross-reference by rate name: The Calculate API uses tariffRateName which matches the rateName in 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.