Signals: the typed UK area-data layer.

One typed primitive over seven categories of public-record data, resolved to LSOA grain across England, Wales and Scotland. Value, normalised position, national-within-country percentile, per-signal confidence and source attribution on every response. Provenance is on the wire, not in a follow-up email.

Sample response

See it before you write a line of code.

Pick a postcode. We render the AreaProfile the same way the API returns it. Same shape, same fields, same provenance footer.

GET/v1/area?postcode=M1%201AE
PostcodeM1 1AELSOAE01005207DistrictManchesterCountryEnglandurban
deprivation.imd_decile
1decile
5.4 percentilehigher is better
IMD 2025
crime.total_12m
3,712count
92.1 percentilelower is better
police.uk
property.median_price
£182,500GBP
18.2 percentileneutral
HM Land Registry
property.price_change_pct_yoy
+4.1%pct
71.5 percentilehigher is better
derived
transport.station_count
5count
96.8 percentilehigher is better
OSM
fetch_modehybridengine_version2.0.2observed_periodApr 2025 to Mar 2026

Reading this view

fetch_mode
How each signal reached the wire. store means served from our persisted Postgres layer with a percentile and a normalised position. live means fetched from the upstream source on this request. hybrid means both happened in one response, which is the common case.
Falls back to live
Rows marked this way have no persisted row for this LSOA, so the service falls back to a live fetch from the upstream source. The Scotland postcode above is the classic case: HM Land Registry covers England and Wales only, so Scotland LSOAs have no store-backed property values today.

Sample shape and realistic values. Signal counts and percentiles vary per release of the underlying sources.

Anatomy of a Signal

Every field load-bearing. None of it decoration.

One Signal exploded. The shape is a Zod schema shared between apps/web and apps/api, so the runtime payload and the static types cannot drift.

SIGNALcrime.total_12mvalue: 1200KEYStable, category-namespaced.Pin against it forever.CATEGORYOne of seven. Additive.Categories never renamed.OBSERVED PERIODStatic, trailing-window,or monthly. Audit anchor.NORMALIZED_VALUE0-1 position within country.PERCENTILE0-100. National-within-country.CONFIDENCEPer-signal trust (0-1).With plain-language reason.SOURCEAttribution per value.Source catalog on methodology.DIRECTIONhigher / lower / neutral.Orthogonal to position.

Seven categories. One constellation.

Each category is a stable namespace under one Signal contract. New signals land under existing namespaces. No category is ever renamed.

CRIMEDEPRIVATIONPROPERTYSCHOOLSAMENITIESTRANSPORTENVIRONMENT
  • Crime

    12-month and monthly counts, store-backed at LSOA × month.

  • Deprivation

    IMD 2025, WIMD 2019, SIMD 2020. Never cross-compared.

  • Property

    Median price + transaction count + monthly history. E & W only.

  • Schools

    Ofsted within 1.5km. Live fetch today.

  • Amenities

    Shops, food, parks within 0.5-2km. Live counts.

  • Transport

    Station + bus stop counts at radii. Live.

  • Environment

    Flood risk + active warnings. Live from EA.

Three endpoints. One contract. No SDK required.

Plain JSON over HTTPS, Bearer-token auth with the oga_ prefix, all paths under /v1/. Single-signal ranking lives here; multi-signal compound filtering lives one product up under Intelligence.

Returns the full seven-category Signal catalog for one UK postcode or place name. No scoring, no AI. The primary read.

Parameters

  • areastring

    UK postcode or place name. One of area or postcode is required.

  • postcodestring

    Alias for area. Same validation and resolution path.

  • bundlestring (Lever)

    Bundle id from the caller's org. Filters response to the bundle whitelist.

Response

AreaProfile: { geo, signals[], meta }. Sets X-Engine-Version response header.

Status codes

200
OK.
400
Missing or invalid area / postcode.
401
Missing or invalid API key.
403
Plan has no API access, or IP-allowlist blocked.
404
Ungeocodable, or dark flag off.
429
Rate-limited (30 req / minute / key).

Same primitive. Five different workflows.

Each buyer reaches for Signals from a different angle. The data layer underneath is the same.

PropTech

The problem

Your product already has the buyer or renter on the page. They want decision-grade context about the area at the grain of the property. Building it yourself means stitching together a dozen government APIs and reconciling boundaries.

Why Signals

One typed request to /v1/area returns the seven-category catalog with country-scoped percentiles and per-signal confidence. Pin to the signal keys your model consumes; the contract stays additive.

Their value

Weeks of integration replaced by one API key. Comparable percentiles, not raw numbers that mean different things in Cardiff and Manchester.

Drop one endpoint into your property detail page and ship richer area context than your competitor's roadmap.

Insurance and InsureTech

The problem

Underwriting needs deterministic, addressable, dated values you can pin a price to and re-derive on audit. Live one-API-per-source fan-outs and trust-our-score report APIs do not survive an actuarial review.

Why Signals

Every Signal carries source_snapshot_id, engine_version, observed_period, and a confidence with a plain-language reason. Bundles let you lock the model to the exact signal keys your tariff uses.

Their value

Reproducible inputs you can defend to a regulator. Smaller blast radius on data updates because bundles whitelist what reaches your model.

Deterministic, dated, pinnable area inputs your actuarial team can sign off.

Lenders

The problem

Decisioning at scale needs comparable, percentile-normalised area inputs across the book. Most vendors give you raw numbers that are not comparable across home nations, with no audit trail of what the value was on the date you decisioned.

Why Signals

/v1/area returns national-within-country percentiles; /v1/areas ranks the universe at LSOA grain across a country or LAD. Country scoping is by LSOA code prefix so cross-border methodology lies are structurally impossible.

Their value

Concentration analysis and back-tests run against one consistent grain. Audit trail per decision because the wire payload carries lineage.

Comparable, percentile-normalised, audited area inputs for decisioning at portfolio scale.

CRE and site selection

The problem

Picking a site is a ranking problem. Which areas in this LAD meet my thresholds on deprivation, prices and footfall proxies, sorted. You do not want a one-area-at-a-time report API; you want to query the universe.

Why Signals

/v1/areas filters by country, by LAD, by percentile band or raw-value threshold on a chosen signal. Sort by percentile or value, capped at 1000 rows. Drill into the shortlist with /v1/area for the full profile.

Their value

Shortlists generated against typed thresholds in one HTTP call instead of geocoding 1000 postcodes through a report API. Output is ready to merge with internal data.

Threshold-and-rank the LSOA universe in one query, then drill into any area's full profile.

Public sector

The problem

Public-sector analysts need defensible, sourced, dated metrics that will not be challenged in an FOI response or a council briefing. They need to compare like-with-like inside a country, not across a methodological border.

Why Signals

Every Signal carries explicit source, observed_period, confidence and confidence_reason. Normalisation is country-scoped on purpose. We refuse to manufacture a cross-GB deprivation percentile.

Their value

An evidence base that holds up under scrutiny. Country-scoped percentiles instead of false-precision cross-border comparisons.

Defensible, sourced, dated area metrics with the methodology version stamped on every response.

Build on the typed UK area-data layer.

One endpoint resolves any UK postcode to the seven-category Signal catalog at LSOA grain. Provenance on the wire, methodology version stamped on every response, percentiles country-scoped by design.