ENGIE (BE) - Custom integration for energy prices

Hi all, I needed accurate price data from ENGIE so I spent some time reverse-engineering their platform. I’m planning to publish my integration on HACS soon but I would like to have it tested by other people first.

A few things to note:

  • Currently, only 2FA via SMS and e-mail are supported. Passkeys and itsme support are off the table, not interested in touching those. I’m also not sure what will happen when ENGIE forces 2FA on all of their customers in March.

  • I was only able to test with Easy Variabel. The API call for prices uses MONTHLY for maxGranularity, so this might not be ideal for people with a dynamic contract.

  • ENGIE seems to be very strict with their access tokens: they get revoked after about 2 minutes, so the integration refreshes the token every minute in the background. There is a binary sensor to keep track of the authentication status.

  • The integration creates sensors for offtake and injection prices (both including and excluding VAT), per EAN. Injection sensors are only created when the data is available (e.g. gas will only have offtake).

For those interested in the login flow, I’ve included a Bruno collection in the repository.

Feel free to test this out by spinning up the devcontainer or by manually adding the ingration, all contributions and improvements are welcome :smile:

3 Likes

Hi, I tried the integration, but I’m stuck waiting on the SMS/e-mail code. When I log into Engie’s site , I never have to enter either one of those. Just e-mail & pwd…

Hi, that’s interesting… I was under the impression they would enforce 2FA starting on 02/03/2026. Are you not prompted to set up 2FA when you log in to engie.be?

I would recommend setting up a 2FA method (phone or email) via engie.be or the smart app. Once you do, the login flow for this integration will work. I’m not really planning to support the non-2FA login flow, since I’m sure they will make it mandatory at some point anyway :slightly_frowning_face:.

Hi, I don’t even get the option of setting up the 2FA when I log into engie.be or the smart app… :man_shrugging:
Guess I’ll have to wait a bit until it gets enforced for my account…

You can try adding a new separate user via https://www.engie.be/nl/energiedesk/usermanagement/manage-access, they might only enforce it for newer accounts.

Hello Daan,

Thanks for making this integration. I recently got into HA in my home and loving it so far, finding your recent integration was a real pleasure.

However, I can’t seem to configure it.
I honestly can’t remember if I had to setup 2FA on my Engie account. However when i go through your logging process, I can get an SMS or an email, so I guess it is activated for my account ? Yet, even when manually logging in into the Engie app or website, 2FA is not required, so I don’t know really…

Anyway, even if i enter the received SMS or email 2FA code, the integration provides me with an error message " Invalid username or password.". If I try again with the same 2FA code, I get " An unknown error occurred. "

Also, I used the customer number that I could find in my invoice. But in your integration, it has to start with 00, while my own customer number does not. Is it normal ?

1 Like

Update !
I created a new separate user in my Engie account, as you suggested, activated 2FA, and logged with it in your integration (with the same customer number starting with 2, instead of 00) and now it seems to work :slight_smile:

I guess 2FA was not “really” activated on my main account yet.

NB: the gas price in the integration is expressed in EUR/m3, but the price should be in EUR/kWh to be the same as what i can find on the Engie website with the current price for my contract.

If I could also suggest a small improvement, it would be to have an additional sensor providing current price, based on the data you already have, and the time of the day, depending of course on the contract type. Sure, I could make a template helper for this, and I will, but having it part of the integration would be a nice bonus. Thanks again.

Hi!

I have 2FA on my account, but as maverstr already mentioned: my customer doesn’t start with 00, but that field is filled in already so can’t ‘just’ remove it.
And when I fill in all the fields, I get a code on mail or SMS, but using that code throws an error “Invalid username or password.”.
Am I doing something wrong?

Hi, thanks for testing! The 00-prefix is a standard enforced by the ENGIE Smart App. In order to avoid users having to add the prefix themselves, I added it to the text field. You can simply paste your real customer number behind it (with or without whitespaces, both should work). That should do the trick, let me know how it goes! :smile:

Hi! Glad you were able to figure it out! I should really update the README to give some extra information about the whole 2FA situation… it’s kinda confusing. The gas pricing unit is an issue indeed… will fix it ASAP :smile:

The current price entity sounds interesting, I’ll see what I can do :smile:

@janh82 I can only recommend you to try to add a new user to in the admin panel of the Engie website, and then try to log in with that one, it did the trick for me.

Thanks Daan, and glad to see you’re also highly responsive !

I had to reboot my Raspberry during the day, as i was experimenting on other stuff, but on reboot I got an error in your integration “Failed to set up: Authentication failed (401)”. I guess I had to reconnect using 2FA because somehow the token did not persist ? There is no way to manually reconnect at the moment, so I need to delete my account in the integration, and create it again. That took barely a minute so it is not a big deal, but I thought you may want to hear about it.

If it may help you, or anyone else, here is the custom sensor template I made (with AI help) for getting the current tariff state based on current day and time, and then retrieving current injection and offtake price from your integration. Note that this is only valid for tri-rate contracts.

template:
  - trigger:
      - platform: time_pattern
        minutes: "/1"
    sensor:
      - name: Current Electricity Tariff
        unique_id: current_electricity_tariff
        icon: mdi:transmission-tower
        availability: >
          {{
            states('sensor.engie_belgium_electricity_peak_offtake_price') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_off_peak_offtake_price') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_super_off_peak_offtake_price') not in ['unknown', 'unavailable', 'none', '']
          }}
        state: >
          {% set t = now().strftime('%H:%M') %}
          {% set is_weekend = now().weekday() >= 5 %}

          {% if is_weekend %}
            {% if '01:00' <= t < '07:00' or '11:00' <= t < '17:00' %}
              Heures super creuses
            {% else %}
              Heures creuses
            {% endif %}
          {% else %}
            {% if '01:00' <= t < '07:00' %}
              Heures super creuses
            {% elif '11:00' <= t < '17:00' or t >= '22:00' or t < '01:00' %}
              Heures creuses
            {% else %}
              Heures pleines
            {% endif %}
          {% endif %}

      - name: Current Electricity Offtake Price
        unique_id: current_electricity_offtake_price
        unit_of_measurement: "EUR/kWh"
        availability: >
          {{
            states('sensor.current_electricity_tariff') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_peak_offtake_price') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_off_peak_offtake_price') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_super_off_peak_offtake_price') not in ['unknown', 'unavailable', 'none', '']
          }}
        state: >
          {% set tariff = states('sensor.current_electricity_tariff') %}
          {% set peak_price = states('sensor.engie_belgium_electricity_peak_offtake_price') | float(0) %}
          {% set off_peak_price = states('sensor.engie_belgium_electricity_off_peak_offtake_price') | float(0) %}
          {% set super_off_peak_price = states('sensor.engie_belgium_electricity_super_off_peak_offtake_price') | float(0) %}

          {% if tariff == 'Heures super creuses' %}
            {{ super_off_peak_price | round(4) }}
          {% elif tariff == 'Heures creuses' %}
            {{ off_peak_price | round(4) }}
          {% elif tariff == 'Heures pleines' %}
            {{ peak_price | round(4) }}
          {% else %}
            {{ none }}
          {% endif %}

      - name: Current Electricity Injection Price
        unique_id: current_electricity_injection_price
        unit_of_measurement: "EUR/kWh"
        availability: >
          {{
            states('sensor.current_electricity_tariff') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_peak_injection_price') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_off_peak_injection_price') not in ['unknown', 'unavailable', 'none', '']
            and states('sensor.engie_belgium_electricity_super_off_peak_injection_price') not in ['unknown', 'unavailable', 'none', '']
          }}
        state: >
          {% set tariff = states('sensor.current_electricity_tariff') %}
          {% set peak_price = states('sensor.engie_belgium_electricity_peak_injection_price') | float(0) %}
          {% set off_peak_price = states('sensor.engie_belgium_electricity_off_peak_injection_price') | float(0) %}
          {% set super_off_peak_price = states('sensor.engie_belgium_electricity_super_off_peak_injection_price') | float(0) %}

          {% if tariff == 'Heures super creuses' %}
            {{ super_off_peak_price | round(4) }}
          {% elif tariff == 'Heures creuses' %}
            {{ off_peak_price | round(4) }}
          {% elif tariff == 'Heures pleines' %}
            {{ peak_price | round(4) }}
          {% else %}
            {{ none }}
          {% endif %}
1 Like

I haven’t quite figured out how long the refresh token is valid, since it’s a non-standard token and the lifetime is not really mentioned anywhere. Since the access tokens are only valid for 2 minutes, the integration refreshes them every minute and then also stores the newly received refresh token, to use with the next refresh. I suppose the Smart App has some sort of re-auth flow that I might be able to use. I’ll take a look. Do you have an estimation for how long your instance was shut down? Hours? For now: keeping the integration/your HA instance alive is the best option :frowning_face:

Honestly it was just a simple sudo restart, so I guess less than a few minutes.
In practice, I did not check if the authentication failed immediately after reboot. I just noticed it later that day, thus I just supposed it was due to it, but without confirmation.
Anyway, it is not a very long process to delete and re-log into the account, so it ain’t really a big issue imo :slight_smile:

@maverstr The gas price unit has been fixed in v0.4.0. So it’s now EUR/kWh instead of EUR/m3 :smile:

1 Like

I was wondering now. Do the shown prices include transport and other additions? I would like to know how much money i have to pay out of my pocket, not only energy price …

2 Likes

The ENGIE pages states the following for me:

Hoe wordt de variabele prijs bepaald?

Je energiecontract heeft een variabele energieprijs. Bij een contract met variabele energieprijs volgt je prijs de marktprijzen. Als die prijzen stijgen, dan stijgt jouw energieprijs. Als die prijzen dalen, dan daalt jouw energieprijs. Die aanpassing van de prijs gebeurt maandelijks of trimestrieel afhankelijk van een prijsformule die vastligt voor de duur van je contract en de indexatieparameter die in deze formule wordt gebruikt.

Om je te helpen, hebben wij een overzicht gemaakt van je ENGIE-energieprijs per maand voor je huidige contract.

So I suppose these prices are what you’re actually paying? Since they don’t seem to match with the prices on my contract.

How can we use the prices in the energy dashboard, when I add them I get:

Last reset missing
The following entities have state class 'measurement' but 'last_reset' is missing:

* sensor.engie_belgium_electricity_peak_offtake_price
* sensor.engie_belgium_electricity_peak_injection_price
Last reset missing
The following entities have state class 'measurement' but 'last_reset' is missing:

* sensor.engie_belgium_electricity_off_peak_offtake_price
* sensor.engie_belgium_electricity_off_peak_injection_price

That’s normal when adding new entities to the energy dashboard. last_reset will populate after some time.

That did the trick: added a new account and now I’m good to go! Thanks for the answer!

1 Like

I tried it out myself. After creating a new user account with Engie, I was able to set up the integration in HA.
Now I’m getting the message in HA: “Failed setup - error communicating with Engie API”