Async Python client for National Grid built on aiohttp
Project description
aionatgrid
Asynchronous Python client for communicating with National Grid's GraphQL and REST APIs using aiohttp. The package provides pre-built query helpers for common operations, automatic OIDC authentication, and multi-endpoint routing.
Features
- Async
NationalGridClientwith context-manager support and connection reuse - Pre-built query helpers for linked accounts, billing info, and energy usage data
- Automatic OIDC authentication via Azure AD B2C with token caching and refresh
- Multi-endpoint GraphQL routing (user, billing account, energy usage endpoints)
- REST API support with shared authentication
- Configurable via
NationalGridConfigdataclass - JWT token verification and automatic expiration handling
Requirements
- Python 3.10+
uvfor dependency management (install from Astral)
Installation
uv sync
The command creates a .venv managed by uv and installs runtime plus development dependencies declared in pyproject.toml.
Usage
Quick Start
import asyncio
from aionatgrid import NationalGridClient, NationalGridConfig
async def main() -> None:
config = NationalGridConfig(
username="user@example.com",
password="your-password",
)
async with NationalGridClient(config=config) as client:
# Get linked billing accounts
response = await client.linked_billing_accounts()
print(response.data)
if __name__ == "__main__":
asyncio.run(main())
Available Query Methods
The client provides convenience methods for common National Grid API operations:
| Method | Description | Endpoint |
|---|---|---|
linked_billing_accounts() |
Get user's linked billing account IDs | user-cu-uwp-gql |
billing_account_info() |
Get account details (region, meters, address) | billingaccount-cu-uwp-gql |
energy_usage_costs() |
Get energy costs for a billing period | energyusage-cu-uwp-gql |
energy_usages() |
Get historical usage data | energyusage-cu-uwp-gql |
realtime_meter_info() |
Get real-time meter readings (REST) | REST endpoint |
Example: Fetching Energy Usage Data
import asyncio
from datetime import date
from aionatgrid import NationalGridClient, NationalGridConfig
async def main() -> None:
config = NationalGridConfig(
username="user@example.com",
password="your-password",
)
async with NationalGridClient(config=config) as client:
# Step 1: Get linked accounts
accounts = await client.linked_billing_accounts()
account_id = accounts.data["user"]["accountLinks"]["nodes"][0]["billingAccountId"]
# Step 2: Get account info (for region/companyCode)
info = await client.billing_account_info(
variables={"accountNumber": account_id}
)
region = info.data["billingAccount"]["region"]
# Step 3: Fetch energy usage costs
costs = await client.energy_usage_costs(
variables={
"accountNumber": account_id,
"date": date.today().isoformat(),
"companyCode": region,
}
)
print(costs.data)
# Step 4: Fetch historical usage (last 12 months)
from_month = (date.today().year - 1) * 100 + date.today().month
usages = await client.energy_usages(
variables={
"accountNumber": account_id,
"from": from_month,
"first": 12,
}
)
print(usages.data)
if __name__ == "__main__":
asyncio.run(main())
Custom GraphQL Queries
For custom queries, use the execute() method directly:
from aionatgrid import GraphQLRequest
request = GraphQLRequest(
query="query MyQuery { ... }",
variables={"key": "value"},
endpoint="https://myaccount.nationalgrid.com/api/custom-endpoint"
)
response = await client.execute(request)
REST API Access
response = await client.request_rest("GET", "/api/endpoint")
print(response.status, response.data)
Examples
Run the included example scripts:
uv run python examples/list-accounts.py --username user@example.com --password secret
uv run python examples/account-info.py --username user@example.com --password secret
uv run python examples/energy-usage.py --username user@example.com --password secret
uv run python examples/interval-reads.py --username user@example.com --password secret
Testing and Linting
uv run pytest # run unit tests
uv run ruff check . # lint
uv run ruff format . # format
uv run mypy src # type-check
All commands above also have Makefile shortcuts (see Makefile).
Project Layout
.
├── examples/
│ ├── account-info.py # Billing account details example
│ ├── energy-usage.py # Energy costs and usage example
│ ├── interval-reads.py # Interval meter readings example
│ └── list-accounts.py # Account listing example
├── src/aionatgrid/
│ ├── __init__.py # Public exports
│ ├── auth.py # Authentication helpers
│ ├── client.py # NationalGridClient implementation
│ ├── config.py # NationalGridConfig and RetryConfig
│ ├── exceptions.py # Custom exception classes
│ ├── graphql.py # GraphQL request/response types
│ ├── helpers.py # Utility functions
│ ├── oidchelper.py # OIDC authentication flow
│ ├── queries.py # GraphQL query builders
│ ├── rest.py # REST request/response types
│ └── rest_queries.py # REST query builders
├── tests/
│ ├── test_client.py # Client unit tests
│ ├── test_config.py # Configuration tests
│ └── test_retry.py # Retry logic tests
├── Makefile # Developer shortcuts
└── pyproject.toml # Packaging metadata
Architecture
Multi-Endpoint Routing
National Grid uses separate GraphQL endpoints for different data domains. The query helpers automatically route requests to the correct endpoint:
- user-cu-uwp-gql: User account links
- billingaccount-cu-uwp-gql: Billing account metadata
- energyusage-cu-uwp-gql: Energy usage and cost data
Authentication
The client handles OIDC authentication automatically:
- First API call triggers authentication
- Tokens are cached with thread-safe locking
- Expired tokens are refreshed automatically (5-minute buffer)
- JWT signatures are verified cryptographically
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aionatgrid-0.1.0.tar.gz.
File metadata
- Download URL: aionatgrid-0.1.0.tar.gz
- Upload date:
- Size: 34.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab49146b7587f16a93946136652791377bc189ad9d113cc0c39f0be4eaf6031a
|
|
| MD5 |
8dc44bff4fa5a5b6a3a4792d790a85f0
|
|
| BLAKE2b-256 |
d94a7b2bec74c1ed95f12f9fa69d8ad357b8cb164de67597320c958c6268beeb
|
Provenance
The following attestation bundles were made for aionatgrid-0.1.0.tar.gz:
Publisher:
release.yml on RyanMorash/aionatgrid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aionatgrid-0.1.0.tar.gz -
Subject digest:
ab49146b7587f16a93946136652791377bc189ad9d113cc0c39f0be4eaf6031a - Sigstore transparency entry: 859222246
- Sigstore integration time:
-
Permalink:
RyanMorash/aionatgrid@1996fa6076b69fde46ada3e9f39eb725f6d4fab9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/RyanMorash
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1996fa6076b69fde46ada3e9f39eb725f6d4fab9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file aionatgrid-0.1.0-py3-none-any.whl.
File metadata
- Download URL: aionatgrid-0.1.0-py3-none-any.whl
- Upload date:
- Size: 30.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4be77aba73adde6f3e5eeb718beeb3078bbd32f2fb41ec508fa2e90bfd1f2b98
|
|
| MD5 |
79c6906f5c48d64ee3d3d2d27fb2931d
|
|
| BLAKE2b-256 |
901c96340c24f2577235d0ef345206166f95315345bcb2682fd9c364b5083dd9
|
Provenance
The following attestation bundles were made for aionatgrid-0.1.0-py3-none-any.whl:
Publisher:
release.yml on RyanMorash/aionatgrid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aionatgrid-0.1.0-py3-none-any.whl -
Subject digest:
4be77aba73adde6f3e5eeb718beeb3078bbd32f2fb41ec508fa2e90bfd1f2b98 - Sigstore transparency entry: 859222300
- Sigstore integration time:
-
Permalink:
RyanMorash/aionatgrid@1996fa6076b69fde46ada3e9f39eb725f6d4fab9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/RyanMorash
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1996fa6076b69fde46ada3e9f39eb725f6d4fab9 -
Trigger Event:
release
-
Statement type: