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.0.tar.gz (19.5 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.0-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: uw_api-0.2.0.tar.gz
  • Upload date:
  • Size: 19.5 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.0.tar.gz
Algorithm Hash digest
SHA256 6acbbfc8f3579b72c7c97b82e38749b4f5bfaf9e996603eb57d2f592b84cabc2
MD5 306ceeea8c9ffb0dcaf855c5bba038b1
BLAKE2b-256 ee101104f19c01a7a0d9383607e8a9cf9ce1ee332dcc8b1ae7e2923b450a331f

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: uw_api-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 14.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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6b934f2dafdce8c5710275c296df4dce3bd7f52b71d9ad870c96bfba5eabde5d
MD5 dd605c1ce1a405c3d3fdccec5ada0ac5
BLAKE2b-256 477b324253ef87c6fdacdb007cf266308e17fc103008d99899e5ada92490414a

See more details on using hashes here.

Provenance

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

0.2.1

2 files

This release

0.2.0 This release

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