{"openapi":"3.1.0","info":{"title":"PowerUsage Calculation API","version":"1.0.0","description":"Public, no-auth electricity cost calculation endpoints. Supply an inline rate (flat and/or time-of-use) or a location code, plus device usage, and get daily/monthly/annual costs. Shared rate limit: 60 requests/minute per IP."},"servers":[{"url":"https://powerusage.app/calc"}],"paths":{"/api/cost":{"post":{"summary":"Device electricity cost (daily/monthly/annual)","description":"Computes cost for a device. Mode is auto-selected: power_states > annual_kwh > flat/TOU. Supply a rate via rateConfig (inline flat + optional TOU tiers) OR regionCode (DB lookup).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostRequest"}}}},"responses":{"200":{"description":"Cost breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"region_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/shift-savings":{"post":{"summary":"Optimal TOU run window for a shiftable device","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostRequest"}}}},"responses":{"200":{"description":"Savings, or {message,savings} when no TOU data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShiftSavingsResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/arbitrage":{"post":{"summary":"Battery charge/discharge arbitrage value","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArbitrageRequest"}}}},"responses":{"200":{"description":"Per-cycle and aggregate savings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArbitrageResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/battery-cost":{"post":{"summary":"Charging cost for consumer electronics or an EV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatteryCostRequest"}}}},"responses":{"200":{"description":"Charging cost","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatteryCostResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"region_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/battery-run-time":{"post":{"summary":"Runtime of a battery under a fixed load","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatteryRunTimeRequest"}}}},"responses":{"200":{"description":"Estimated runtime","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatteryRunTimeResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/battery-charge-tou":{"post":{"summary":"Cheapest TOU window to charge a battery","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatteryChargeTouRequest"}}}},"responses":{"200":{"description":"Optimal charge window and per-hour costs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatteryChargeTouResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"region_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/rates/{regionCode}":{"get":{"summary":"Full rate dataset for a location","parameters":[{"name":"regionCode","in":"path","required":true,"schema":{"type":"string"},"description":"Location code, e.g. US-CA."},{"name":"appVersion","in":"query","required":false,"schema":{"type":"string"},"description":"Logged for analytics."}],"responses":{"200":{"description":"Rate dataset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateDataset"}}}},"404":{"description":"region_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/rates/index":{"get":{"summary":"Slim list of all locations","responses":{"200":{"description":"Location list (cached 1h)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RateIndexItem"}}}}}}}},"/api/rates/nearest":{"get":{"summary":"Rate dataset for the closest utility to coordinates","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}}],"responses":{"200":{"description":"Rate dataset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateDataset"}}}},"400":{"description":"Missing or out-of-range params","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"no_locations_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/rates/lookup":{"get":{"summary":"Rate candidates near coordinates (DB or OpenEI fallback)","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}}],"responses":{"200":{"description":"Candidate list with source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLookupResponse"}}}},"400":{"description":"Invalid params","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}}},"TouTier":{"type":"object","required":["start_hour","end_hour","rate"],"properties":{"name":{"type":"string","description":"Label, e.g. peak / off-peak."},"start_hour":{"type":"integer","description":"Tier start hour (0–23)."},"end_hour":{"type":"integer","description":"Tier end hour (1–24)."},"rate":{"type":"number","description":"$/kWh during this window."}}},"RateConfig":{"type":"object","required":["flat_rate"],"description":"Inline rate. Use this OR regionCode.","properties":{"flat_rate":{"type":"number","description":"$/kWh flat rate (used when no TOU tier covers an hour)."},"currency":{"type":"string","default":"USD"},"tou_tiers":{"type":"array","items":{"$ref":"#/components/schemas/TouTier"}}}},"SolarConfig":{"type":"object","description":"Optional solar offset. mode=daily uses a fixed window; mode=hourly uses a per-hour production profile with export credit.","properties":{"mode":{"type":"string","enum":["daily","hourly"]},"window":{"type":"object","properties":{"start":{"type":"integer","description":"Hour solar begins (0–23)."},"end":{"type":"integer","description":"Hour solar ends (1–24, > start)."},"rate":{"type":"number","description":"Optional override rate for solar hours (default 0)."}}},"production_kw":{"type":"object","additionalProperties":{"type":"number"},"description":"hourly mode: hour (0–23) → kW output."},"export_rate":{"type":"number","description":"hourly mode: $/kWh credit for exported solar."}}},"Device":{"type":"object","description":"Usage profile. For flat/TOU mode supply watts + hours_per_day (+ optional schedule). annual_kwh mode uses kwh_per_use + uses_per_week. power_states mode uses a state array.","properties":{"watts":{"type":"number","description":"Power draw in watts. Required for flat/TOU mode."},"hours_per_day":{"type":"number","description":"Hours run per day (1–24). Required for flat/TOU mode."},"schedule":{"type":"array","description":"Run windows as [start_hour, end_hour] tuples. end_hour may exceed 24 for overnight windows (e.g. [22,30] = 10pm–6am). When the rate has tou_tiers, providing a schedule enables TOU pricing.","items":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2}},"kwh_per_use":{"type":"number","description":"annual_kwh mode: energy per use. Pair with uses_per_week. TOU not applied."},"uses_per_week":{"type":"number"},"shiftable":{"type":"boolean","description":"Required true for /api/shift-savings."},"power_states":{"type":"array","description":"Multi-state profile; one state must set is_remainder:true. Takes priority over other modes.","items":{"type":"object","properties":{"watts":{"type":"number"},"hours_per_week":{"type":"number"},"is_remainder":{"type":"boolean"}}}},"metadata":{"type":"object","description":"Freeform. metadata.quantity multiplies all outputs (default 1)."}}},"CostRequest":{"type":"object","required":["device"],"properties":{"device":{"$ref":"#/components/schemas/Device"},"regionCode":{"type":"string","description":"Location code for DB rate lookup, e.g. US-CA. Provide this OR rateConfig."},"rateConfig":{"$ref":"#/components/schemas/RateConfig"},"solarConfig":{"$ref":"#/components/schemas/SolarConfig"}}},"CostResponse":{"type":"object","properties":{"daily_cost":{"type":"number"},"monthly_cost":{"type":"number"},"annual_cost":{"type":"number"},"kwh_per_day":{"type":"number"},"currency":{"type":"string"},"mode":{"type":"string","enum":["flat","tou","annual_kwh","power_states"]},"tou_note":{"type":"string"},"export_credit":{"type":["object","null"],"properties":{"daily":{"type":"number"},"monthly":{"type":"number"},"annual":{"type":"number"}}}}},"ShiftSavingsResponse":{"type":"object","description":"Either savings fields, or { message:'no_tou_data', savings:0 } when the location has no TOU tiers.","properties":{"current_cost":{"type":"number"},"optimal_cost":{"type":"number"},"optimal_window":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"annual_savings":{"type":"number"},"currency":{"type":"string"},"message":{"type":"string"},"savings":{"type":"number"}}},"ArbitrageRequest":{"type":"object","required":["battery_wh","charge_rate","discharge_rate"],"properties":{"battery_wh":{"type":"number","description":"Battery capacity in Wh."},"charge_rate":{"type":"number","description":"$/kWh paid to charge."},"discharge_rate":{"type":"number","description":"$/kWh value when discharging."},"dod_percent":{"type":"number","description":"Depth of discharge 1–100 (default 80)."},"round_trip_efficiency":{"type":"number","description":"0–1 (default 0.90)."},"cycles_per_month":{"type":"number","description":"Default 30."}}},"ArbitrageResponse":{"type":"object","properties":{"usable_kwh":{"type":"number"},"kwh_out":{"type":"number"},"cost_to_charge":{"type":"number"},"value_of_discharge":{"type":"number"},"net_per_cycle":{"type":"number"},"monthly_savings":{"type":"number"},"annual_savings":{"type":"number"}}},"BatteryCostRequest":{"type":"object","required":["mode"],"description":"Supply rate via rate_per_kwh OR regionCode. mode=electronics needs wh or mah + charges_per_week. mode=ev needs battery_kwh, miles_per_month, efficiency_mi_per_kwh.","properties":{"mode":{"type":"string","enum":["electronics","ev"]},"regionCode":{"type":"string"},"rate_per_kwh":{"type":"number"},"wh":{"type":"number","description":"electronics: capacity in Wh (provide wh or mah)."},"mah":{"type":"number","description":"electronics: capacity in mAh."},"voltage_v":{"type":"number","description":"electronics: cell voltage for mAh→Wh (default 3.7)."},"charges_per_week":{"type":"number"},"depth_of_discharge":{"type":"number","description":"1–100 (default 100)."},"battery_kwh":{"type":"number","description":"ev: full battery capacity."},"miles_per_month":{"type":"number"},"efficiency_mi_per_kwh":{"type":"number"}}},"BatteryCostResponse":{"type":"object","description":"Fields present depend on mode.","properties":{"wh_per_charge":{"type":"number"},"kwh_per_charge":{"type":"number"},"cost_per_charge":{"type":"number"},"cost_per_mile":{"type":"number"},"cost_per_full_charge":{"type":"number"},"monthly_cost":{"type":"number"},"annual_cost":{"type":"number"},"currency":{"type":"string"},"mode":{"type":"string","enum":["electronics","ev"]}}},"BatteryRunTimeRequest":{"type":"object","required":["wh","load_watts"],"properties":{"wh":{"type":"number","description":"Battery capacity in Wh."},"load_watts":{"type":"number","description":"Constant load in watts."},"dod_percent":{"type":"number","description":"1–100 (default 80)."},"efficiency_factor":{"type":"number","description":"0–1 (default 0.90)."}}},"BatteryRunTimeResponse":{"type":"object","properties":{"usable_wh":{"type":"number"},"run_time_hours":{"type":"number"},"run_time_minutes":{"type":"number"}}},"BatteryChargeTouRequest":{"type":"object","required":["wh","charge_rate_watts"],"description":"Supply rate via rate_per_kwh, rateConfig, OR regionCode.","properties":{"wh":{"type":"number","description":"Battery capacity in Wh."},"charge_rate_watts":{"type":"number","description":"Charger power in watts."},"dod_percent":{"type":"number","description":"1–100 (default 80)."},"rate_per_kwh":{"type":"number"},"rateConfig":{"$ref":"#/components/schemas/RateConfig"},"regionCode":{"type":"string"}}},"BatteryChargeTouResponse":{"type":"object","properties":{"kwh_to_charge":{"type":"number"},"charge_hours":{"type":"number"},"optimal_start_hour":{"type":"integer"},"optimal_cost":{"type":"number"},"worst_cost":{"type":"number"},"average_cost":{"type":"number"},"savings_vs_worst":{"type":"number"},"windows":{"type":"array","items":{"type":"object","properties":{"start_hour":{"type":"integer"},"cost":{"type":"number"}}}},"currency":{"type":"string"}}},"RateDataset":{"type":"object","properties":{"region_code":{"type":"string"},"name":{"type":"string"},"currency":{"type":"string"},"flat_rate":{"type":"number"},"version":{"type":"string"},"updated_at":{"type":"string"},"tou_tiers":{"type":"array","items":{"$ref":"#/components/schemas/TouTier"}}}},"RateIndexItem":{"type":"object","properties":{"region_code":{"type":"string"},"name":{"type":"string"},"flat_rate":{"type":"number"},"currency":{"type":"string"},"has_tou":{"type":"boolean"}}},"RateLookupResponse":{"type":"object","properties":{"source":{"type":"string","enum":["db","cache","openei","none"]},"candidates":{"type":"array","items":{"type":"object"}}}}}}}