Guides

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 FieldDescriptionExample
UDPRNUnique Delivery Point Reference Number (8-digit unique ID)12345678
Sub-Building NameFlat, unit, suite, or apartment identifierFlat 4B
Building NameNamed structure or office blockProspect House
Building NumberNumeric street number12
Dependent ThoroughfareSecondary road or access laneMews Way
ThoroughfareMain street or road nameCommercial Street
Double Dependent LocalitySmall hamlet or specific district zoneCanary Wharf
Dependent LocalityVillage, suburb, or neighborhoodSpitalfields
Post TownOfficial Royal Mail routing sorting office / townLONDON
PostcodeOutcode (area/district) + Incode (sector/unit)EC1V 1AB
Traditional CountyHistorical 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:

  1. 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.
  2. 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.
  3. 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_KEY

Example 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:

  1. Debounce User Input: When building live address autocomplete, debounce keyboard events by 250–300ms to minimize unnecessary API requests.
  2. 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.
  3. Store UDPRN for Deduplication: Store the Royal Mail udprn in your database. UDPRNs remain stable across renames and postal reorganizations, eliminating duplicate customer records.
  4. 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.

UK Address API & Royal Mail PAF: Developer Integration Guide | Postio · Postio