JouloDocs

Home Assistant

Integrate Joulo charger data into your Home Assistant smart home setup

Joulo's API works with Home Assistant's RESTful sensor integration. Add your charger status, active session data, and energy totals as sensors in your HA dashboard • and restart a hung charger remotely via a rest_command.

Prerequisites

  • A Joulo account with at least one connected charger
  • An active API token (generate one from Developer → API in the dashboard)
  • Home Assistant with access to edit configuration.yaml

Configuration

Add the following to your configuration.yaml. Replace YOUR_API_TOKEN with your actual token.

For convenience, store your token in secrets.yaml:

joulo_api_auth: "Bearer YOUR_API_TOKEN"

Here joulo_api_auth is only the name of the secret. The value is the word Bearer, a space, and your token exactly as shown in the dashboard • the token itself does not start with joulo_, so don't add that prefix.

Then add the following to configuration.yaml:

rest:
  - resource: https://api.joulo.nl/functions/v1/api/chargers
    scan_interval: 60
    headers:
      Authorization: !secret joulo_api_auth
    sensor:
      - name: "Joulo Charger Status"
        unique_id: joulo_charger_status
        value_template: >-
          {{ value_json.chargers[0].status | default('unknown') }}
      - name: "Joulo Is Charging"
        unique_id: joulo_is_charging
        value_template: "{{ value_json.chargers[0].is_charging | default(false) }}"
      - name: "Joulo Session kWh"
        unique_id: joulo_session_kwh
        value_template: >-
          {% set s = value_json.chargers[0].current_session | default(none) %}
          {{ (s.kwh_so_far if s else 0) | float(0) }}
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total_increasing
      # Indicative net euro value of the active session. 0 when idle.
      - name: "Joulo Session Earnings"
        unique_id: joulo_session_earnings
        value_template: >-
          {% set s = value_json.chargers[0].current_session | default(none) %}
          {{ (s.estimated_euro if s and s.estimated_euro is not none else 0) | float(0) }}
        unit_of_measurement: "EUR"
        device_class: monetary
      # RFID card or token that started the active session. Empty when idle.
      # evcc can use it to identify the vehicle, see the EVCC guide.
      - name: "Joulo Active TAG ID"
        unique_id: joulo_active_tag_id
        value_template: >-
          {% set s = value_json.chargers[0].current_session | default(none) %}
          {{ s.id_tag if s and s.id_tag else '' }}

  - resource: https://api.joulo.nl/functions/v1/api/energy
    scan_interval: 3600
    headers:
      Authorization: !secret joulo_api_auth
    sensor:
      - name: "Joulo Total kWh"
        unique_id: joulo_total_kwh
        value_template: "{{ value_json.total_kwh_all | float(0) }}"
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total_increasing
      - name: "Joulo Total ERE"
        unique_id: joulo_total_ere
        value_template: "{{ value_json.total_ere_credits | float(0) }}"
        state_class: total_increasing

  - resource: https://api.joulo.nl/functions/v1/api/ere-position
    scan_interval: 3600
    headers:
      Authorization: !secret joulo_api_auth
    sensor:
      # Sold ERE that has not reached your bank account yet:
      # payable (buyer has paid) plus reserved (sold, buyer still to pay).
      - name: "Joulo Awaiting Payout"
        unique_id: joulo_awaiting_payout
        value_template: >-
          {{ ((value_json.payable.net_eur | float(0))
            + (value_json.reserved.net_eur | float(0))) | round(2) }}
        unit_of_measurement: "EUR"
        device_class: monetary

Every sensor has a unique_id. Without one, Home Assistant cannot register the entity, so you cannot rename it in the UI and a YAML reload can leave a duplicate such as sensor.joulo_session_kwh_2. Keep the IDs stable once you use them in automations or the energy dashboard.

The session sensors bind current_session to s first. Read it directly as value_json.chargers[0].current_session.id_tag and the template fails on every poll while no session runs. Jinja raises there before default() can catch anything.

Authentication only works via the Authorization: Bearer header. The previously documented ?token= query parameter is no longer accepted and will return 401.

Sensors explained

SensorSourcePoll intervalDescription
Joulo Charger Status/chargers60sConnection status of your first charger
Joulo Is Charging/chargers60sBoolean • whether the charger is actively charging
Joulo Session kWh/chargers60sEnergy delivered in the current session (0 if not charging)
Joulo Session Earnings/chargers60sIndicative net euro value of the current session (0 if not charging). A forecast, not a payout
Joulo Active TAG ID/chargers60sCard or token that started the active session, for evcc
Joulo Total kWh/energy1hLifetime total energy across all chargers (total_kwh_all, including non-MID)
Joulo Total ERE/energy1hLifetime total ERE-credits earned (MID-eligible chargers only)
Joulo Awaiting Payout/ere-position1hNet euros from sold ERE that you have not received yet (payable + reserved)

Multiple chargers

If you have more than one charger, adjust the array index in the templates. For example, your second charger would use value_json.chargers[1].status.

For a more robust setup, you can create a template sensor that finds a charger by nickname:

template:
  - sensor:
      - name: "Garage Charger Status"
        state: >-
          {% set charger = value_json.chargers | selectattr('nickname', 'equalto', 'Garage') | first %}
          {{ charger.status if charger else 'unknown' }}

Energy dashboard

To add Joulo energy data to the Home Assistant energy dashboard, use the Joulo Total kWh sensor as a "Grid consumption" or custom energy source. Since it reports a monotonically increasing total, HA can calculate daily/monthly usage automatically.

Set scan_interval for the /energy endpoint to 3600 (1 hour) or higher • the data is aggregated monthly and doesn't change frequently.

Restart your charger remotely

POST /chargers/reboot sends an OCPP Reset to your charger through Joulo's backend • handy when the charge point hangs and you would otherwise have to flip the breaker. It works for chargers connected via OCPP (including the Joulo Proxy). An active charging session will be stopped.

First find your charger's id:

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  https://api.joulo.nl/functions/v1/api/chargers

Then define a rest_command in configuration.yaml:

rest_command:
  joulo_reboot_charger:
    url: https://api.joulo.nl/functions/v1/api/chargers/reboot
    method: POST
    headers:
      Authorization: !secret joulo_api_auth
    content_type: "application/json"
    payload: '{"charger_id": "YOUR_CHARGER_ID", "type": "Soft"}'

Call it from a dashboard button:

type: button
name: Restart charger
icon: mdi:restart
tap_action:
  action: call-service
  service: rest_command.joulo_reboot_charger
  confirmation:
    text: Restart the charger? An active session will be stopped.

Good to know:

  • type is "Soft" (default • the charger ends an active session gracefully, then restarts) or "Hard" (immediate full reboot, for when Soft doesn't help).
  • Delivery is live-only over the charger's OCPP connection. If the charger is offline the API returns 409 • nothing is queued for later.
  • Reboots are rate-limited per charger (a burst of 2, then one per 5 minutes), so a misfiring automation can't hold your charger in a boot loop.

Avoid triggering the reboot from an automation on flaky signals (such as "when a sensor becomes unavailable"). Combine conditions and add a cooldown so a temporary API hiccup doesn't restart your charger mid-session.