Home Assistant setup
Seven sensors from one request every 15 minutes: the price now and tomorrow’s cheapest window for your car, heat pump or home battery. Part of the Personal plan and the paid plans above it — your API key is in your account.
1. Store your key
Add your API key to secrets.yaml in your Home Assistant configuration folder:
# secrets.yaml progrunners_key: YOUR_API_KEY
2. Add the REST sensors
Paste this into configuration.yaml, replace DE-LU with your zone code
(the code shown on your zone page, for example NL, AT or IT-North) and restart Home Assistant.
hours sets the length of the cheapest window, 1 to 12 hours.
# configuration.yaml
rest:
- resource: https://progrunners.com/api/v1/summary?zone=DE-LU&hours=3
headers:
X-API-Key: !secret progrunners_key
scan_interval: 900
sensor:
- name: "Power price now"
unique_id: progrunners_price_now
value_template: "{{ value_json.now.price if value_json.now else none }}"
unit_of_measurement: "EUR/MWh"
state_class: measurement
- name: "Power price now ct"
unique_id: progrunners_price_now_ct
value_template: "{{ (value_json.now.price / 10) | round(2) if value_json.now else none }}"
unit_of_measurement: "ct/kWh"
state_class: measurement
- name: "Cheapest window tomorrow"
unique_id: progrunners_cheapest_window
value_template: >-
{% if value_json.cheapest_window %}{{ value_json.cheapest_window.start_local }}–{{ value_json.cheapest_window.end_local }}{% else %}unknown{% endif %}
- name: "Next cheapest window start"
unique_id: progrunners_next_window_start
device_class: timestamp
value_template: "{{ value_json.next_window.start_utc if value_json.next_window else none }}"
- name: "Next cheapest window end"
unique_id: progrunners_next_window_end
device_class: timestamp
value_template: "{{ value_json.next_window.end_utc if value_json.next_window else none }}"
- name: "Cheapest window tomorrow average"
unique_id: progrunners_cheapest_avg
value_template: "{{ value_json.cheapest_window.average if value_json.cheapest_window else none }}"
unit_of_measurement: "EUR/MWh"
- name: "Power price tomorrow average"
unique_id: progrunners_tomorrow_avg
value_template: "{{ value_json.tomorrow.average }}"
unit_of_measurement: "EUR/MWh"
Prices are wholesale day-ahead prices in EUR/MWh (Great Britain: GBP/MWh), before grid charges, taxes and your supplier’s margin.
10 EUR/MWh = 1 ct/kWh. Times: start_local and end_local are in the zone’s local time.
3. What the API returns
GET /v1/summary needs your key and returns the price of the current quarter-hour (the published auction price,
or our forecast where no price is published yet), tomorrow’s minimum, maximum and average, and the cheapest window tomorrow by our forecast — or by the
published prices once the auction has cleared (actual_published). Example:
{"zone": "DE-LU", "unit": "EUR/MWh", "timezone": "Europe/Berlin",
"created": "2026-11-07T10:34:12+01:00",
"now": {"time_utc": "2026-11-07T15:45:00Z", "price": 118.4, "actual": true},
"tomorrow": {"date": "2026-11-08", "quarters": 96, "min": 61.2, "max": 162.9,
"average": 104.7, "actual_published": false},
"cheapest_window": {"hours": 3, "start_local": "02:00", "end_local": "05:00",
"start_utc": "2026-11-08T01:00:00Z", "end_utc": "2026-11-08T04:00:00Z",
"average": 63.8},
"next_window": {"hours": 3, "start_local": "02:00", "end_local": "05:00",
"start_utc": "2026-11-08T01:00:00Z", "end_utc": "2026-11-08T04:00:00Z",
"average": 63.8}}
cheapest_window is the cheapest window within tomorrow (local time), for display. next_window is the cheapest window that starts
from the current quarter-hour up to the end of tomorrow — use it in automations, because it does not jump to the next day at midnight.
For a chart of the full tomorrow, call GET /v1/forecast?zone=… — every 15 minutes with the 10–90 % range. See the API reference.
4. Use it in an automation
Charge during the next cheapest window:
automation:
- alias: "Charge in the cheapest window"
trigger:
- platform: time
at: sensor.next_cheapest_window_start
id: "start"
- platform: time
at: sensor.next_cheapest_window_end
id: "end"
action:
- service: "switch.turn_{{ 'on' if trigger.id == 'start' else 'off' }}"
target:
entity_id: switch.ev_charger
Replace switch.ev_charger with your charger, heat pump or battery switch. Entity IDs follow the sensor names; check them under Settings → Entities.
The window can move when a newer forecast or the published auction prices arrive (around 13:00 CET); the sensors refresh every 15 minutes.