Skip to main content

Python SDK for the Postio API — UK address, email, and phone validation. PAF + Ordnance Survey backed. Sync + async, type-safe via Pydantic v2.

Project description

Postio Python SDK

PyPI Python versions License: MIT

Python SDK for the Postio API — UK address, email, and phone validation. Backed by Royal Mail PAF and Ordnance Survey. Sync + async, type-safe via Pydantic v2.

Install

pip install postio

Requires Python 3.10+.

30-second example

from postio import PostioClient

client = PostioClient(api_key="pk_live_...")  # or set POSTIO_API_KEY

result = client.address.search("downing street")
for hit in result.results:
    print(hit.udprn, hit.suggestion)

print("request id:", result.meta.requestId)

Async

import asyncio
from postio import AsyncPostioClient

async def main():
    async with AsyncPostioClient(api_key="pk_live_...") as client:
        result = await client.address.postcode("SW1A 2AA")
        for addr in result.results:
            print(addr.address_line_1, addr.post_town)

asyncio.run(main())

API

Method Returns Notes
client.address.search(q, max_results=None) AddressSearchEnvelope Free-text typeahead lookup
client.address.postcode(postcode, max_results=None) AddressPostcodeEnvelope Full addresses for a postcode
client.address.udprn(udprn) AddressUdprnEnvelope Single address by UDPRN
client.email.validate(address) EmailEnvelope Syntax + MX + SMTP + deliverability
client.phone.validate(number) PhoneEnvelope E.164 format + carrier + reachability
client.connect() ConnectSuccess Free health probe

AsyncPostioClient exposes the same surface, awaitable.

Errors

Every non-2xx response raises a typed exception. PostioError is the base.

from postio import (
    PostioClient,
    PostioInvalidKey,       # 401
    PostioOutOfCredit,      # 402
    PostioForbidden,        # 403
    PostioNotFound,         # 404
    PostioValidationError,  # 400 / 422
    PostioRateLimit,        # 429 — has .retry_after
    PostioServerError,      # 5xx — retried by default
    PostioTimeout,
    PostioConnectionError,
)

try:
    client.address.postcode("not-a-postcode")
except PostioValidationError as err:
    print(err.status, err.code, err.request_id, err.envelope)

Every error carries status, code, details, request_id, and the raw envelope. The request_id is the support handle to quote when reporting issues to admin@postio.co.uk.

Configuration

from postio import PostioClient, RetryConfig

client = PostioClient(
    api_key="pk_live_...",
    base_url="https://api.postio.co.uk/v1",   # default
    timeout=10.0,                              # seconds
    retries=2,                                 # or RetryConfig(...) or None to disable
    headers={"x-tracking-id": "..."},          # extra headers, merged
)

Default retry policy: 2 retries, exponential backoff with full jitter (0.5s → 8s cap), retries on 408, 409, 429, 5xx, and network/timeout errors. Pass retries=None to disable.

Frameworks

The SDK is framework-agnostic but ships classifiers for Django, Flask, and FastAPI. Drop the client on your app state at startup:

FastAPI

from contextlib import asynccontextmanager
from fastapi import FastAPI
from postio import AsyncPostioClient

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.postio = AsyncPostioClient()  # reads POSTIO_API_KEY
    yield
    await app.state.postio.close()

app = FastAPI(lifespan=lifespan)

Django — instantiate one PostioClient in apps.py's ready() and stash it on a module-level singleton; close it in a shutdown signal handler.

FlaskPostioClient on app.extensions["postio"], close in app.teardown_appcontext.

Links

License

MIT — see LICENSE.

Postio is a trading name of Onno Group Limited, registered in England & Wales (company no. 08622799). Registered office: Suite 22 Trym Lodge, 1 Henbury Road, Westbury-On-Trym, Bristol BS9 3HQ.

Project details


Download files

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

Source Distribution

postio-0.1.0.tar.gz (10.8 kB view details)

Uploaded Source

Built Distribution

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

postio-0.1.0-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file postio-0.1.0.tar.gz.

File metadata

  • Download URL: postio-0.1.0.tar.gz
  • Upload date:
  • Size: 10.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for postio-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a8d3efc32713f780a525baa1b20425e4f361d1d838336e37ab6aa91c914ddb3b
MD5 8e2f14ff159d3bf585767ceb46c76cfd
BLAKE2b-256 a1f510fd7d9b64afb92160b9c18a3ac293ab14d2bf2eb7cd1b87b035543581db

See more details on using hashes here.

Provenance

The following attestation bundles were made for postio-0.1.0.tar.gz:

Publisher: release.yml on postio-uk/postio-python

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

File details

Details for the file postio-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: postio-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for postio-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 05b5b072a5514c87088a9f3e2bdd70104ecf9efaa16c855eb3167ec2ccc93c50
MD5 1022508f582a922c5ff547376ccab27b
BLAKE2b-256 339be01d61ff5a41179dd995307b8985b26d92488f1eca970dd7d5d0bc0878d6

See more details on using hashes here.

Provenance

The following attestation bundles were made for postio-0.1.0-py3-none-any.whl:

Publisher: release.yml on postio-uk/postio-python

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page