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

Uploaded Python 3

File details

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

File metadata

  • Download URL: postio-0.1.1.tar.gz
  • Upload date:
  • Size: 10.6 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.1.tar.gz
Algorithm Hash digest
SHA256 d62428c92353c3d0e73d2e27d47780a52d5c206d3ebb227aaaef0bf2b6b9db80
MD5 74c22c93b2141be358ae24955ae37e0f
BLAKE2b-256 f31ca11c214d90f8c9b737c46cc391174129df51a0c64313035a7ef6910c9887

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: postio-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.6 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dccc4b634569a04dedeeb12d0c81174da720f97c7ed809dbc487f088697cdbe4
MD5 34a9af3b4267f54971a802598dd3349a
BLAKE2b-256 fd13fe2967ac408f0f4586a565128d147537a6ea5776e5f6a92b4b2bacb77938

See more details on using hashes here.

Provenance

The following attestation bundles were made for postio-0.1.1-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