Deprivation indices
MHCLG (IMD 2025), StatsWales (WIMD 2019), Scottish Gov (SIMD 2020)
Decile, rank, and the seven IMD domain scores per LSOA. Country-specific methodologies; we never compare across the border.
Signal-first infrastructure. Country-scoped percentiles. Monthly time-series snapshots that cannot be backfilled. Deterministic engine, version stamped on every response.
A signal is one measured, sourced, normalized, percentiled, time-stamped attribute of a UK area. Everything above signals is composition. Reports, scores, peers, insights, and forecasts are surfaces built on top.
The raw measurement in its native unit. number, string, or null with a reason.
Direction-agnostic position 0–1 within country. Ascending: 0 = lowest, 1 = highest. Read with the signal’s direction field.
Per-scope rank 0–100 from PERCENT_RANK(). Today: national-within-country. Regional and per-cohort recompute on the roadmap.
0.0–1.0 with confidence_reason. Source-driven (sample size, freshness, fallback path). Honest, not aspirational.
Every signal_value and timeseries row carries source_snapshot_id and engine_version. Re-running the same query against the same engine version returns the same number. Always.
We name every source on this page. Marketing copy elsewhere says “multiple sources”; full provenance lives here and in source_snapshots on every API response.
MHCLG (IMD 2025), StatsWales (WIMD 2019), Scottish Gov (SIMD 2020)
Decile, rank, and the seven IMD domain scores per LSOA. Country-specific methodologies; we never compare across the border.
HM Land Registry
Standard residential sales (PPD category A, types D/S/T/F, non-deleted, positive prices). Median price + transaction count per LSOA per month.
Home Office
Bulk street-level archive joined to LSOA codes carried on each record. Aggregated to monthly count per LSOA. No spatial join needed.
Department for Education
School inspection ratings — Outstanding, Good, Requires Improvement, Inadequate — within 1.5km of postcode. England only.
OSM contributors via Overpass
Schools, food/shops, transport stations, bus stops, parks, healthcare. Live amenity counts at radius bands around the postcode.
Defra
Flood risk zones and active warnings around the postcode. Distinguishes river-at-risk from active-warning states.
ONS / Royal Mail (postcodes.io)
Postcode resolution: lat/long, LSOA, local authority, ward, constituency, region, country, rural-urban classification.
Slow-moving signals (deprivation, prices, crime) live in a persisted store. Live signals (Ofsted, OpenStreetMap, flood) call the source on every request. The geographic spine joins them.
Canonical area registry: LSOAs, MSOAs, LADs, regions, with boundary version (2011 / 2021).
ONS NSPL/ONSPD spine: postcode → OA / LSOA / MSOA / LAD / region. 1.8M postcodes loaded.
One row per refresh run. Captures source name, captured_at, record count, optional sha. The audit anchor.
Catalog of every signal we expose. signal_key, label, direction, unit, source, description.
One row per (signal_key, geo_type, geo_code). Current value, normalized_value, source_snapshot_id, engine_version.
Per-scope percentile rank, 0 to 100. Computed in-DB via PERCENT_RANK() window function.
Append-only history. PK includes observed_period; INSERT … ON CONFLICT DO NOTHING — corrections surface as next period, never overwrite.
Every contributing signal was fetched from a live source on this request. The fallback path; happens when the store has no row for an area.
Every contributing signal was read from the persisted store. No live calls were made. The path that scales.
A mix — some signals store-served, some live-served on this request. Honest about partial coverage during the live-to-store migration.
Percentiles are computed in the database with PERCENT_RANK() window functions and persisted. Each country (England, Wales, Scotland) normalizes within itself. IMD 2025, WIMD 2019, and SIMD 2020 are different methodologies; we never compare across.
Rank within country. The current production scope. England LSOAs ranked against England; Wales against Wales; Scotland against Scotland.
Rank within ONS region (North West, South East, …). The geographic spine is loaded; the per-region percentile recompute job is not yet built.
Rank within a customer-defined Levers cohort. Cohorts themselves ship today (POST /v1/orgs/:id/cohorts); per-cohort percentile recompute is the planned step. The k-NN peer graph already drives the peer-relative z-score derived signals (see § 06).
Every month, a CLI job appends one row per signal per area to signal_timeseries, keyed by observed_period. INSERT … ON CONFLICT DO NOTHING. Corrections surface as next period’s value, never overwrite the past. Un-backfillable history that compounds every month.
History is immutable per (signal_key, geo_type, geo_code, observed_period). The primary key prevents duplication; the conflict policy prevents overwrite.
The append job is one set-based INSERT … SELECT statement. Re-running a period is a no-op. Safe under partial failure and re-deploy.
Prices and crime ingest write monthly history directly; the static-source job (deprivation) snapshots at refresh time. Each signal’s observed_period reflects its actual cadence.
Computed in the database from the time-series, persisted alongside raw signals, immediately queryable through the typed query plane. Each derived signal carries a documented window and a sample-size guard.
POST /v1/scoreaggregates the signal catalog into a 0–100 composite. Same input, same engine version, same output. Four presets cover the canonical workflows; custom weights and saved org presets layer on top.
Origination. For someone choosing where to live.
Site selection. For commercial location decisions.
Investment underwrite. For acquisitions and portfolio.
Reference baseline. The default preset.
The frozen v2 engine computes every dimension. Custom weights pass { preset, weights }; saved organisation presets pass { preset_id }. Response carries weights_source ("preset" or "custom") and the engine version that produced the number.
Three derived surfaces over the store. Each one is honest about what it is, what it isn’t, and what the defaults assume.
POST /v1/peersk nearest LSOAs to a target. Euclidean distance over normalized values, dimension-mean-squared (AVG, not SUM), default k=20, max k=200, min 3 overlapping signals.
Distance is symmetric and bounded in [0,1]. No per-signal weighting in v1.
POST /v1/insightsAnomaly screening: rank LSOAs by |peer-relative z|. Materialized peer graph (~840k assignments). Default k=50, max k=500. Optional |z| threshold.
Peer math is precomputed offline. No request-time recompute.
POST /v1/forecastLinear regression over signal_timeseries: regr_slope, regr_intercept, regr_r2, regr_syy. Default window 24 months, horizon 12. Constant ±2·residual_stderr confidence band.
This is not a learned model. Not ARIMA, not Holt-Winters, not Prophet. CI does not widen with horizon distance.
POST /v1/query is a typed JSON grammar with six plan ops. Programmatic {plan} never touches the LLM. Natural-language {question} routes through a planner that emits the same typed grammar. Every response echoes the executed plan and plan_source so every result is replayable.
Every signal value and every score dimension carries confidence(0.0–1.0) and a human-readable confidence_reason. The rubric is fixed; the inputs are sample size, freshness, fallback path, and (for property) YoY volatility.
Inferred-not-measured dimensions (Foot Traffic, Rental Yield, Regeneration, Tenant Demand) cap at MEDIUM by design. Monitor change detection gates on min_transactions (default 8) so a 2-sale move never fires a webhook.
Every response carries engine_version in the body and X-Engine-Version in the headers. Pin a request to a specific version with the request header. Pin a whole organisation through Levers methodology pinning.
OpenStreetMap data-source reliability hardening. Transport scoring no longer degrades to NONE confidence for UK city centres. No formula changes.
Org-level methodology pinning is owner-only. PUT /v1/orgs/:id/methodologysets the pin; every scoring response from that org’s keys stamps the pinned version in X-Engine-Version. Explicit request headers still win over the org pin. The pinned row stays in the database even after a version ages out of support, for audit; runtime gracefully falls back to latest rather than 500.
Levers are the per-organisation methodology controls. All four are opt-in: no bundle, no preset_id, no pin, no cohort means default behaviour. RBAC, white-label, and IP allowlist live alongside on the operational side.
POST /v1/orgs/:id/bundlesNamed whitelist of signal_keys. Scopes /v1/area, /v1/areas, and /v1/query — the API exposes only the bundle's signals to your keys.
A request for an out-of-bundle signal returns 422 bundle_signal_not_allowed. No silent omission.
POST /v1/orgs/:id/presetsSave a (base_preset, weights) pair server-side. Call by preset_id from POST /v1/score. Reusable across team members and replayable in audits.
Frozen v2 engine unchanged. weights_source surfaces as "custom" on response.
PUT /v1/orgs/:id/methodologyPin the whole org to a specific engine_version. Every scoring response from the org's keys stamps that version in X-Engine-Version.
Owner-only by design: misclicking a pin has high cost for regulator-facing audits. Explicit request header still wins.
POST /v1/orgs/:id/cohortsNamed list of LSOA codes (max 10,000). Scopes the candidate pool on /v1/peers — "find peers in MY universe."
Cohorts ship today; per-cohort percentile recompute (scope=peer_group) is on the roadmap.
Three-tier RBAC (member / admin / owner), per-org white-label (display_name + brand_url), and per-key IP allowlist (allowed_ip_cidrs) are documented in full on /docs/levers (landing in this workstream).
Said up front to save reviewer time. The system is decision-grade screening + analysis; not valuation, not lending, not address-level today.
OneGoodArea does not predict the market value of a specific property. Use a dedicated AVM for that.
Not a predictor of individual default, affordability, or creditworthiness. Tier-3 enrichment input only.
LSOA grain is the floor today. Address-level scoring via OS AddressBase Premium + UPRN is on the roadmap (AR-134).
Scores within 100m of an LSOA boundary deserve a closer look. Postcode and LSOA boundaries are administrative, not behavioural.
Deprivation indices correlate with protected characteristics. Buyers are responsible for FCA / CONC / SS1/23 compliance in regulated workflows.
Five public artefacts, four of them outside this page. The fifth is this page.
You are here. Stamped on every release with engine_version + released_at.
Open14.2Public release history. Every shipped MAJOR / MINOR / PATCH bump documented.
Open14.3OpenAPI 3.0 spec rendered as an interactive reference. Currently being regenerated against the live backend.
OpenA typed signal API, four product surfaces, monthly time-series history, and org-level methodology pinning. Same answer, every time you ask.