Replacing getAddress.io? Free drop-in replacement →
·

API Reference

All endpoints return JSON. Authentication uses Authorization: Api-Key YOUR_KEY on every request.

Base URL: https://homedata.co.uk/api/v1
Legacy endpoints: https://api.homedata.co.uk
💡

Two base URLs. Newer endpoints (properties, address, broadband, schools, crime, listings) use https://homedata.co.uk/api/v1/ — all auth and rate limiting is handled here. Older endpoints (EPC, risks, deprivation, price trends, comparables, sales) still use https://api.homedata.co.uk/api/. Both use the same API key. We're migrating everything to /api/v1/ — new integrations should prefer V1 paths where available.

Transparent call-weighted pricing. Most endpoints cost 1 call. Premium endpoints use weighted billing: address find/postcode 2 calls, address retrieve 5 calls, comparables 10 calls, solar 5 calls. Every response includes an X-Call-Weight header. View pricing →
GET

Property Intelligence

/api/v1/properties/{uprn}
Core Property 1 call England ✓ Wales ✓ Scotland ~ N. Ireland ~

Full property record including address, type, tenure, bedrooms, floor area, EPC, construction age, and sold dates. Returns data for any of the UK's 29M+ addressable properties.

Auth: API key required
Response time: ~40ms (lite) / ~300ms (full)
cURL
curl https://homedata.co.uk/api/v1/properties/10093609154 \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://homedata.co.uk/api/v1/properties/10093609154",
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()["data"]
print(data["address"]["full_address"])
JavaScript
const response = await fetch(
  "https://homedata.co.uk/api/v1/properties/10093609154",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
console.log(data.full_address);
View example response
{
  "uprn": 10093609154,
  "usrn": 74503415,
  "udprn": 53129037,
  "full_address": "APARTMENT 1009, CHAPMAN HOUSE, SALFORD, M3 5FH",
  "address": "Apartment 1009 Chapman House",
  "postcode": "M3 5FH",
  "outward_postcode": "M3",
  "building_name": "CHAPMAN HOUSE",
  "street_name": "TRINITY WAY",
  "town_name": "SALFORD",
  "property_type": "Flat",
  "built_form": "Purpose Built",
  "construction_age_band": "2007-2011",
  "bedrooms": 2,
  "bathrooms": 1,
  "habitable_rooms": 3,
  "epc_floor_area": 56.0,
  "internal_area_sqm": 56.0,
  "current_energy_efficiency": 84,
  "current_energy_rating": "B",
  "potential_energy_efficiency": 84,
  "tenure": "Leasehold",
  "council_tax_band": "C",
  "has_garden": false,
  "has_parking": false,
  "windows_type": "Double glazed",
  "last_sold_date": "2019-11-15",
  "last_sold_price": 135000,
  "latitude": 53.4851,
  "longitude": -2.2537
}

80+ fields available — see Data Dictionary for the full list.
GET

EPC & Energy

/api/epc-checker/{uprn}/
Core Property 1 call England ✓ Wales ✓ Scotland ~ N. Ireland ✗

Energy Performance Certificate data. Returns current and potential energy efficiency scores (1–100), last EPC date, floor area, construction age band, and certificate ID.

Auth: API key required
Response time: ~190ms
cURL
curl https://api.homedata.co.uk/api/epc-checker/100023336956/ \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/epc-checker/100023336956/",
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
epc = response.json()
print(f"Rating: {epc['current_energy_efficiency']}")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/epc-checker/100023336956/",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const epc = await response.json();
console.log(`Rating: ${epc.current_energy_efficiency}`);
View example response
{
  "uprn": 10093609154,
  "current_energy_efficiency": 84,
  "potential_energy_efficiency": 84,
  "last_epc_date": "2020-07-28",
  "epc_floor_area": 59,
  "construction_age_band": "2007-2011",
  "epc_id": "1813679032512020072814144822200478"
}
GET

Environmental Risks

/api/risks/{risk_type}/?uprn={uprn}
Risk & Environment 1 call England ✓ Wales ✓ Scotland ✓ N. Ireland ~

Environmental risk assessment for any UK property. Returns risk level, score, and contextual data. Use all to get every risk type in a single request.

Auth: API key required
Response time: ~350ms (single) / ~800ms (all)

Available risk types

flood radon noise landfill coal_mining invasive_plants air_quality_today all
cURL
# Single risk type
curl "https://api.homedata.co.uk/api/risks/flood/?uprn=100023336956" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# All risk types in one call
curl "https://api.homedata.co.uk/api/risks/all/?uprn=100023336956" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/risks/flood/",
    params={"uprn": "100023336956"},
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
for risk in data["results"]:
    print(f"{risk['risk_type']}: {risk['label']} (score {risk['score']})")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/risks/flood/?uprn=100023336956",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
data.results.forEach(r =>
  console.log(`${r.risk_type}: ${r.label} (score ${r.score})`)
);
View example response
{
  "risk_type": "flood",
  "uprn": 100023336956,
  "location": {
    "lat": 51.503541,
    "lon": -0.12767
  },
  "results": [
    {
      "risk_type": "flood_rivers_sea",
      "label": "Very low",
      "score": 1,
      "score_unit": "band",
      "intersects": true,
      "distance_m": 0,
      "radius_description": "At property",
      "properties": {
        "description": "Less than 1 in 1,000 chance of flooding each year"
      }
    },
    {
      "risk_type": "flood_surface_water",
      "label": "Low",
      "score": 2,
      "score_unit": "band",
      "intersects": true,
      "distance_m": 0,
      "radius_description": "At property",
      "properties": {
        "description": "Between 1 in 1,000 and 1 in 100 chance of flooding each year"
      }
    }
  ]
}
GET

Deprivation Index

/api/deprivation/?postcode={postcode}
Risk & Environment 1 call England ✓ Wales ~ Scotland ✗ N. Ireland ✗

English Indices of Multiple Deprivation for any postcode. Returns overall score plus individual domains: income, employment, education, health, crime, housing, and environment.

Coverage note: IMD data covers England only (Scotland, Wales, and Northern Ireland use separate indices). Dataset loading is ongoing — the following postcode areas are not yet available: SW, M, SM, SN, SO, SP, SR, SS, ST, SY, ME, MK, WA, RM, HA, BD, BL, BH, GU, HP, HD, HG, HR and parts of N, S.

Working areas include: SE, E, NW, W, NE, B (Birmingham), L (Liverpool), LS (Leeds), OX (Oxford), BS (Bristol), PE, YO, and most of the Midlands and North East.

If you receive a "Postcode not found" response, try SE1 7PB or E1 6AN to verify your API key is working correctly. This is a data coverage gap, not an auth issue.

Auth: API key required
Coverage: England only
Response time: ~165ms
Parameters: postcode (required) — full UK postcode
cURL
curl "https://api.homedata.co.uk/api/deprivation/?postcode=E1%206AN" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/deprivation/",
    params={"postcode": "E1 6AN"},
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
imd = response.json()
print(f"Decile: {imd['overall']['decile']}/10")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/deprivation/?postcode=E1%206AN",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const imd = await response.json();
console.log(`Decile: ${imd.overall.decile}/10`);
View example response
{
  "postcode": "E1 6AN",
  "lsoa": { "code": "E01032739", "name": "City of London 001F" },
  "lad": { "code": "E09000001", "name": "City of London" },
  "overall": {
    "rank": 25325,
    "decile": 8,
    "score": 3,
    "label": "Fairly High Deprivation",
    "short_label": "Fairly High",
    "lad_rank": 267,
    "lad_rank_description": "Local authority ranks 267 out of 317"
  },
  "domains": [
    {
      "domain": "income",
      "label": "Income",
      "description": "Proportion of population experiencing deprivation relating to low income",
      "rank": 33530,
      "decile": 10,
      "score": 1,
      "score_label": "Very High Deprivation"
    },
    { "domain": "employment", "rank": 29007, "decile": 9, "score": 2, ... },
    { "domain": "education", "rank": 29964, "decile": 9, "score": 2, ... },
    { "domain": "health", "rank": 20214, "decile": 6, "score": 5, ... },
    { "domain": "crime", "rank": 31628, "decile": 10, "score": 1, ... },
    { "domain": "housing", "rank": 17995, "decile": 6, "score": 5, ... },
    { "domain": "environment", "rank": 2191, "decile": 1, "score": 10, ... }
  ],
  "metadata": {
    "source": "MHCLG English Indices of Deprivation 2019",
    "total_lsoas": 33755,
    "score_explanation": "Score is 1-10 where 10 = least deprived"
  }
}
GET

Price Distributions

/api/price_distributions/{outcode}/
Market & Pricing 1 call England ✓ Wales ✓ Scotland ✓ N. Ireland ✗

Price distribution data for an outcode. Shows percentile breakdowns (25th, 50th, 75th) and averages by property type, useful for market segmentation and pricing analysis.

Auth: API key required
Response time: ~500ms (cached) / ~5s (uncached, first request)
Parameters: outcode (path) — UK outcode (e.g. E1, SW1A)
cURL
curl https://api.homedata.co.uk/api/price_distributions/E1/ \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/price_distributions/E1/",
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
for price_range, count in data["bins"].items():
    print(f"£{price_range}: {count} properties")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/price_distributions/E1/",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
Object.entries(data.bins).forEach(([range, count]) =>
  console.log(`£${range}: ${count} properties`)
);
View example response
{
  "outcode": "E1",
  "bins": {
    "125000-695000": 342,
    "695000-1265000": 187,
    "1265000-1835000": 45,
    "1835000-2405000": 12,
    "2405000-2975000": 3
  }
}
GET

Comparables

Beta
/api/comparables/{uprn}/
Market & Pricing 2 calls — premium England ✓ Wales ✓ Scotland ✓ N. Ireland ✗

Find comparable sold properties near a given UPRN. Uses PostGIS spatial queries to find nearby sales with similar characteristics.

Auth: API key required
Response time: ~250ms (cached) / ~600ms (uncached)
cURL
curl https://api.homedata.co.uk/api/comparables/100023336956/ \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/comparables/100023336956/",
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
comps = response.json()
print(f"Found {comps['total_results']} comparables")
for c in comps["comparables"]:
    print(f"{c['address']}: £{c['sold_let_price']:,} ({c['distance_meters']:.0f}m away)")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/comparables/100023336956/",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const comps = await response.json();
console.log(`Found ${comps.total_results} comparables`);
comps.comparables.forEach(c =>
  console.log(`${c.address}: £${c.sold_let_price?.toLocaleString()} (${Math.round(c.distance_meters)}m away)`)
);
View example response
{
  "reference_uprn": 100023336956,
  "filters": {
    "bedrooms": null,
    "property_type": null,
    "count": 20,
    "start_date": "2025-03-13",
    "end_date": "2026-03-13",
    "event_type": "all"
  },
  "comparables": [
    {
      "uprn": 10033541876,
      "address": "Flat 2, 14 Downing Street",
      "postcode": "SW1A 2AB",
      "bedrooms": 2,
      "bathrooms": 1,
      "epc_floor_area": 68.0,
      "property_type": "Flat",
      "construction_age_band": "1900-1929",
      "current_energy_efficiency": 62,
      "distance_meters": 45.2,
      "sale_id": 87234,
      "txid": "A1B2C3D4E5F6",
      "sold_let_date": "2025-11-15",
      "sold_let_price": 925000,
      "listing_price": 950000,
      "transaction_type": "Sale",
      "is_complete": true,
      "latest_listing": {
        "listing_id": "HD173456789",
        "added_date": "2025-08-20",
        "latest_price": 950000,
        "latest_status": "Sold STC",
        "source": "Home.co.uk"
      },
      "title": {
        "title_no": "TGL123456",
        "estate_interest": "Leasehold",
        "title_class": "Absolute"
      }
    }
  ],
  "total_results": 18,
  "response_time_seconds": 0.2341
}
GET

Address by Postcode

/api/address/postcode/{postcode}/
Core Property 1 call England ✓ Wales ✓ Scotland ✓ N. Ireland ✓

List all addresses in a postcode. Returns UPRNs so you can chain into other endpoints. Use URL-encoded or concatenated postcodes (e.g. SW1A2AA or SW1A%202AA).

Auth: API key required — Authorization: Api-Key YOUR_KEY
Response time: ~195ms
cURL
curl https://api.homedata.co.uk/api/address/postcode/SW1A2AA/ \
  -H "Authorization: Api-Key YOUR_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/address/postcode/SW1A2AA/",
    headers={"Authorization": "Api-Key YOUR_KEY"},
)
data = response.json()
for addr in data["addresses"]:
    print(f"{addr['address']} (UPRN: {addr['uprn']})")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/address/postcode/SW1A2AA/",
  { headers: { "Authorization": "Api-Key YOUR_KEY" } }
);
const data = await response.json();
data.addresses.forEach(a =>
  console.log(`${a.address} (UPRN: ${a.uprn})`)
);
View example response
{
  "postcode": "SW1A 2AA",
  "count": 1,
  "addresses": [
    {
      "uprn": 100023336956,
      "address": "PRIME MINISTER & FIRST LORD OF THE TREASURY, 10 DOWNING STREET, LONDON, SW1A 2AA",
      "building_name": "",
      "building_number": "10",
      "sub_building": "",
      "street": "Downing Street",
      "town": "London"
    }
  ]
}

⚠️ URL encoding: Use %20 or remove spaces entirely in the URL path. Do NOT use + — it's treated literally in URL paths.

GET

Address Search

/api/address/find/?q={query}
Core Property 1 call England ✓ Wales ✓ Scotland ✓ N. Ireland ✓

Full-text address search powered by Elasticsearch (36M+ UK addresses). Type-ahead autocomplete for address forms and property lookup interfaces. Returns matched addresses with UPRNs for use with the retrieve endpoint.

Auth: API key required — Authorization: Api-Key YOUR_KEY
Parameters: q (required) — search query (minimum 2 characters)
Response time: ~160ms
cURL
curl "https://api.homedata.co.uk/api/address/find/?q=10%20Downing%20Street" \
  -H "Authorization: Api-Key YOUR_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/address/find/",
    params={"q": "10 Downing Street"},
    headers={"Authorization": "Api-Key YOUR_KEY"},
)
results = response.json()
for addr in results["suggestions"]:
    print(f"{addr['address']}, {addr['postcode']}")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/address/find/?q=10%20Downing%20Street",
  { headers: { "Authorization": "Api-Key YOUR_KEY" } }
);
const data = await response.json();
data.suggestions.forEach(a =>
  console.log(`${a.address}, ${a.postcode}`)
);
View example response
{
  "suggestions": [
    {
      "uprn": 100023336956,
      "address": "10 Downing Street",
      "address_line_1": "10 Downing Street",
      "address_line_2": null,
      "town": "London",
      "postcode": "SW1A 2AA"
    },
    {
      "uprn": 10004862792,
      "address": "10 Downing Street",
      "address_line_1": "10 Downing Street",
      "address_line_2": null,
      "town": "Llanelli",
      "postcode": "SA15 2UA"
    }
  ],
  "meta": { "query_type": "address_search", "took_ms": 12, "total": 7 }
}
GET

Address Retrieve

/api/address/retrieve/{uprn}/?level={level}
Core Property 1 call England ✓ Wales ✓ Scotland ✓ N. Ireland ✓

Enriched property data for a known UPRN at three detail levels. Use after Address Search or Address by Postcode to get full property intelligence.

Auth: API key required
Parameters: level (optional) — enrichment level: address (default), property, or full

Enrichment levels

address Address fields, UPRN, coordinates
property + property type, bedrooms, bathrooms, EPC, floor area, last sold price
full + predicted value, construction details, garden/parking, area stats, renovation costs
cURL
# Address only (default)
curl https://api.homedata.co.uk/api/address/retrieve/100023336956/ \
  -H "Authorization: Api-Key YOUR_API_KEY"

# Full property intelligence
curl "https://api.homedata.co.uk/api/address/retrieve/100023336956/?level=full" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/address/retrieve/100023336956/",
    params={"level": "property"},
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
addr = response.json()
print(f"{addr['full_address']} — {addr.get('bedrooms')} bed {addr.get('property_type')}")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/address/retrieve/100023336956/?level=property",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const addr = await response.json();
console.log(`${addr.full_address} — ${addr.bedrooms} bed ${addr.property_type}`);
View example response (level=address)
{
  "uprn": 100023336956,
  "udprn": 7832854,
  "usrn": 8400709,
  "full_address": "10 DOWNING STREET, LONDON, SW1A 2AA",
  "address_line_1": "10 Downing Street",
  "address_line_2": "",
  "address_line_3": "",
  "building_name": "",
  "building_number": "10",
  "sub_building": "",
  "street_name": "Downing Street",
  "locality": "",
  "town_name": "London",
  "post_town": "London",
  "postcode": "SW1A 2AA",
  "outward_postcode": "SW1A",
  "latitude": 51.5033,
  "longitude": -0.1276,
  "level": "address"
}
View example response (level=property)
{
  // ... all address fields above, plus:
  "property_type": "Semi-Detached",
  "bedrooms": 4,
  "predicted_bedrooms": 4,
  "bathrooms": 2,
  "habitable_rooms": 6,
  "floors": 3,
  "epc_floor_area": 180.0,
  "predicted_floor_area": 175.0,
  "current_energy_efficiency": 62,
  "potential_energy_efficiency": 78,
  "last_epc_date": "2020-07-28",
  "last_sold_date": "2019-11-15",
  "last_sold_price": 925000,
  "last_sold_adjusted_price": 980000,
  "classification_code": "RD03",
  "level": "property"
}
GET

Broadband Speeds

Free
/api/v1/broadband?postcode={postcode}
Area Intelligence FREE — uncounted England ✓ Wales ✓ Scotland ✓ N. Ireland ✓

Broadband speed and coverage data for any UK postcode — average and max download/upload speeds, superfast/ultrafast/gigabit availability percentages, and full-fibre coverage. Data sourced from Ofcom's Connected Nations report, updated annually. Free on all plans — PropertyData charges 1 credit for the equivalent endpoint.

Auth: API key required — Authorization: Api-Key YOUR_KEY
Parameters: postcode (required) — UK postcode, spaces optional
Response time: ~50ms (cached 24h) / ~100ms (cold)
Data source: Ofcom Connected Nations (annual)

Parameters

Parameter Type Required Description
postcode string required UK postcode. Spaces are stripped automatically. e.g. SW1A2AA or SW1A 2AA
cURL
curl "https://homedata.co.uk/api/v1/broadband?postcode=SW1A2AA" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://homedata.co.uk/api/v1/broadband",
    params={"postcode": "SW1A2AA"},
    headers={"Authorization": "Api-Key YOUR_API_KEY"},
)
data = response.json()
print(f"Avg download: {data['avg_download_speed']} Mbps")
print(f"Gigabit available: {data['gigabit_available_pct']}%")
JavaScript
const response = await fetch(
  "https://homedata.co.uk/api/v1/broadband?postcode=SW1A2AA",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
console.log(`Avg download: ${data.avg_download_speed} Mbps`);
console.log(`Gigabit available: ${data.gigabit_available_pct}%`);
View example response
{
  "postcode": "SW1A 2AA",
  "avg_download_speed": 67.4,
  "max_download_speed": 362.0,
  "avg_upload_speed": 18.2,
  "max_upload_speed": 36.0,
  "superfast_available_pct": 98.0,
  "ultrafast_available_pct": 72.0,
  "gigabit_available_pct": 45.0,
  "full_fibre_available_pct": 45.0,
  "below_uso_pct": 0.5,
  "connections_count": 24,
  "premises_count": 26,
  "data_year": 2025
}

Response fields

Field Type Description
avg_download_speed float Average download speed in Mbps
max_download_speed float Maximum download speed in Mbps
avg_upload_speed float Average upload speed in Mbps
max_upload_speed float Maximum upload speed in Mbps
superfast_available_pct float % of premises with superfast broadband (≥30 Mbps) available
ultrafast_available_pct float % of premises with ultrafast broadband (≥300 Mbps) available
gigabit_available_pct float % of premises with gigabit-capable connectivity
full_fibre_available_pct float % of premises with full-fibre (FTTP) available
below_uso_pct float % of premises below the Universal Service Obligation (10 Mbps down / 1 Mbps up)
connections_count integer Number of active broadband connections at this postcode
premises_count integer Total addressable premises at this postcode
data_year integer Year of the Ofcom Connected Nations dataset (e.g. 2025)

Error codes

Status Code Meaning
422 missing_postcode No postcode query parameter provided
422 invalid_postcode Postcode doesn't match UK format (e.g. SW1A 2AA)
404 not_found Valid postcode but no Ofcom data available for it
503 service_unavailable Broadband data temporarily unavailable
GET

Boundaries Autocomplete

No auth
/api/boundaries/autocomplete/?q={query}
FREE — uncounted England ✓ Wales ✓ Scotland ✓ N. Ireland ✓

Search for administrative boundaries (local authorities, wards, parishes) by name. Returns boundary metadata. Available on all plans including Free — no API key required.

Auth: None required (open endpoint)
Response time: ~280ms
cURL
curl "https://api.homedata.co.uk/api/boundaries/autocomplete/?q=islington"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/boundaries/autocomplete/",
    params={"q": "islington"}
)
data = response.json()
for b in data["results"]:
    print(f"{b['name']} (level {b['admin_level']})")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/boundaries/autocomplete/?q=islington"
);
const data = await response.json();
data.results.forEach(b =>
  console.log(`${b.name} (level ${b.admin_level})`)
);
View example response
{
  "results": [
    {
      "id": 14445,
      "name": "London Borough of Islington",
      "display_name": "London Borough of Islington, Greater London, England",
      "admin_level": 8
    }
  ]
}
GET

Land Registry Titles

/api/property_lr_titles/{uprn}/
Planning & Land 1 call England ✓ Wales ✓ Scotland ✗ N. Ireland ✗

Land Registry title boundary data for a property. Returns a GeoJSON Feature with the title polygon.

Auth: API key required
Response format: GeoJSON Feature
cURL
curl https://api.homedata.co.uk/api/property_lr_titles/100023336956/ \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/property_lr_titles/100023336956/",
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
feature = response.json()  # GeoJSON Feature
print(f"Geometry type: {feature['geometry']['type']}")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/property_lr_titles/100023336956/",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const feature = await response.json(); // GeoJSON Feature
console.log(`Geometry: ${feature.geometry.type}`);
View example response
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [-0.12764, 51.50332],
        [-0.12758, 51.50338],
        [-0.12771, 51.50341],
        [-0.12777, 51.50335],
        [-0.12764, 51.50332]
      ]
    ]
  },
  "properties": {
    "title_no": "NGL936618",
    "property": 100023336956,
    "record_status": "A",
    "estate_interest_code": "F",
    "estate_interest": "Freehold",
    "title_class_code": "ABS",
    "title_class": "Absolute",
    "has_restrictive_covenant": false,
    "created_at": "2024-06-15T10:30:00Z",
    "updated_at": "2024-06-15T10:30:00Z"
  }
}
GET

Property Sales

/api/property_sales/?uprn={uprn}
Core Property 1 call England ✓ Wales ✓ Scotland ✗ N. Ireland ✗

Sale records including listing dates, prices, and associated agent listings. Paginated results. A filter parameter (uprn, property, or id) is required — requests without a filter return 400.

Auth: API key required
Parameters: uprn (required), page (optional, pagination)
cURL
curl "https://api.homedata.co.uk/api/property_sales/?uprn=10093609154" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/property_sales/",
    params={"uprn": "10093609154"},
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
for sale in data["results"]:
    print(f"{sale['transaction_type']}: £{sale.get('sold_let_price', 'N/A')}")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/property_sales/?uprn=10093609154",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
data.results.forEach(s =>
  console.log(`${s.transaction_type}: £${s.sold_let_price ?? 'N/A'}`)
);
View example response
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 4521876,
      "sold_let_date": "2019-11-15",
      "first_listing_date": "2019-07-22",
      "sold_let_price": 135000,
      "is_complete": true,
      "is_available": false,
      "property": 10093609154,
      "txid": "F7E8D9C0B1A2",
      "transaction_type": "Sale",
      "property_listings": [
        {
          "id": 8734521,
          "alias": "Listing 1",
          "listing_id": "HD145678901",
          "added_date": "2019-07-22",
          "latest_price": 140000,
          "latest_status": "Sold STC",
          "transaction_type": "Sale",
          "source": "Home.co.uk",
          "display_address": "Chapman House, Salford, M3 5FH",
          "bedrooms": 2,
          "bathrooms": 1,
          "images": ["https://images.homedata.co.uk/..."]
        }
      ],
      "property_sale_events": [
        {
          "id": 12345678,
          "event_status": "Sold STC",
          "event_date": "2019-10-03"
        },
        {
          "id": 12345679,
          "event_status": "Completed",
          "event_date": "2019-11-15"
        }
      ]
    }
  ]
}
GET

Market Activity

/api/property_sale_events/
Market Data 1 call England ✓ Wales ✓ Scotland ✗ N. Ireland ✗

The full listing lifecycle for any property — every event from first instruction to completion. Returns Added, Reduced, Under Offer, Sold STC, Withdrawn, and Completed events, each timestamped and priced. Unlike Land Registry (completions only, 3–6 month lag), this includes properties that were listed but never sold. 30 years of data from Home.co.uk.

Use Property Sales to get sale/listing IDs for a UPRN, then query this endpoint for the full event timeline. Each event includes type, date, price, and source.

Auth: API key required
List: GET /api/property_sale_events/ — paginated list of all events (25 per page)
Detail: GET /api/property_sale_events/{id}/ — single event by ID
Filter: id (exact match)
Event types: Added · Reduced · Under Offer · Sold STC · Withdrawn · Completed · Let · Sale Cancelled

Tip: To get events for a specific property, first call /api/property_sales/?uprn={uprn} to get the listing IDs, then look up events by ID. Filtering by listing, uprn, and event_type is coming soon.

cURL
# List recent market activity events (paginated)
curl "https://api.homedata.co.uk/api/property_sale_events/" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# Get a specific event by ID
curl "https://api.homedata.co.uk/api/property_sale_events/9823401/" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

headers = {"Authorization": "Api-Key YOUR_API_KEY"}

# Step 1 — get listing IDs for a property via Property Sales
sales = requests.get(
    "https://api.homedata.co.uk/api/property_sales/",
    params={"uprn": "100023336956"},
    headers=headers
).json()["results"]

# Step 2 — get event timeline (paginated list)
events = requests.get(
    "https://api.homedata.co.uk/api/property_sale_events/",
    headers=headers
).json()["results"]

for e in events:
    price = f"£{e['price']:,}" if e['price'] else "—"
    print(f"{e['date']}  {e['event_type']:<15}  {price}")
JavaScript
const headers = { "Authorization": "Api-Key YOUR_API_KEY" };

// Get a specific event by ID
const resp = await fetch(
  "https://api.homedata.co.uk/api/property_sale_events/9823401/",
  { headers }
);
const event = await resp.json();
console.log(`${event.date}  ${event.event_type}  £${event.price?.toLocaleString() ?? '—'}`);
View example response
{
  "count": 4,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 9823401,
      "event_type": "Added",
      "date": "2024-01-12",
      "price": 595000,
      "source": "Home.co.uk",
      "listing": 4821,
      "sale": null
    },
    {
      "id": 9823402,
      "event_type": "Reduced",
      "date": "2024-02-28",
      "price": 575000,
      "source": "Home.co.uk",
      "listing": 4821,
      "sale": null
    },
    {
      "id": 9823404,
      "event_type": "Sold STC",
      "date": "2024-03-22",
      "price": 568000,
      "source": "Home.co.uk",
      "listing": 4821,
      "sale": null
    },
    {
      "id": 9823405,
      "event_type": "Completed",
      "date": "2024-06-14",
      "price": 568000,
      "source": "Land Registry",
      "listing": 4821,
      "sale": 31204
    }
  ]
}
GET

Live Listings

/api/live-listings/search/?boundary_id={id}
Market & Pricing 1 call England ✓ Wales ✓ Scotland ✓ N. Ireland ~

Search currently active UK property listings. Filter by boundary, property type, price range, and bedrooms. Returns paginated results with price, property details, and UPRN for chaining into other endpoints.

💡

Two-step workflow: Use Boundaries Autocomplete to find a boundary_id for your location, then pass it here. For example, search for "Manchester" → get id: 14624 → use boundary_id=14624.

Auth: API key required
Response time: ~560ms

Parameters

Name Type Description
boundary_id int Filter by boundary ID (from Boundaries Autocomplete)
transaction_type string "Sale" or "Rental"
bedrooms int Number of bedrooms
min_price int Minimum price filter
max_price int Maximum price filter
sort string added_date, -added_date (default), latest_price, -latest_price
page / page_size int Pagination (default page_size: 200, max: 200)
cURL
# Step 1: Find the boundary ID for your location
curl "https://api.homedata.co.uk/api/boundaries/autocomplete/?q=Manchester"
# → {"results": [{"id": 14624, "name": "Manchester", ...}]}

# Step 2: Search listings within that boundary
curl "https://api.homedata.co.uk/api/live-listings/search/?boundary_id=14624&transaction_type=Sale&bedrooms=3" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

# Step 1: Find boundary ID
boundaries = requests.get(
    "https://api.homedata.co.uk/api/boundaries/autocomplete/",
    params={"q": "Manchester"}
).json()
boundary_id = boundaries["results"][0]["id"]

# Step 2: Search listings
response = requests.get(
    "https://api.homedata.co.uk/api/live-listings/search/",
    params={
        "boundary_id": boundary_id,
        "transaction_type": "Sale",
        "max_price": 400000
    },
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
print(f"Found {data['count']} listings")
for listing in data["results"][:5]:
    print(f"£{listing['latest_price']:,} — {listing['display_address']}")
JavaScript
// Step 1: Find boundary ID
const boundaries = await fetch(
  "https://api.homedata.co.uk/api/boundaries/autocomplete/?q=Manchester"
).then(r => r.json());
const boundaryId = boundaries.results[0].id;

// Step 2: Search listings
const response = await fetch(
  `https://api.homedata.co.uk/api/live-listings/search/?boundary_id=${boundaryId}&transaction_type=Sale`,
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
console.log(`Found ${data.count} listings`);
data.results.slice(0, 5).forEach(l =>
  console.log(`£${l.latest_price?.toLocaleString()} — ${l.display_address}`)
);
View example response
{
  "count": 3616,
  "page": 1,
  "page_size": 200,
  "total_pages": 19,
  "results": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "listing_id": "7391803",
      "branch_id": "3741",
      "property_uprn": 10093895962,
      "sale_id": 4521876,
      "display_address": "Jurston Fields, Wellington",
      "transaction_type": "Sale",
      "latest_status": "For sale",
      "latest_price": 270000,
      "source": "Home.co.uk",
      "bedrooms": 2,
      "bathrooms": 2,
      "reception_rooms": 1,
      "listing_property_type": "Detached"
    },
    ...
  ]
}
POST

Bulk Export

Growth+
POST /api/v1/listings/export
Market & Pricing 1 call / 10 rows England ✓ Wales ✓ Scotland ✓ N. Ireland ~

Search property listings with filters and download the results as CSV or JSON. Perfect for bulk data extraction — filter by area, price, days on market, property type, and more. Returns full addresses, prices, agent details, and coordinates.

💰

Billing: 1 API call per 10 rows returned (minimum 1 call). A 500-row export uses 50 API calls. Available on Growth (max 1,000 rows/request), Pro, and Scale (max 5,000 rows/request) plans.

Auth: API key required (Growth tier minimum)
Method: POST (JSON body)
Response: JSON or CSV (streamed)

Request Body (JSON)

Name Type Description
filters required object Search filters (see below). Must include at least one geographic scope.
fields string[] Fields to include in output. Default: address, postcode, price, bedrooms, property_type, status, dom, listed_date, agent, reductions
format string "csv" (default) or "json"
limit int Max rows to return (Growth: 1,000 max, Pro/Scale: 5,000 max)
offset int Skip N rows for pagination (default: 0)

Filter Parameters

Name Type Description
postcode string Outcode or full postcode (e.g. "NR1" or "NR1 3JQ")
boundary_id int Boundary ID from Boundaries Autocomplete
lat / lng float Coordinates for radius search
radius_miles float Radius in miles (0.1–25, default: 5). Used with postcode or lat/lng
min_price / max_price int Asking price range filter
property_type string[] Property types: Detached, Semi-Detached, Terraced, Flat, Bungalow
bedrooms_min / bedrooms_max int Bedroom count range
transaction_type string "Sale" or "Rental"
min_dom int Minimum days on market (e.g. 90 for stale listings)
listed_since date Only listings added after this date (ISO format)
is_new_build bool Filter to new-build properties only

Available Fields

listing_id address postcode uprn price original_price bedrooms bathrooms property_type transaction_type status dom listed_date agent agent_branch reductions lat lng construction_age has_address_match
cURL
# Export all 3-bed properties in NR1 under £300k as CSV
curl -X POST "https://homedata.co.uk/api/v1/listings/export" \
  -H "Authorization: Api-Key YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "postcode": "NR1",
      "min_price": 100000,
      "max_price": 300000,
      "bedrooms_min": 3,
      "transaction_type": "Sale"
    },
    "fields": ["address", "postcode", "price", "bedrooms", "dom", "agent", "reductions"],
    "format": "csv",
    "limit": 500
  }' \
  -o export.csv
Python
import requests

response = requests.post(
    "https://homedata.co.uk/api/v1/listings/export",
    headers={"Authorization": "Api-Key YOUR_API_KEY"},
    json={
        "filters": {
            "postcode": "NR1",
            "min_dom": 90,
            "max_price": 300000
        },
        "fields": ["address", "price", "dom", "reductions", "agent"],
        "format": "json",
        "limit": 1000
    }
)
data = response.json()
print(f"Exported {data['returned']} listings ({data['api_calls_used']} API calls used)")
for row in data["data"][:5]:
    print(f"£{row['price']:,} — {row['address']} — {row['dom']} days, {row['reductions']} reductions")
JavaScript
const response = await fetch("https://homedata.co.uk/api/v1/listings/export", {
  method: "POST",
  headers: {
    "Authorization": "Api-Key YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    filters: { postcode: "NR1", min_dom: 90 },
    fields: ["address", "price", "dom", "lat", "lng"],
    format: "json"
  })
});
const data = await response.json();
console.log(`Exported ${data.returned} listings (${data.api_calls_used} calls used)`);
View example JSON response
{
  "status": "success",
  "total_results": 847,
  "returned": 847,
  "offset": 0,
  "format": "json",
  "api_calls_used": 85,
  "data": [
    {
      "address": "14 Earlham Road, Norwich, NR2 3DB",
      "postcode": "NR2 3DB",
      "price": 275000,
      "bedrooms": 3,
      "property_type": "Semi-Detached",
      "status": "active",
      "dom": 142,
      "listed_date": "2025-09-15",
      "agent": "Savills",
      "reductions": 3
    },
    {
      "address": "8 Prince of Wales Road, Norwich, NR1 1LB",
      "postcode": "NR1 1LB",
      "price": 195000,
      "bedrooms": 2,
      "property_type": "Flat",
      "status": "active",
      "dom": 30,
      "listed_date": "2026-02-15",
      "agent": "William H Brown",
      "reductions": 0
    },
    ...
  ]
}
View example CSV output
address,postcode,price,bedrooms,property_type,status,dom,listed_date,agent,reductions
"14 Earlham Road, Norwich, NR2 3DB",NR2 3DB,275000,3,Semi-Detached,active,142,2025-09-15,Savills,3
"8 Prince of Wales Road, Norwich, NR1 1LB",NR1 1LB,195000,2,Flat,active,30,2026-02-15,William H Brown,0
GET

Council Tax Band

/api/council_tax_band/?postcode={postcode}&building_number={number}
Core Property 1 call England ✓ Wales ✓ Scotland ✗ N. Ireland ✗

Look up the council tax band for any UK residential property. Data sourced live from HMRC's Valuation Office Agency (VOA). Returns the band (A–H) and verified address.

Different from other endpoints: This endpoint uses postcode + building_number (or building_name) — not a UPRN. If you only have a UPRN, use Address Retrieve first to get the building number, then call this endpoint.

Auth: API key required
Parameters: postcode (required), building_number or building_name (one required)
Note: Live VOA lookup — response time 1–3s. England and Wales only.
cURL
curl "https://api.homedata.co.uk/api/council_tax_band/?postcode=SW1A+2AA&building_number=10" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/council_tax_band/",
    params={
        "postcode": "SW1A 2AA",
        "building_number": "10"
    },
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
print(f"Council Tax Band: {data['council_tax_band']}")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/council_tax_band/?postcode=SW1A+2AA&building_number=10",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
console.log(`Council Tax Band: ${data.council_tax_band}`);
View example response
{
  "address": "10 DOWNING STREET, LONDON, SW1A 2AA",
  "council_tax_band": "H"
}
GET

Planning Applications

/api/planning/search/?postcode={postcode}
Planning & Land 1 call England ✓ Wales ✓ Scotland ~ N. Ireland ~

Search planning applications near a UK location. National coverage across 417 Local Planning Authorities with ~20M geocoded applications. Returns current and historical planning data including application status, type, decision dates, and case officer details.

Auth: API key required
Response time: ~200ms (cached) / ~400ms (cold)
Coverage: 417 LPAs across England, Scotland, Wales

Parameters

postcode UK postcode (e.g., SW1A 2AA). Either postcode or lat+lng required.
lat, lng Coordinates for centre of search (alternative to postcode).
radius_km Search radius in km. Default: 0.5, max: 5.
days Only applications from last N days. Default: 90, max: 365.
type Filter: Full, Outline, Heritage, Trees, Conditions.
status Filter: Undecided, Approved, Refused, Withdrawn.
page Page number (25 results per page).
cURL
curl "https://api.homedata.co.uk/api/planning/search/?postcode=SW1A+2AA&radius_km=0.5&days=90" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://api.homedata.co.uk/api/planning/search/",
    params={"postcode": "SW1A 2AA", "radius_km": 0.5, "days": 90},
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
for app in data["results"]:
    print(f"{app['reference']} — {app['description'][:80]}...")
JavaScript
const response = await fetch(
  "https://api.homedata.co.uk/api/planning/search/?postcode=SW1A+2AA&radius_km=0.5&days=90",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
console.log(`${data.count} planning applications found`);
data.results.forEach(app => console.log(`${app.reference}: ${app.status}`));
Example response
JSON
{
  "count": 47,
  "page": 1,
  "per_page": 25,
  "radius_km": 0.5,
  "days": 90,
  "results": [
    {
      "reference": "26/01372/LBC",
      "address": "10 Downing Street London SW1A 2AA",
      "postcode": "SW1A 2AA",
      "description": "Removal and replacement of internal doors...",
      "status": "Pending",
      "decision": "Undecided",
      "type": "Heritage",
      "size": "Small",
      "authority": "Westminster",
      "ward": "St James's",
      "date_received": "2026-02-25",
      "date_validated": "2026-02-25",
      "date_decided": null,
      "target_decision_date": "2026-04-22",
      "case_officer": "See source",
      "agent_name": "See source",
      "applicant_name": null,
      "num_comments": 0,
      "num_documents": 0,
      "url": "https://idoxpa.westminster.gov.uk/...",
      "location": {
        "longitude": -0.127695,
        "latitude": 51.50354
      },
      "distance_km": 0.0
    }
  ]
}
GET

Agent Statistics

/api/agent_stats/{uprn}/
Market & Pricing 1 call England ✓ Wales ✓ Scotland ~ N. Ireland ✗

Returns estate agent performance statistics for agents operating near a given property. Includes average time on market, sale-to-asking-price ratio, and recent listing counts within 0.3 miles of the UPRN. Useful for comparing agents before instructing.

Auth: API key required
Parameters: uprn (path, required), view=market_share (optional — switch to market share mode)
Response time: ~200ms (cached, 2h TTL) / 5–20s (uncached — ES geo agg + SQL metrics over 200 branches on first request)
⏱ First request for a new UPRN triggers full data aggregation and can take up to 20s. Subsequent requests within the 2-hour cache window are fast (~200ms). Consider pre-warming by calling this endpoint at registration time.
cURL
curl https://api.homedata.co.uk/api/agent_stats/100023336956/ \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

UPRN = 100023336956
response = requests.get(
    f"https://api.homedata.co.uk/api/agent_stats/{UPRN}/",
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
agents = response.json()  # flat array
for agent in agents:
    stats = agent["stats"]
    print(f"{agent['agent_name']}: {stats['listing_count']} listings, {stats['avg_sale_percent']}% avg sale")
JavaScript
const uprn = 100023336956;
const response = await fetch(
  `https://api.homedata.co.uk/api/agent_stats/${uprn}/`,
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const agents = await response.json(); // flat array
agents.forEach(a =>
  console.log(`${a.agent_name}: ${a.stats.listing_count} listings, ${a.stats.avg_sale_percent}% avg sale`)
);
View example response
[
  {
    "id": 4521,
    "branch_name": "Chapplins Estate Agents, Havant",
    "agent_name": "Chapplins Estate Agents",
    "sales_phone_number": "023 9247 1234",
    "stats": {
      "listing_count": 52,
      "avg_time_on_market": 67,
      "avg_sale_percent": 98.24,
      "avg_time_to_sstc": 34,
      "avg_time_to_first_offer": 21,
      "avg_latest_price": 345000,
      "count_last_6mo": 28,
      "new_last_30d": 4,
      "reduced_count": 6,
      "recent_listings": [
        {
          "listing_id": "7391803",
          "address": "3 Elm Lane, Havant, PO9 1AB",
          "price": 325000,
          "status": "For sale",
          "sale_price": null,
          "sold_date": null
        }
      ]
    }
  },
  {
    "id": 4522,
    "branch_name": "Leaders, Havant",
    "agent_name": "Leaders",
    "sales_phone_number": "023 9249 5678",
    "stats": {
      "listing_count": 38,
      "avg_time_on_market": 45,
      "avg_sale_percent": 97.1,
      "avg_time_to_sstc": 28,
      "avg_time_to_first_offer": 18,
      "avg_latest_price": 289000,
      "count_last_6mo": 22,
      "new_last_30d": 3,
      "reduced_count": 4,
      "recent_listings": []
    }
  }
]

Note: Response is a flat JSON array (not wrapped in a results key). Each agent includes a nested stats object with performance metrics. avg_sale_percent is the average sale-to-asking-price ratio (e.g. 98.24 = sold at 98.24% of asking). Times are in days.

GET

Crime Data

/api/v1/crime/nearby?postcode={postcode}
Risk & Environment 1 call England ✓ Wales ✓ Scotland ✗ N. Ireland ✓

Search street-level crime near a UK postcode or coordinate. Returns crime counts aggregated by category (burglary, theft, violent crime, etc). Data sourced from Police UK covering England, Wales, and Northern Ireland. Updated monthly.

Auth: API key required
Parameters: postcode (e.g. SW1A 2AA) or lat + lng (required), date (YYYY-MM, optional — defaults to latest), category (optional — filter by crime type)
Coverage: England, Wales, Northern Ireland. Scotland: British Transport Police data only.
Response time: ~50ms (cached, 6h TTL) / 1–5s (uncached — Police UK API latency)
⏱ Uncached requests call the Police UK API which can take 1–5s. Cached responses are near-instant. Data updates monthly.
cURL
curl "https://homedata.co.uk/api/v1/crime/nearby?postcode=SW1A+2AA" \
  -H "Authorization: Api-Key YOUR_API_KEY"

# With date and category filter
curl "https://homedata.co.uk/api/v1/crime/nearby?lat=51.5074&lng=-0.1278&date=2025-12&category=burglary" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://homedata.co.uk/api/v1/crime/nearby",
    params={"postcode": "SW1A 2AA"},
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
print(f"Total crimes: {data['total_crimes']} in {data['month']}")
for cat in data["categories"]:
    print(f"  {cat['label']}: {cat['count']}")
JavaScript
const response = await fetch(
  "https://homedata.co.uk/api/v1/crime/nearby?postcode=SW1A+2AA",
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const data = await response.json();
console.log(`${data.total_crimes} crimes in ${data.month}`);
data.categories.forEach(c =>
  console.log(`  ${c.label}: ${c.count}`)
);
View example response
{
  "total_crimes": 847,
  "month": "2025-12",
  "search_point": {
    "latitude": 51.50354,
    "longitude": -0.127695
  },
  "categories": [
    {
      "category": "violent-crime",
      "label": "Violence and sexual offences",
      "count": 203,
      "latest_month": "2025-12",
      "sample_locations": [
        {
          "street": "On or near Whitehall",
          "latitude": "51.504284",
          "longitude": "-0.126366"
        }
      ]
    },
    {
      "category": "anti-social-behaviour",
      "label": "Anti-social behaviour",
      "count": 156,
      "latest_month": "2025-12",
      "sample_locations": []
    },
    {
      "category": "theft-from-the-person",
      "label": "Theft from the person",
      "count": 112,
      "latest_month": "2025-12",
      "sample_locations": []
    },
    {
      "category": "other-theft",
      "label": "Other theft",
      "count": 98,
      "latest_month": "2025-12",
      "sample_locations": []
    },
    {
      "category": "burglary",
      "label": "Burglary",
      "count": 45,
      "latest_month": "2025-12",
      "sample_locations": []
    }
  ],
  "coverage_note": "England, Wales, and Northern Ireland. Scotland shows British Transport Police data only."
}

Categories: anti-social-behaviour, bicycle-theft, burglary, criminal-damage-arson, drugs, other-crime, other-theft, possession-of-weapons, public-order, robbery, shoplifting, theft-from-the-person, vehicle-crime, violent-crime. Use the category parameter to filter by type, or omit to get all.

GET

Solar Assessment

/api/solar-assessment/{uprn}/
Risk & Environment 2 calls — premium England ✓ Wales ✓ Scotland ✓ N. Ireland ~

Full solar energy potential assessment for a UK property. Returns estimated system size, annual generation, savings, payback period, and CO₂ offset. Based on property roof data, local solar irradiance (120 UK postcode zones), and standard PV calculation models. Designed for solar installers, energy advisors, and home improvement platforms.

Auth: API key required
Parameters: uprn (path, required)
Confidence: High (OS footprint) / Medium (EPC floor area) / Low (bedroom estimate)
Phase 2: LIDAR roof pitch + satellite orientation analysis
cURL
curl https://api.homedata.co.uk/api/solar-assessment/10003469503/ \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

UPRN = 10003469503
response = requests.get(
    f"https://api.homedata.co.uk/api/solar-assessment/{UPRN}/",
    headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
data = response.json()
solar = data["solar_potential"]
print(f"{solar['system_size_kwp']} kWp — £{solar['annual_savings_gbp']}/yr savings")
print(f"Payback: {solar['payback_years']} years ({solar['co2_saved_kg_per_year']} kg CO₂/yr)")
JavaScript
const uprn = 10003469503;
const response = await fetch(
  `https://api.homedata.co.uk/api/solar-assessment/${uprn}/`,
  { headers: { "Authorization": "Api-Key YOUR_API_KEY" } }
);
const { solar_potential: s } = await response.json();
console.log(`${s.system_size_kwp} kWp — £${s.annual_savings_gbp}/yr, payback ${s.payback_years}y`);
View example response
{
  "property": {
    "uprn": 10003469503,
    "address": "14 Acacia Avenue, Manchester, M20 4LN",
    "property_type": "Semi-Detached",
    "bedrooms": 3,
    "construction_age_band": "1950-1966"
  },
  "roof": {
    "estimated_area_m2": 72.0,
    "usable_area_m2": 32.4,
    "material": "Pitched, Slate",
    "has_existing_solar": false,
    "pitch_estimate_degrees": 35,
    "orientation_estimate": "mixed"
  },
  "solar_potential": {
    "max_panels": 18,
    "system_size_kwp": 7.56,
    "annual_generation_kwh": 4787,
    "annual_savings_gbp": 673,
    "annual_export_income_gbp": 145,
    "system_cost_estimate_gbp": 13230,
    "payback_years": 19.7,
    "co2_saved_kg_per_year": 694,
    "trees_equivalent_per_year": 33,
    "local_irradiance_kwh_m2": 990
  },
  "with_battery": {
    "annual_savings_gbp": 991,
    "self_consumption_pct": 80,
    "battery_cost_gbp": 4200,
    "total_system_cost_gbp": 17430,
    "payback_years": 17.6
  },
  "assumptions": {
    "panel_wattage_w": 420,
    "electricity_rate_p_kwh": 24.5,
    "export_rate_p_kwh": 5.5,
    "system_efficiency": 0.82
  },
  "data_quality": {
    "confidence": "medium",
    "missing_for_higher_confidence": ["os_footprint_area", "lidar_roof_pitch"],
    "note": "Orientation assumed mixed — south-facing adds ~10-15% to estimates."
  }
}

Use case: Solar installers, energy advisors, boiler-to-heat-pump assessors, home improvement tools. The has_existing_solar flag in the response (from our property database) indicates if solar panels are already present — useful for targeting leads. Phase 2 will add satellite-derived roof orientation for ±5% accuracy improvement.

GET

Schools Nearby

Starter+
/api/v1/schools/nearby
Area Intelligence 1 call England ✓ Wales ✗ Scotland ✗ N. Ireland ✗

Find schools near any UK property or postcode — with phase, age range, pupil numbers, type, and straight-line distance. Data sourced directly from the DfE's GIAS register (~27,000 open schools in England). Ofsted ratings are being integrated.

Requires Starter plan or above. Free-tier keys will receive a 403 endpoint_not_allowed response. Upgrade at homedata.co.uk/pricing.

Ofsted data now included. The ofsted object returns rating (Outstanding, Good, Requires Improvement, Inadequate) and last_inspection date. Filter results with ?ofsted=Good. Coverage: ~27,000 schools with inspections.

Auth: API key required
Response time: ~50ms (cached) / ~200ms (uncached PostGIS query)
Coverage: England only — ~27,000 open schools from DfE GIAS

Parameters

Parameter Type Required Description
postcode string one of* UK postcode. e.g. SW1A 2AA
lat + lng float one of* WGS84 decimal coordinates. e.g. lat=51.5074&lng=-0.1278
radius float optional Search radius in miles. Range: 0.1–5.0. Default: 0.5
limit int optional Max results to return. Range: 1–50. Default: 20
phase string optional Filter by school phase: Primary, Secondary, All-through, Nursery, 16 plus
ofsted string optional Filter by Ofsted rating: Outstanding, Good, Requires Improvement, Inadequate

* Provide either postcode or lat + lng — not both.

cURL
curl "https://homedata.co.uk/api/v1/schools/nearby?postcode=SW1A+2AA&radius=0.5&phase=Primary" \
  -H "Authorization: Api-Key YOUR_API_KEY"
Python
import requests

response = requests.get(
    "https://homedata.co.uk/api/v1/schools/nearby",
    headers={"Authorization": "Api-Key YOUR_API_KEY"},
    params={
        "postcode": "SW1A 2AA",
        "radius": 0.5,
        "phase": "Primary",
    }
)
data = response.json()
for school in data["schools"]:
    ofsted = school["ofsted"]
    rating = ofsted["rating"] if ofsted else "Not yet inspected"
    print(f"{school['name']} — {rating} ({school['distance_km']}km)")
JavaScript
const params = new URLSearchParams({
  postcode: 'SW1A 2AA',
  radius: '0.5',
  phase: 'Primary',
});

const response = await fetch(
  `https://homedata.co.uk/api/v1/schools/nearby?${params}`,
  { headers: { 'Authorization': 'Api-Key YOUR_API_KEY' } }
);
const data = await response.json();
data.schools.forEach(s =>
  console.log(`${s.name} — ${s.ofsted?.rating ?? 'Not yet inspected'} (${s.distance_km}km)`)
);
View example response
{
  "query": {
    "lat": 51.5034,
    "lng": -0.1276,
    "radius_miles": 0.5,
    "postcode": "SW1A 2AA",
    "phase": "Primary",
    "ofsted": null
  },
  "count": 3,
  "total_in_radius": 3,
  "ofsted_summary": {},
  "schools": [
    {
      "urn": 100024,
      "name": "Westminster Cathedral Catholic Primary School",
      "type": "Voluntary aided school",
      "type_group": "Faith schools",
      "phase": "Primary",
      "gender": "Mixed",
      "religious_character": "Roman Catholic",
      "admissions_policy": "Selective",
      "age_range": "3-11",
      "number_of_pupils": 453,
      "school_capacity": 480,
      "percentage_fsm": 14.2,
      "ofsted": null,
      "address": {
        "street": "Ambrosden Avenue",
        "locality": null,
        "town": "London",
        "county": "Westminster",
        "postcode": "SW1P 1QH"
      },
      "local_authority": "Westminster",
      "contact": {
        "website": "https://www.wccs.org.uk",
        "telephone": "020 7798 9020",
        "head_teacher": "Mrs Jane Smith"
      },
      "trust": null,
      "location": {
        "lat": 51.4968,
        "lng": -0.1354
      },
      "distance_km": 0.34,
      "distance_miles": 0.21
    }
  ],
  "metadata": {
    "source": "GIAS — DfE Get Information About Schools",
    "coverage": "England (~27,000 open schools)",
    "note": "Distance is straight-line (as the crow flies)"
  }
}

Error responses

Status Code Meaning
401 authentication_required Missing or invalid API key
403 endpoint_not_allowed Your plan doesn't include Schools. Requires Starter or above.
404 not_found School not found for the given URN (applies to /schools/{urn})
422 invalid_params Missing location param — provide postcode or lat+lng
429 rate_limit_exceeded Monthly request quota reached

Use cases: School catchment analysis for estate agent listings, property valuation tools (proximity to top-rated schools is a significant price signal), family home search platforms, and conveyancing due diligence. Pair with Property Intelligence and Deprivation Index for a complete area profile.

Want the full OpenAPI spec?

Our interactive Swagger UI includes all endpoints, request schemas, and live testing.

Open Interactive API Reference →