For CRE and site selection

Screen the whole UK against your site criteria in one typed call.

Compound multi-signal ranking across LSOAs, country or local authority scope. Up to eight AND-joined filters with eleven comparison operators. Find the peer set of your best-performing catchment in one call. Replay any ranked shortlist as a deterministic plan next quarter and get the same answer.

The problem

Site selection is a ranking problem at portfolio scale.

Picking a site for a new store, a build-to-rent block, or a tenant catchment is not a single-area decision. It is a ranking problem at portfolio scale. Which areas in this country or local authority meet our thresholds on footfall demand, competition density, transport access, spending power and commercial costs, sorted by which one is the closest match to our best-performing locations?

The legacy answer is to stitch ONS Mid-Year Estimates, postcode sector demographics, Land Registry, a footfall provider, and a crime spreadsheet, then re-rank by hand in Excel. Each refresh of the criteria means rebuilding the join. Adding a new constraint means a new spreadsheet. The shortlist is not reproducible next quarter because the data and the join logic both change underneath you.

What CRE and site-selection teams actually want: a single typed query that takes compound criteria, runs against a stable LSOA-grain dataset, returns ranked rows, and lets you replay the same query next quarter and get a comparable answer. Plus a separate call that says “here are the catchments most like our top-performing store.”

How it fits

Five integration points from screen to score to replay.

What a typical CRE or site-selection integration looks like. Compound query first, drill in second, peer set third, score fourth, replay fifth.

Step 01

Compound rank in one call

POST /v1/query with a rank_areas plan. Up to 8 AND-joined filters on stored signal keys, 11 comparison operators (eq, lt, lte, gt, gte, between, plus the five percentile variants). Sort by any signal, scope by country or local authority district, cap at 1000 rows. One round trip.

POST /v1/query
{ "plan": { "op": "rank_areas", "params": {
   "signals": [
     { "key": "property.median_price", "filter": { "lte": 300000 } },
     { "key": "crime.total_12m", "filter": { "percentile_lte": 25 } },
     { "key": "property.price_change_pct_yoy",
       "filter": { "gt": 0 } } ],
   "sort_by": { "signal": "property.price_change_pct_yoy",
                "direction": "desc" },
   "country": "England", "limit": 50 } } }
Step 02

Drill into shortlisted areas

Each rank_areas result row carries geo_code (the canonical LSOA). Pipe the shortlist into GET /v1/area for the full seven-category profile per area. Compose your own dashboard rows from the typed signals catalog.

# For each LSOA in the shortlist:
GET /v1/area?postcode=M1 1AE
-> { "geo": { "lsoa": "E01005207", ... },
     "signals": [ ... 7 categories ... ],
     "meta": { "engine_version": "2.0.2" } }
Step 03

Find areas like the best-performing one

POST /v1/peers takes a target LSOA (your top store) and returns k nearest neighbours by Euclidean distance over normalised signal values. Default k=20, min 3 overlapping dimensions. Materialised peer graph (~840k assignments across 42k LSOAs) so the call is cheap and stable.

POST /v1/peers
{ "target": { "postcode": "EC1A 1BB" },
  "country": "England",
  "k": 20 }
-> { "peers": [
     { "geo_code": "E01...", "distance": 0.045,
       "n_dims_used": 7 } ] }
Step 04

Score with the commercial profile

POST /v1/score with the business profile returns the 5 dimensions a site-selection analyst already uses: foot_traffic_demand, competition_density, transport_access, local_spending_power, commercial_costs. Custom weights or a saved org profile (preset_id) lets the team encode their own brand fit.

POST /v1/score
{ "area": "EC1A 1BB", "preset": "business" }
-> { "score": 71, "area_type": "urban",
     "dimensions": [ { "key": "foot_traffic_demand", ... } ],
     "weights_source": "preset",
     "engine_version": "2.0.2" }
Step 05

Replay the screen next quarter

The /v1/query response echoes the executed plan plus plan_source. Save the plan JSON alongside the shortlist; next quarter, paste it back as the request body and get a comparable answer against refreshed data. The criteria become version-controlled JSON instead of a spreadsheet that lives on one analyst's laptop.

# Q3 query
POST /v1/query { "plan": { ... } }
-> { "plan_source": "client",
     "plan":   { /* echoed */ },
     "results": [ ... ] }

# Q4: same plan, refreshed data
POST /v1/query { "plan": { /* paste */ } }
Products you reach for

Intelligence leads. Signals handles single-signal scans. Scores is the brand-fit lens.

Monitor (portfolio drift detection) is rarely the primary CRE lift, but if you watch a leased portfolio it slots in the same way it does for insurers.

§ 01

Intelligence

See product →

Primary surface. /v1/query with rank_areas does compound screening across the UK in one call. /v1/peers gives the peer set of any target catchment in one call. /v1/insights ranks LSOAs by peer-relative anomaly when you want to find catchments that are unusual for their group. Every response echoes the executed plan for replay.

POST /v1/query
{ "plan": { "op": "rank_areas", "params": {
   "signals": [ { "key": "...", "filter": { ... } } ],
   "sort_by": { ... },
   "country": "England", "limit": 50 } } }
-> { "plan_source": "client",
     "plan":   { /* echoed for replay */ },
     "results": [ ... ] }
§ 02

Signals

See product →

Single-signal cross-area ranking via /v1/areas. When the screen is one dimension at a time ("top 50 LSOAs by price_change_pct_yoy in the West Midlands"), /v1/areas is the simpler surface. Same store, same percentiles, same LSOA grain. /v1/area drills into any shortlisted LSOA for the full seven-category profile.

GET /v1/areas?signal=property.price_change_pct_yoy
       &country=England&min_percentile=80
       &sort=value_desc&limit=50
-> { "signal": "property.price_change_pct_yoy",
     "count": 50,
     "areas": [
       { "geo_type": "lsoa", "geo_code": "E01...",
         "value": 18.4, "percentile": 92.1 } ] }
§ 03

Scores

See product →

The commercial profile returns the five dimensions a site-selection analyst already uses. Custom weights per portfolio class (food + bev vs convenience vs experiential), or a saved org profile (preset_id) for brand-specific fit. Deterministic engine, same score across deploys.

POST /v1/score
{ "area": "EC1A 1BB", "preset": "business" }
-> { "score": 71, "area_type": "urban",
     "dimensions": [
       { "key": "foot_traffic_demand", ... },
       { "key": "competition_density", ... },
       { "key": "transport_access", ... },
       { "key": "local_spending_power", ... },
       { "key": "commercial_costs", ... } ] }
What you can defend

Six properties the property committee will sign off.

The shortlist needs to survive committee scrutiny. Each property is documented on /methodology and stamped on every response.

§ 01

Compound queries in one round trip

rank_areas accepts up to 8 AND-joined signal filters with 11 comparison operators (raw value or percentile). One INNER JOIN per signal in the executor. AND semantics across all filters. No more spreadsheet joins; no more partial joins across data vendors.

§ 02

Reproducible shortlists

Every /v1/query response echoes the executed plan plus plan_source. Save the plan JSON alongside the shortlist; replay it next quarter against refreshed data and get a comparable answer. Criteria become version-controlled JSON instead of an Excel file on a laptop.

§ 03

Materialised peer graph

/v1/peers reads from a materialised k-NN graph (~840k assignments across 42k LSOAs, k=20 default). The peer math runs offline in the refresh:peers + derive:signals batch so query-time is cheap. Same definition of "peer" feeds find_peers, find_insights, and the peer-relative-z derived signals.

§ 04

ONS-backed scope, no fake polygons

Country and LAD scoping use the official ONS NSPL spine. Region scope is on the roadmap; ad-hoc polygon overlays are not. Where the analyst wants a custom catchment, Levers peer cohorts persist an explicit list of LSOA codes per org and constrain /v1/peers to that universe.

§ 05

Deterministic + stable

Same postcode plus same scoring profile gives the same score across deploys. Same plan gives the same shortlist across the same data state. The deterministic engine is frozen v2, golden-tested; AI never sets the numbers (AI translates NL into the typed plan; the database produces the rows).

§ 06

Country-scoped percentiles

Normalisation runs national-within-country. England's IMD, Wales's WIMD, and Scotland's SIMD are different methodologies. A cross-border percentile would be a lie. If you operate across all three countries, you compare percentiles within each, not across.

Frequently asked

Questions a CRE analyst asks before integrating.

What is the difference between /v1/areas and /v1/query?

/v1/areas (Signals product) is single-signal threshold-and-rank within a country or local authority. Faster to write, easier to cache, no plan grammar to learn. /v1/query (Intelligence product) is the compound version: up to 8 AND-joined signal filters, 11 comparison operators, plus the other five plan ops (get_area, score_area, find_peers, find_insights, find_forecast). Use /v1/areas when the screen is one dimension; use /v1/query when it is compound.

Can I screen hundreds of catchments at once?

Yes. /v1/query with rank_areas caps at 1000 rows per call. Default limit is 100. The executor runs one signal_values INNER JOIN per filter signal in the plan, all parameters bound through prepared statements so there is no SQL injection surface and the database can plan efficiently. For most CRE screens, one call returns the shortlist; pipe each result row's geo_code into /v1/area for full per-area profiles if you need them.

Can I customise the commercial dimensions?

Yes, but within the business profile's fixed 5-dimension set (foot_traffic_demand, competition_density, transport_access, local_spending_power, commercial_costs). You re-weight, you do not redefine. Custom weights per request OR save a per-org profile via POST /v1/orgs/:id/presets and reference it as preset_id on every call. Weight keys must match PRESET_DIMENSION_KEYS[business].

How do you handle catchments that are not LSOA-shaped?

Two options. (a) Approximate the catchment as a list of LSOA codes and use Levers peer cohorts to persist it (POST /v1/orgs/:id/cohorts, up to 10000 LSOA codes per cohort). Pass cohort_id on /v1/peers to constrain the candidate set. (b) Resolve a few representative postcodes inside the catchment via /v1/area and aggregate signals client-side. Custom-polygon ingest is not on the roadmap; the LSOA × month grain is the floor.

Where does footfall data come from?

Today we surface the proxies (residential density, retail amenity counts within radii, transport-station counts) via the business scoring profile. We do not ingest mobile-device footfall feeds (Streetlytics, Mytraffic, etc.). Most CRE teams already have one of those; OneGoodArea is the deterministic area-context layer underneath, not a footfall vendor. If footfall ingest moves up the priority list, it will land as a new signal category, not a replacement.

How does the peer set actually get computed?

Euclidean distance over normalised signal values, dimension-mean-squared (distance = SQRT(AVG_i((t_i - c_i)^2)) over dimensions both the target and candidate have normalised). Symmetric, bounded in [0,1], robust to missing dimensions. Default k=20, min 3 overlapping dimensions. The graph is materialised in peer_assignments (~840k rows) by the refresh:peers batch; query-time is a single LATERAL join.

Can the team replay the same shortlist next quarter?

Yes, by design. Every /v1/query response carries plan_source and the executed plan. Save the plan JSON alongside the shortlist. Next quarter, paste the plan back as the request body and the same deterministic executor runs it against refreshed data. If the engine version moved between runs, the response header X-Engine-Version tells you so; org-level methodology pinning locks the version if you want byte-equivalent runs.

One typed query against the whole UK. Reproducible next quarter.

Replace the spreadsheet join with a versioned plan. Get the peer set of your best-performing catchment in one call. Score with weights the property committee can sign off.