Skip to main content

Async Python client for the Veolia water portal API (eau.veolia.fr).

Table of contents

Installation

First of all, you need to install devbox if you don't have a python environment

Once the previous step is done, simply run

devbox shell
cp .env.example .env   # fill in your credentials
python usage_example.py

That's it !

If you already have a python environment just run

pip install veolia-api-foxace

Usage

"""Example of usage of the Veolia API"""

import asyncio
from datetime import date

import aiohttp

from veolia_api.veolia_api import VeoliaAPI


async def main() -> None:
    """Main function."""

    async with aiohttp.ClientSession() as session:
        client_api = VeoliaAPI("your@email.com", "password", session)

        await client_api.fetch_all_data(date(2025, 1, 1), date(2025, 9, 1))

        # Display fetched data
        print(client_api.account_data.daily_consumption)
        print(client_api.account_data.monthly_consumption)
        print(client_api.account_data.alert_settings.daily_enabled)


if __name__ == "__main__":
    asyncio.run(main())

You can use usage_example.py

Portals

Veolia operates several portals. They share the same Cognito authentication flow but each has its own client_id, and some run on a dedicated data backend. Select a portal with the portal_url argument (defaults to the national portal):

client_api = VeoliaAPI("your@email.com", "password", session, portal_url="www.ea-pm.fr")
portal_url Description Backend
eau.veolia.fr (default) Veolia France (national) default
eaudetm.monespace.eau.veolia.fr Eau de Toulouse Métropole default
www.ea-pm.fr Eau de Perpignan Méditerranée Métropole dedicated

You can resolve a commune name to its portal at setup time:

from veolia_api import resolve_portal_url

portal = await resolve_portal_url("Toulouse")   # "eaudetm.monespace.eau.veolia.fr"
client_api = VeoliaAPI("your@email.com", "password", session, portal_url=portal)

To add a portal, add an entry to VEOLIA_PORTALS in veolia_api/portals.py with its client_id (found in the portal's JavaScript bundle as ClientId:"...") and, if different from the default, its backend_url.

Refresh-token authentication

Some portals put password sign-ins behind Cognito's adaptive authentication: whenever it does not recognise the caller's context, Cognito answers a challenge (SMS_MFA in practice) instead of tokens. On accounts migrated to such a portal the pool's phone_number is an unverified placeholder, so the code never arrives and the challenge can never be answered. The client reports that case as VeoliaAPIChallengeError rather than a generic authentication failure.

REFRESH_TOKEN_AUTH is not a sign-in flow, so Cognito never risk-scores it: a refresh token obtained once from a context it already trusts authenticates from any address. Pass it instead of the credentials, which may then be empty:

client_api = VeoliaAPI("", "", session, refresh_token="ey...")

Obtain the token from a machine the portal is used from, with an InitiateAuth call carrying the portal's client_id:

curl -s https://cognito-idp.eu-west-3.amazonaws.com/ \
  -H 'Content-Type: application/x-amz-json-1.1' \
  -H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
  -d '{"ClientId":"<client_id>","AuthFlow":"USER_PASSWORD_AUTH",
       "AuthParameters":{"USERNAME":"your@email.com","PASSWORD":"..."}}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["AuthenticationResult"]["RefreshToken"])'

A refresh token is a credential in its own right: store it as you would the password, and keep it out of logs and diagnostics.

It is also short-lived: its validity is set on the Cognito app client, measured at one hour on the Toulouse Métropole pool, and REFRESH_TOKEN_AUTH returns no new one — there is no rotation. Treat it as a way to reach an account whose password sign-in is challenged, not as a lasting alternative to the password. Cognito's risk score warms up as an address keeps presenting valid tokens, so the password sign-in is usually accepted again afterwards.

Maintainers can regenerate the portal table from Veolia's national bundle:

python scripts/regenerate_portals.py

The script prints a candidate VEOLIA_PORTALS block and a diff against the current table — review and edit veolia_api/portals.py manually.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on reporting bugs, suggesting features, and submitting pull requests.

Credits

This repository is inspired by the work done by @CorentinGrard. Thanks to him for his work. It is a fork of Jezza34000/veolia-api.

License

This project is licensed under the MIT License. See LICENSE for details.

Release files for veolia-api-foxace 2.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for veolia-api-foxace 2.5.1
File Size Uploaded
veolia_api_foxace-2.5.1.tar.gz 20.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for veolia-api-foxace 2.5.1
File Interpreter ABI Platform
veolia_api_foxace-2.5.1-py3-none-any.whl Python 3 none any Details

Total release size: 40.9 kB

Release files / veolia_api_foxace-2.5.1.tar.gz

Download URL veolia_api_foxace-2.5.1.tar.gz
Size 20.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c9596fce3ab7291b100634ed48cf8431590b86dcee907a7c2a4ec3c379cb19bc
BLAKE2b-256 checksum
How to use checksums
12a979737d6b5dbbf939d9c01c97af0a37b35f3f5bf84518934c9d758c237847
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.

Transparency log

Release files / veolia_api_foxace-2.5.1-py3-none-any.whl

Download URL veolia_api_foxace-2.5.1-py3-none-any.whl
Size 20.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
64174ab6e933ef38ec85c9be585d5e2d02dc8873a4af7729f86d090d44b43796
BLAKE2b-256 checksum
How to use checksums
07b311dbaa67ce15d03515429f31317870f79bbf1f88f541f9280bff642a75c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.

Transparency log

Release history Release notifications | RSS feed

2.6.0

2 release files

This release

2.5.1 This release

2 release files

2.5.0

2 release files

2.4.4

2 release files

2.4.3

2 release files

2.4.2

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page