PowerUsage

← Docs

Cost Calculation API

Public, no-auth endpoints to compute electricity costs from a rate, wattage, and usage schedule.

The calculation API is public — no authentication required. Give it a rate (flat and/or time-of-use) plus device usage, and it returns daily, monthly, and annual costs. Ideal for scripts and agents.

Looking for your tracked devices and profile? That's the authenticated API Guide (/api/v1, requires an API token). This page covers the public calculation endpoints.

Base URL: https://powerusage.app/calc

Machine-readable spec: /api/openapi.json — OpenAPI 3.1. Point any agent/LLM tooling at it to auto-generate a calling contract.

Rate limit: 60 requests/minute. Exceeding returns HTTP 429 with a Retry-After header.


POST /api/cost

Daily/monthly/annual cost for a device.

Rate input — pick one:

  • rateConfig — inline rate: { "flat_rate": 0.15, "currency": "USD", "tou_tiers": [...] }
  • regionCode — DB lookup by location code, e.g. "US-CA"

Usage input (device) — mode auto-selected:

  • flat / TOU: watts + hours_per_day (+ optional schedule). With schedule and a rate that has tou_tiers, pricing is computed per TOU tier.
  • annual_kwh: kwh_per_use + uses_per_week (TOU not applied).
  • power_states: a power_states array (multi-state profile).

schedule is an array of [start_hour, end_hour] tuples. end_hour can exceed 24 for overnight windows — [22, 30] means 10 pm–6 am.

Example: rate + wattage + schedule → daily/monthly/yearly

curl -s https://powerusage.app/calc/api/cost \
  -H "Content-Type: application/json" \
  -d '{
    "device": { "watts": 100, "hours_per_day": 8, "schedule": [[22, 30]] },
    "rateConfig": {
      "flat_rate": 0.15,
      "currency": "USD",
      "tou_tiers": [
        { "name": "off-peak", "start_hour": 0, "end_hour": 9,  "rate": 0.12 },
        { "name": "peak",     "start_hour": 9, "end_hour": 24, "rate": 0.30 }
      ]
    }
  }'

Example: simple flat rate + wattage

curl -s https://powerusage.app/calc/api/cost \
  -H "Content-Type: application/json" \
  -d '{
    "device": { "watts": 100, "hours_per_day": 8 },
    "rateConfig": { "flat_rate": 0.15 }
  }'

Response:

{
  "daily_cost": 0.12,
  "monthly_cost": 3.65,
  "annual_cost": 43.8,
  "kwh_per_day": 0.8,
  "currency": "USD",
  "mode": "flat"
}
Field Description
daily_cost / monthly_cost / annual_cost Cost over each period (rounded to 4 decimals)
kwh_per_day Energy consumed per day
currency Currency code
mode flat, tou, annual_kwh, or power_states
tou_note Present when TOU data exists but couldn't be applied

POST /api/shift-savings

Cheapest continuous run window for a shiftable device on a TOU rate. Same body as /api/cost; device.shiftable must be true with watts + hours_per_day.

curl -s https://powerusage.app/calc/api/shift-savings \
  -H "Content-Type: application/json" \
  -d '{
    "device": { "watts": 1500, "hours_per_day": 3, "shiftable": true },
    "regionCode": "US-CA"
  }'

Returns { "current_cost", "optimal_cost", "optimal_window", "annual_savings", "currency" }, or { "message": "no_tou_data", "savings": 0 } when the location has no TOU tiers.


POST /api/battery-cost

Charging cost for consumer electronics or an EV. Supply rate_per_kwh or regionCode.

curl -s https://powerusage.app/calc/api/battery-cost \
  -H "Content-Type: application/json" \
  -d '{ "mode": "ev", "battery_kwh": 75, "miles_per_month": 1000, "efficiency_mi_per_kwh": 4, "rate_per_kwh": 0.15 }'

POST /api/arbitrage

Per-cycle and aggregate savings from charging a battery cheap and discharging when power is expensive.

curl -s https://powerusage.app/calc/api/arbitrage \
  -H "Content-Type: application/json" \
  -d '{ "battery_wh": 13500, "charge_rate": 0.12, "discharge_rate": 0.40 }'

GET rate data

  • GET /api/rates/{regionCode} — full rate dataset (flat rate + TOU tiers) for a location.
  • GET /api/rates/index — slim list of all locations.
curl -s https://powerusage.app/calc/api/rates/US-CA

Errors

Status Body Meaning
400 { "error": "..." } Invalid or missing input
404 { "error": "region_not_found" } Unknown regionCode
429 { "error": "rate_limited", "retry_after": N } Rate limit exceeded; wait N seconds