Skip to main content

uw-api

Async Python client for the Utility Warehouse customer portal API.

Endpoints are hardcoded (discovered from myaccount.uw.co.uk/) and require no configuration — just provide credentials.

Installation

pip install uw-api

Usage

import asyncio
from uw_api import UWClient

async def main():
    async with UWClient(email="user@example.com", password="secret") as client:
        await client.login()

        account = await client.gql.get_account()
        print(f"Account: {account.account_number}")

        bills = await client.gql.get_bills()
        for bill in bills:
            print(f"Bill {bill.bill_id}: £{bill.total_amount_gbp}")

        consumption = await client.gql.get_consumption()
        print(f"Electricity: {consumption.electricity_kwh} kWh")
        print(f"Gas: {consumption.gas_kwh} kWh")

        meters = await client.gql.get_meters()
        for meter in meters:
            print(f"{meter.meter_type}: {meter.meter_number} (smart={meter.is_smart})")

        tariff = await client.gql.get_tariff()
        if tariff:
            print(f"Tariff: {tariff.tariff_name}")

asyncio.run(main())

API Reference

Auth

client = UWClient(email="...", password="...")
await client.login()

Authenticates via OAuth2 PKCE at account.uw.co.uk/v2/login. Session cookies are managed automatically. The library re-authenticates on 401 responses.

Account

account = await client.gql.get_account()

Returns UWAccount with account_id and account_number.

Energy

consumption = await client.gql.get_consumption()
services   = await client.gql.get_energy_services()
usage      = await client.gql.get_energy_usage()
  • get_consumption()EnergyConsumption (latest electricity/gas kWh)
  • get_energy_services() → raw list of energy service dicts
  • get_energy_usage() → list of EnergyUsage with per-meter readings

Meters

meters   = await client.gql.get_meters()
readings = await client.gql.get_meter_readings()
  • get_meters() → list of Meter (type, serial, smart status, last reading date)
  • get_meter_readings() → list of MeterReading (value, type, date, source)

Bills

bills   = await client.gql.get_bills()
pdf_url = await client.gql.get_pdf_url(month=1, year=2026)
  • get_bills() → list of Bill (ID, date, amount, status, PDF URL)
  • get_pdf_url(month, year) → str URL for the bill PDF

Financial

balance  = await client.gql.get_balance()
services = await client.gql.get_live_services()
tariff   = await client.gql.get_tariff()
  • get_balance(){"due": float, "overdue": float}
  • get_live_services() → dict of service statuses
  • get_tariff()EnergyTariff (name, code, rates)

Hardcoded Endpoints

Purpose URL
Login page https://account.uw.co.uk/v2/login
GraphQL API https://myaccount.uw.co.uk/server/graphql

11 GraphQL operations are embedded in uw_api/graphql/queries.py.

Discovery Script (optional)

A HAR-based discovery script is included for verifying or re-discovering endpoints:

python scripts/discover_api.py parse-har capture.har

This is not required for normal use — the library ships with hardcoded endpoints discovered from myaccount.uw.co.uk/ in July 2026.

Architecture

UWClient → UWAuth (OAuth2 PKCE)
         → UWGraphQL → /server/graphql (POST)
                      → Pydantic v2 models
  • Auth: CSRF token extraction from login page HTML, form-encoded POST with Castle.io device token
  • GraphQL: All data via POST /server/graphql with operation-oriented queries
  • Retry: 3 attempts with exponential backoff on 429/5xx, re-auth on 401
  • Models: UWAccount, EnergyUsage, EnergyConsumption, EnergyTariff, Meter, MeterReading, Bill, BillPDFMetadata

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uw_api-0.2.2.tar.gz (21.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

uw_api-0.2.2-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file uw_api-0.2.2.tar.gz.

File metadata

  • Download URL: uw_api-0.2.2.tar.gz
  • Upload date:
  • Size: 21.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for uw_api-0.2.2.tar.gz
Algorithm Hash digest
SHA256 33639c810097e841f8666f39ff001e632b7cf85fe1b3c802f52d5a80159bbede
MD5 4b715925d68bc5ed131497d865be5665
BLAKE2b-256 4b9275f56b1d93cdcba64b69932b8711b6ae7b1872006d91dfd4aef20b566b49

See more details on using hashes here.

Provenance

The following attestation bundles were made for uw_api-0.2.2.tar.gz:

Publisher: release-please.yml on KRoperUK/uw-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uw_api-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: uw_api-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 15.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for uw_api-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1ae7fc8e502b1aedc9f66dd40a51e69f0ff979ba9d872515cce65e77fd54f527
MD5 83a9d52da84307413240c491de485ba2
BLAKE2b-256 4fe48da93c6db76d9e61ad7605c5b4b72868cd1adce39def77483f2d17e4758d

See more details on using hashes here.

Provenance

The following attestation bundles were made for uw_api-0.2.2-py3-none-any.whl:

Publisher: release-please.yml on KRoperUK/uw-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 files

0.2.1

2 files

0.2.0

2 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