Skip to main content

Postio Python SDK

PyPI Python versions License: MIT

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

First time? Sign up free — first 100 lookups on us, no card needed.

Install

pip install postio

Requires Python 3.10+.

30-second example

from postio import PostioClient

client = PostioClient(api_key="pk_...")  # 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_...") 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 at https://postio.co.uk/contact.

Configuration

from postio import PostioClient, RetryConfig

client = PostioClient(
    api_key="pk_...",
    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.

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.2.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.2-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for postio-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3799f4833f56e0ba2900afcf60bc3883573cd4a08ef324300439f183ee80fd46
MD5 725edef305b9a0983f228ae7c082be1a
BLAKE2b-256 36c99953692c3873d8dda95d436574c06536c31fd5f81a32fef07bd999cf613e

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: postio-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for postio-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0eb6b9fe8979dee808ff0c72f3ebb7774e15cbf94ebe4dcf366e7cc16845c825
MD5 20356a2ddacda7b57c1b40e5eb3d0318
BLAKE2b-256 c5e8e18b61a12edb51ee2cce4a0748543b94e5c7467803c0d67de4a823f6eb09

See more details on using hashes here.

Provenance

The following attestation bundles were made for postio-0.1.2-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 Sentry Error logging StatusPage Status page