API reference
Overview
Base URL /v1. All requests and responses are JSON. Send a UPRN or a UK postcode; get back coordinates and a precision tier. 1,000 successful lookups are free per account, then a one-time £20 unlocks unlimited use. Unmatched lookups never count against your allowance.
Authentication
Get a key from the dashboard or via POST /v1/signup. The demo endpoints below work without a key.
Precision & coverage
Every response carries a precision field:
| Tier | Meaning |
|---|---|
| property | Exact building coordinate, via a UPRN or an address match against the register. matched_via says which. |
| postcode | Postcode-centroid fallback. Typically 50 m – several hundred metres from the building. |
| unmatched | Nothing resolved. Free — not counted against your allowance. |
Property-level coverage: England & Wales. Postcode centroids: England, Wales, Scotland. Northern Ireland (BT) postcodes return unmatched for data-licensing reasons.
Single geocode
| Param | Notes |
|---|---|
uprn | Positive integer, up to 12 digits. Tried first. |
postcode | UK postcode, any casing or spacing. |
address | Optional address text. Fuzzy-matched against the register within the postcode; a confident match returns building-level coordinates with matched_via: "address" and a confidence score. |
curl -H "X-API-Key: $KEY" \
"BASE/v1/geocode?uprn=100012"
{
"query": { "uprn": 100012 },
"matched": true,
"precision": "property",
"lat": 51.4566671,
"lon": -2.5591032,
"uprn": 100012
}
Batch geocode
Up to 500 queries per call, answered in order. The response includes a per-tier summary. This is what the upload tool uses under the hood.
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{ "queries": [ {"uprn": 100012}, {"postcode": "SW1A 1AA"} ] }' \
"BASE/v1/geocode/batch"
{
"results": [
{ "query": {"uprn": 100012}, "matched": true, "precision": "property",
"lat": 51.4566671, "lon": -2.5591032, "uprn": 100012 },
{ "query": {"postcode": "SW1A 1AA"}, "matched": true, "precision": "postcode",
"lat": 51.5010, "lon": -0.1416 }
],
"summary": { "property": 1, "postcode": 1, "unmatched": 0 }
}
Demo endpoints
No key required — these power the site's try-it box and the tool's 25-row preview. Same response shapes as above. Allowance: 300 lookups per IP per day; the batch form accepts up to 25 queries per call and returns demo_remaining.
Signup
curl -X POST -H "Content-Type: application/json" \
-d '{ "email": "you@company.co.uk" }' "BASE/v1/signup"
{ "api_key": "…", "usage_count": 0, "free_limit": 1000, "unlocked": false }
One key per email. The key is shown once in the response and also emailed to you.
Forgotten keys: send { "email": "..." } and the key is re-emailed to that address (the response never reveals whether an account exists).
Usage
curl -H "X-API-Key: $KEY" "BASE/v1/usage"
{
"email": "you@company.co.uk",
"usage_count": 342,
"free_limit": 1000,
"unlocked": false,
"breakdown": { "property": 291, "postcode": 44, "unmatched": 7 }
}
Checkout
Returns a Stripe Checkout URL for the one-time £20 unlock. On completion your key becomes unlimited — nothing else changes.
curl -X POST -H "X-API-Key: $KEY" "BASE/v1/checkout"
{ "checkout_url": "https://checkout.stripe.com/c/pay/…" }
Errors & limits
| Status | Meaning |
|---|---|
| 400 | Malformed request — missing or invalid parameters. |
| 401 | invalid_api_key |
| 402 | free_tier_exhausted — body includes checkout_url. Unlock for £20 once. |
| 429 | Rate limited — 600 requests/minute per key, or the daily demo allowance. |
{
"error": "free_tier_exhausted",
"usage_count": 1000,
"free_limit": 1000,
"checkout_url": "BASE/dashboard"
}
Rate limits protect the infrastructure, not revenue: 600 requests/minute per key, 3 signups per IP per day.