UK Address API & Royal Mail PAF: Developer Integration Guide
Developer guide for UK Address API integration and Royal Mail PAF. Includes PAF data hierarchy, UDPRN resolution, licensing, and code snippets for Node, Python, and PHP.
# UK Address API & Royal Mail PAF Developer Integration Guide
A UK Address API resolves postcodes, partial addresses, and UDPRNs into standardized, premise-level delivery points sourced directly from Royal Mail's Postcode Address File (PAF). PAF covers over 31 million delivery points across England, Scotland, Wales, and Northern Ireland, updated daily by Royal Mail postal carriers.
Integrating directly with raw PAF files requires managing complex database ingestion, licensing compliance, and daily delta updates. A RESTful UK address API abstracts PAF complexity into simple JSON endpoints with premise-level accuracy, autocomplete, and sub-100ms response times.
---
Understanding the Royal Mail PAF Data Hierarchy
UK postal addresses do not follow a rigid street-and-number schema. PAF structures delivery points using a hierarchical model designed for efficient mail sorting and routing.
+-------------------------------------------------------------+
| Postcode Area & District (e.g., EC2A) |
| +-- Post Town (e.g., LONDON) |
| +-- Dependent Locality (e.g., Shoreditch) |
| +-- Thoroughfare / Street (e.g., High Street) |
| +-- Building Name / Number |
| +-- Sub-Building (e.g., Flat 2B) |
| +-- UDPRN (Delivery Point) |
+-------------------------------------------------------------+Key PAF Address Elements
| PAF Field | Description | Example |
|---|---|---|
| UDPRN | Unique Delivery Point Reference Number (8-digit unique ID) | 12345678 |
| Sub-Building Name | Flat, unit, suite, or apartment identifier | Flat 4B |
| Building Name | Named structure or office block | Prospect House |
| Building Number | Numeric street number | 12 |
| Dependent Thoroughfare | Secondary road or access lane | Mews Way |
| Thoroughfare | Main street or road name | Commercial Street |
| Double Dependent Locality | Small hamlet or specific district zone | Canary Wharf |
| Dependent Locality | Village, suburb, or neighborhood | Spitalfields |
| Post Town | Official Royal Mail routing sorting office / town | LONDON |
| Postcode | Outcode (area/district) + Incode (sector/unit) | EC1V 1AB |
| Traditional County | Historical county (omitted in modern PAF postal standards) | Greater London |
Premise-Level Precision vs Postcode-Centric Open Data
Open-data sources like Code-Point Open or ONS Postcode Directory resolve addresses only to an average postcode centroid (typically 15–20 delivery points sharing one postcode). They do not contain individual building numbers, flat sub-divisions, or business names.
Royal Mail PAF provides premise-level precision down to the exact letterbox, indexed by UDPRN (Unique Delivery Point Reference Number).
---
PAF Licensing Mechanics: What Developers Must Know
Royal Mail licenses PAF under structured terms governed by direct licensee contracts:
- Direct PAF Licensee vs Derived Open Data: Postio is a direct Royal Mail PAF licensee. Addresses queried via Postio are checked against the authoritative Royal Mail dataset.
- Per-Lookup vs Per-User Pricing: Legacy PAF licensing often charged fixed seat fees per named user. Modern REST APIs charge per completed lookup, lowering costs for e-commerce checkouts and SaaS applications.
- Address Formating Standards: Royal Mail recommends presenting addresses in 3 to 5 clear address lines plus Post Town and Postcode in uppercase.
---
Integrating Postio UK Address API
Postio provides a high-performance, developer-friendly REST API for UK address autocomplete and postcode lookups. You can test integrations with 100 free lookups upon registration.
REST Endpoint Overview
- Postcode Lookup:
GET https://api.postio.co.uk/v1/addresses?postcode={postcode} - Address Autocomplete:
GET https://api.postio.co.uk/v1/addresses/autocomplete?q={query} - UDPRN Resolution:
GET https://api.postio.co.uk/v1/addresses/udprn/{udprn}
Authentication
Pass your API key in the Authorization header as a Bearer token or X-API-Key header:
GET /v1/addresses?postcode=SW1A1AA HTTP/1.1
Host: api.postio.co.uk
Authorization: Bearer YOUR_API_KEYExample JSON Response (PAF Premise-Level)
{
"status": "success",
"data": [
{
"udprn": "23749210",
"line_1": "Flat 2B, Prospect House",
"line_2": "12 Commercial Street",
"line_3": "",
"premise": "Flat 2B",
"building_name": "Prospect House",
"building_number": "12",
"sub_building_name": "Flat 2B",
"thoroughfare": "Commercial Street",
"dependent_locality": "Spitalfields",
"post_town": "LONDON",
"postcode": "E1 6EQ",
"latitude": 51.5187,
"longitude": -0.0763
}
]
}---
Code Integration Snippets
1. Node.js (TypeScript / JavaScript)
// Node.js 18+ native fetch
async function lookupUkAddress(postcode, apiKey) {
const url = `https://api.postio.co.uk/v1/addresses?postcode=${encodeURIComponent(postcode)}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Address lookup failed: ${response.status} ${response.statusText}`);
}
const { data } = await response.json();
return data.map(addr => ({
udprn: addr.udprn,
line1: addr.line_1,
line2: addr.line_2,
town: addr.post_town,
postcode: addr.postcode
}));
}
// Usage
lookupUkAddress('EC1V 1AB', process.env.POSTIO_API_KEY)
.then(addresses => console.log('Found addresses:', addresses))
.catch(err => console.error(err));2. Python (3.8+)
import os
import requests
def get_paf_addresses(postcode: str, api_key: str):
url = "https://api.postio.co.uk/v1/addresses"
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "application/json"
}
params = {"postcode": postcode.strip()}
response = requests.get(url, headers=headers, params=params, timeout=5)
response.raise_for_status()
payload = response.json()
return payload.get("data", [])
if __name__ == "__main__":
api_key = os.environ.get("POSTIO_API_KEY", "YOUR_API_KEY")
addresses = get_paf_addresses("SW1A 1AA", api_key)
for addr in addresses:
print(f"{addr['line_1']}, {addr['post_town']} {addr['postcode']} (UDPRN: {addr['udprn']})")3. PHP (cURL / PSR-18)
<?php
function lookupAddress(string $postcode, string $apiKey): array
{
$ch = curl_init();
$query = http_build_query(['postcode' => $postcode]);
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.postio.co.uk/v1/addresses?" . $query,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . $apiKey,
"Accept: application/json"
],
CURLOPT_TIMEOUT => 5
]);
$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($statusCode !== 200) {
throw new Exception("Postio API returned HTTP " . $statusCode);
}
$data = json_decode($response, true);
return $data['data'] ?? [];
}
// Usage
$apiKey = getenv('POSTIO_API_KEY') ?: 'YOUR_API_KEY';
$results = lookupAddress('M1 1AA', $apiKey);
foreach ($results as $address) {
echo $address['line_1'] . ', ' . $address['post_town'] . PHP_EOL;
}---
Best Practices for Frontend Checkout Autocomplete
When implementing address lookup on UK checkouts or registration forms:
- Debounce User Input: When building live address autocomplete, debounce keyboard events by 250–300ms to minimize unnecessary API requests.
- Offer Manual Entry Fallback: In edge cases involving newly built properties (prior to Royal Mail Not Yet Built updates), ensure customers can toggle to manual input.
- Store UDPRN for Deduplication: Store the Royal Mail
udprnin your database. UDPRNs remain stable across renames and postal reorganizations, eliminating duplicate customer records. - Format for Shipping Carriers: Major UK carriers (Royal Mail, DPD, Evri) format addresses using standard PAF lines: Line 1 (Premise + Street), Line 2 (Locality), Town, and Postcode.
---
Getting Started
Explore full endpoint documentation, parameter schemas, and webhook support in the Postio Address API Documentation. Register for a free API key to access 100 free live Royal Mail PAF lookups on Postio Signup.
Ready in under a minute.
Sign up, grab a key, paste it in. Your first hundred lookups are on us.