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.1.tar.gz (21.3 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.1-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: uw_api-0.2.1.tar.gz
  • Upload date:
  • Size: 21.3 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.1.tar.gz
Algorithm Hash digest
SHA256 fb86fd142502f6e8cdf9361d431953a05a5f3e0a0ecb095c619f162051093772
MD5 f3ec2b0fbb29e245740642d6d09f888f
BLAKE2b-256 c56d18e39429c2c58716be9e7957338b1c6caa42bba72c1d760337bcf621fb6d

See more details on using hashes here.

Provenance

The following attestation bundles were made for uw_api-0.2.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: uw_api-0.2.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b3581f16805515b13bda419c7a332b28003af449d15c3d28b8726535b5f2e685
MD5 9838e47c1a6713d814ecdce3f0c0d203
BLAKE2b-256 1a02934c9b8d068a69e30bcd281502d0b2aa234d6016f67dae62e6cac6cc0c76

See more details on using hashes here.

Provenance

The following attestation bundles were made for uw_api-0.2.1-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

0.2.2

2 files

This release

0.2.1 This release

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