Skip to main content
This page documents the contracts that shape every Locus scoring response. It complements the APRS data standard — that page covers the underlying record envelope; this page covers the API-surface scoring semantics.

H3 cell index

Locus uses Uber’s H3 hierarchical hexagonal grid for spatial indexing. Every score, metric, and POI lookup resolves to an H3 cell.

Resolution

The default scoring resolution is H3 r8 — about 0.46 km hex edge, which roughly corresponds to a “block group” in US census terms. You can request higher resolution via the radius parameter — Locus aggregates child cells appropriately.

Per-metro resolution overrides

Some low-density, large-parcel metros are scored at H3 r7 (~5.16 km², ~1280 m radius) instead of the default r8 (~0.74 km², ~490 m radius). At r8 a single cell in these markets often covers only one CRE asset, which leaves signal aggregation dominated by small-n noise. Coarsening to r7 produces enough samples per cell for the score to be statistically meaningful. Metros currently overridden to r7:
  • Phoenix
  • Houston
  • Las Vegas
  • Dallas
  • San Antonio
  • Nashville
  • Jacksonville
  • Oklahoma City
  • El Paso
  • Fort Worth
Every other metro continues to score at the r8 default. The override is additive — historical scores are unaffected and no migration is needed on your side. Each row written to cell_scores is tagged with the resolution it was computed at via the resolution_variant column, so downstream consumers (rankings, MAUP ensembles, the explorer) can distinguish r7 from r8 cells. If you join scores across metros, filter or group on resolution_variant rather than assuming a single resolution.

Cell IDs in API responses

Cell IDs are the standard 15-character hex strings produced by h3-js (e.g. 8828308281fffff). Use these as opaque identifiers when caching scores client-side; Locus pins the H3 algorithm version and won’t change cell-ID semantics without a major API version bump.

Scoring profiles

The profile parameter on /api/score adjusts signal weights for a use case. Each profile is a fixed weighting — Locus does not auto-tune weights from your historical data (custom-tuned profiles are on the roadmap). Composite scores are 0–100 with a documented confidence interval. Sub-scores per signal group are also 0–100.

general profile weights

The general profile is tuned for generic commercial real estate (CRE) price prediction rather than any specific use case. Weights are calibrated against the empirical CRE price-correlation literature — building permit issuance, employment density change, and transit ridership are the three signals with the strongest published correlations and clearest lead times against CRE prices. Use a use-case profile (qsr, office, industrial, retail, data_center, self_storage) when you have a specific tenant or asset class in mind — those weights reflect industry-specific priorities rather than generic price prediction. The use-case profile weights are unchanged from prior general rebalances.

Development pipeline sub-scores

The developmentPipeline group rolls up several permit- and construction-derived sub-signals. Each subScores entry returned in the API response carries a name, a 0–100 score, a weight, and a source label.

Permit Scope Quality (AXL-108)

Permit Scope Quality weights every permit in the trailing 6-month window by what the permit is for, not just how many were issued. Each permit’s scope_type and estimated_cost_tier — both extracted by an LLM-based permit classifier from the free-text description — are multiplied to yield a 0–100 contribution, and the cell’s sub-score is the average of those contributions across the window. Scope-type weights: Cost-tier multipliers: A cell dominated by new_construction permits in the highest cost tier will trend toward 100; a cell dominated by low-cost repair permits will trend toward 0. The signal is designed to separate cells where permits indicate genuine new development from cells where permits mostly reflect maintenance churn. When the LLM extractor has not yet annotated any permit in a cell, the sub-score is omitted from subScores and AXL-108 appears in sourcesMissing for the group.

Safety & environment sub-scores

The safetyEnvironment group rolls up crime, regulatory hazard maps, realized loss history, environmental burden, air quality, and 311 service-request signals.

Flood Loss History (AXL-109)

Flood Loss History is a realized-loss companion to the regulatory FEMA FIRM Flood Risk sub-score. The two signals answer different questions:
  • Flood RiskWhat does the regulatory map say this cell is? Forward-looking, redrawn on a multi-year cycle.
  • Flood Loss HistoryWhat has actually happened here? Backward-looking, derived from FEMA National Flood Insurance Program (NFIP) claims.
This distinction matters because repeat-loss corridors and flash-flood-prone areas frequently sit in non-A/V FIRM zones — the FIRM map is a snapshot of modeled hazard, while NFIP claims capture realized loss patterns including pluvial flooding, drainage failures, and stormwater backups that the FIRM zone often misses. The sub-score is computed by:
  1. Finding the nearest US zip centroid to the cell (single PostGIS nearest-neighbor lookup).
  2. Joining that zip to the aggregated NFIP claims table (677k+ raw claims rolled up to ~17.8k zip-level records).
  3. Returning a normalized exposure score in [0, 1] derived from claim count, repeat-loss policy share, and the most recent claim year.
  4. Inverting to a 0–100 safety contribution: a zip with no historic claims scores 100, a maximum-exposure zip scores 0.
When the cell’s nearest zip has no NFIP claims (common for inland low-risk geographies), the sub-score is omitted from subScores and AXL-109 (FEMA NFIP) appears in sourcesMissing for the group. NFIP coverage is US-only — international cells will always show this source as missing.
A coastal cell in a repeat-loss corridor will typically score high on Flood Risk (because it sits in a regulatory AE or V zone) and low on Flood Loss History (because NFIP has paid out repeated claims there). Use both sub-scores together when ranking cells for hazard-sensitive use cases — relying on the FIRM zone alone will under-flag the worst pluvial-flood corridors.

Complaint Trend YoY (AXL-107)

Complaint Trend YoY is a directional companion to the volume-based Complaint Density and Complaint Velocity sub-scores. Density measures how loud a cell is right now; velocity measures the 30-day change; the YoY delta measures whether that loudness is rising or falling against the same window one year ago — the slow-moving signal that volume and short-window velocity both miss. The sub-score is computed in-app from the same service_requests_311 rows the scorer already pulls for density and resolution time, so no additional data source is required:
  1. Count 311 complaints in the trailing 30 days (density_30d).
  2. Count 311 complaints in the matching 30-day window one year prior (the 335-to-395-day window).
  3. Compute the YoY delta as (current − prior) / max(prior, 1), capped at +5× to bound runaway ratios in cells with a near-zero prior baseline.
  4. Map the delta onto a 0–100 safety contribution: −1 (complaints down 100%) → 100, +3 (complaints up 3×) → 0, with values above +3× saturating at 0.
Negative YoY (complaints trending down) lifts the cell’s safety score; positive YoY (complaints rising) penalizes it. Rising 311 density is treated as a Pioneer Stage 1 signal — the same complaint-acceleration pattern that typically precedes pioneer-business clustering by 12–24 months and feeds the Pioneer Signal cascade. When both the current and prior 30-day windows are empty for a cell, the sub-score is omitted from subScores and AXL-107 (311 YoY) appears in sourcesMissing for the group rather than emitting a misleading “improving” signal from a quiet cell with no complaint history. Cells in metros without 311 ingestion will always show this source as missing.
Read all four 311 sub-scores together when interpreting a cell: a cell with high Complaint Density and a high (improving) Complaint Trend YoY is loud-but-getting-quieter, while a cell with low density and a low (deteriorating) trend score is quiet-but-getting-louder — the kind of leading indicator that volume alone obscures.

Utility Complaint Density (ICC)

Utility Complaint Density captures unresolved utility-service friction — outages, billing disputes, service-quality complaints — that shows up as formal filings with a state utility commission. It’s a leading indicator for infrastructure stress that neither crime data nor FEMA flood maps pick up. The sub-score is computed from the ICC (Illinois Commerce Commission) utility-complaint feed, joined to the cell via the same zip-level nearest-neighbor lookup that powers Flood Loss History:
  1. Find the nearest US zip centroid to the cell.
  2. Count ICC utility complaints at that zip in the trailing FY window.
  3. Log-scale the count against the observed distribution (median 4, p90 22, p99 91 complaints/zip) and invert to a 0–100 safety contribution: 0 complaints → 100, saturating toward 0 above ~150.
The dataset is ~91% Illinois — this is a single-state FOIA extract, not a national commission-complaint aggregate. Cells outside Illinois will almost always show ICC in sourcesMissing rather than a misleading zero-complaint “clean” record. Treat this sub-score as an Illinois-only enrichment for now; do not infer utility health for non-IL cells from its absence.

Nuclear Facility Proximity (NRC)

Nuclear Facility Proximity is a proximity penalty for cells that fall inside the NRC’s emergency-planning zones (EPZs) around operating and decommissioning reactor sites. It rides alongside Environmental Risk and Natural Hazard Risk as a discrete, regulatory-anchored hazard layer that the EJScreen and NRI composites do not surface directly. The sub-score is computed by:
  1. Scanning NRC-licensed reactor sites (operating + decommissioning units, ~68 site locations) for the nearest site to the cell centroid using a haversine distance.
  2. Mapping distance onto a linear decay between the NRC’s two published EPZ radii:
    • 16 km (~10 mi) — the plume-exposure EPZ. Cells at or inside this radius score 0 (minimum safety contribution from this signal).
    • 80 km (~50 mi) — the ingestion-pathway planning zone. Cells at or beyond this radius score 100 (no meaningful nuclear-proximity penalty).
  3. Linearly interpolating between the two anchors for cells in the 16–80 km band.
The 16/80 km anchors are the NRC’s own EPZ radii, not tuned parameters. The site coordinates are backfilled at city/township precision via a plant-name → site-coordinate crosswalk (68 sites) — adequate for the EPZ-scale proximity signal, not for anything finer.
Cells far from any US reactor site score at or near 100 on this sub-score — it never rewards proximity, only penalizes it. Use it together with Environmental Risk and Natural Hazard Risk when ranking cells for hazard-sensitive use cases (data centers, hospitals, long-hold industrial siting).

Economic strength sub-scores

The economicStrength group rolls up employment, wage, GDP, banking, small-business lending, innovation, and federal-tenancy signals.

Federal Lease Presence (GSA FRPP)

Federal Lease Presence treats federal-agency tenancy as a positive economic anchor. Federal leases are long-dated, credit-strong, and slow to move — a dense cluster of federal RSF (rentable square footage) around a cell is a durable institutional signal that CRE fundamentals in the area are underwritten by government tenancy, not just private demand. The sub-score is computed from the GSA Federal Real Property Profile (FRPP) FOIA extract:
  1. Sum leased RSF across every federal lease that falls inside the cell’s H3 query ring (not just the exact cell — federal tenancy spills over into the immediate neighborhood).
  2. Log-scale the summed RSF between 2,000 sqft (a very small satellite office) and 750,000 sqft (a dense multi-agency federal cluster).
  3. Map onto 0–100: a single median-sized federal office lease (~8,700 sqft) contributes ~25/100; a large multi-lease cluster saturates to 100.
Cells with no federal leases anywhere in the query ring omit the sub-score and list GSA FRPP in sourcesMissing. This is the most common state — federal-lease footprints are geographically concentrated (metro cores, agency campuses, courthouses, ports of entry), so a missing sub-score is a genuine “no federal anchor here” reading, not a data-quality gap.
Federal leases also project into the Codex as codex_entities (entity_type = facility) — see the Codex documentation if you need the underlying per-lease records rather than the aggregated score contribution.

Business vitality sub-scores

The businessVitality group rolls up business openings/closings, category diversity, rating momentum, review activity, establishment density, health inspections, license velocity, pioneer businesses, and regulatory friction.

Broker Discipline (NY DOS)

Broker Discipline is a regulatory-friction penalty on business vitality — a rising volume of formal disciplinary actions against real-estate brokers in a state signals that the transaction environment is contentious, and that some share of local CRE activity is being litigated rather than transacted cleanly. The sub-score is computed from the NY Department of State (DOS) real-estate broker disciplinary consent-order FOIA extract:
  1. Count distinct DOS disciplinary case files (dos_file_number) for the cell’s state.
  2. Log-scale the count between 1 and 100 disciplinary actions, then invert to a 0–100 contribution: fewer actions → higher score, more actions → lower score.
This is a state-level join, not a per-cell signal. The underlying FOIA snapshot has no per-record address, coordinates, or licensee zip — the field simply is not in the source. That means every cell in the same state shares the same disciplinary count, and by extension the same sub-score contribution. The weight is intentionally low (0.04) to reflect this: a flat state-wide value should never swing an individual cell’s business-vitality score materially. The current extract is a single fiscal-year, single-state (NY) sample — 62 rows across 40 distinct case files. Cells outside NY show NY DOS in sourcesMissing and pay no penalty. Do not read a missing NY DOS sub-score on a non-NY cell as “clean regulatory environment”; read it as “no state-level broker-discipline data available for this state.”
Broker-discipline case files also project into the Codex as codex_events (event_type = broker_disciplinary_action) — use the Codex directly if you need per-case detail rather than the aggregated state-level score contribution.

Confidence semantics

Every Locus response includes a confidence field (0.0–1.0) representing the ratio of expected data sources that returned data for the location.
  • 0.9+ (high) — almost all data sources contributed; treat as authoritative.
  • 0.7–0.9 (medium) — significant signals present; treat as directional, not exact.
  • 0.5–0.7 (low) — sparse coverage; useful for filtering but not for ranking.
  • <0.5 (very low) — Locus returns the score for transparency but it should not be used for production decisions.
Confidence varies by metro. Major US metros (top 50 MSAs) consistently exceed 0.85. Rural areas, US territories, and international markets often fall below 0.7.

Coverage guards on signal groups

Some signal groups include a minimum-source guard to prevent a single universally-available data source from dominating the group score for cells where every other source is missing. When a group’s coverage guard isn’t met, the group emits a neutral no-signal score of 50 and a confidence of 0, with an empty subScores array — instead of returning a misleadingly high or low score derived from one input. Example response for a rural cell where only FEMA flood zone is available:
Treat a safetyEnvironment.score of 50 paired with confidence: 0 as “no safety signal available” — not as “neutral safety.” The 50 is a placeholder so the composite score can still be computed; it is not a measurement. Use the confidence field to filter these cells out of safety-sensitive ranking lists.

Pioneer Signal and early-stage gentrification indicator

Locus includes a Pioneer Signal detection system that identifies early signs of neighborhood transformation. The system tracks a multi-stage cascade that typically precedes gentrification by 12–24 months:
  1. Pioneer businesses — new specialty coffee shops, art galleries, or co-working spaces appear in a previously underserved area.
  2. Council language shift — city council meeting minutes begin referencing “revitalization,” “mixed-use,” or “transit-oriented development” for the area.
  3. Permit acceleration — building permit velocity increases, particularly renovation and change-of-use permits.
  4. Rezoning activity — formal rezoning applications or variance requests are filed.
These stages feed into the Early-Stage Gentrification Indicator (ESGI), a score returned alongside the composite score in scoring responses. The ESGI combines causal edge attribution, upzoning probability, litigation risk, and spatial spillover effects to quantify how likely a cell is to experience rapid value change.

Uncertainty quantification

Scoring responses include uncertainty metadata that helps you assess how much to trust a given score. Locus runs a Monte Carlo simulation (96 samples) with confidence-aware noise injection to produce:
  • Confidence intervals — geo-conformal prediction intervals at 80% and 90% coverage.
  • Sobol sensitivity indices — first-order and total-order indices showing which signal groups contribute most to score variance.
  • Epistemic flags — signals where data is sparse or conflicting, flagged for transparency.
  • Spatial Sharpe ratio — a risk-adjusted score metric analogous to a financial Sharpe ratio, indicating score stability relative to spatial neighbors.
Request uncertainty data by adding include=uncertainty to any scoring endpoint:

Per-cell consensus class

The uncertainty payload tells you how noisy a score is given the data feeding it. The consensus class answers a different question: would this score still hold if Locus had aggregated to a different grid? It is a per-cell sensitivity check against the Modifiable Areal Unit Problem (MAUP) — the well-known finding that spatial statistics can move materially when the underlying grid changes. Locus computes a consensus_class for every cell by comparing the cell’s percentile rank within its metro at the default resolution against the percentile rank of the parent (coarser) hex it sits inside. When the two ranks agree the score is robust to grid choice; when they diverge the score is at least partly a grid artifact. The classification is surfaced on /api/cells/detail (the endpoint that powers the Explorer’s cell-detail panel) as three fields:

Class definitions

A cell shows consensus_class: null until the classification job has populated its row. Treat null the same way you’d treat confidence: null — render no robustness badge rather than guessing.

Example response

When to use it

  • Ranking and shortlisting. Filter to consensus_class = stable_core when you need the most defensible top-N list — those cells survive a grid change.
  • Risk-flagging the long tail. Cells in ambiguity_shell are the cells most worth a human review before commitment. They typically sit on tier boundaries where small grid choices flip rankings.
  • Suppressing false-positive low scores. A stable_non_signal cell is genuinely low across grids — a stable_non_signal paired with a composite_score of 35 means the cell is reliably quiet, not under-sampled.
The classification is recomputed after every material scoring-engine change. The companion Spatial Sharpe ratio gives you the same robustness intuition relative to neighbors rather than relative to grid resolution — combine both when filtering for production-grade rankings.

Data freshness

The freshness metadata in score responses tells you the oldest source feeding a given response — useful for deciding whether to cache.

API stability commitments

  • Cell IDs — frozen across major API versions
  • Scoring profile names — frozen
  • Composite + sub-score scales (0–100) — frozen
  • Confidence semantics — frozen
  • Sub-score names within a group — may change with 90-day notice
  • Underlying data sources — may change without notice (we pick the best available)
  • Weight tuning per profile — adjusted quarterly based on backtesting; minor adjustments not announced, major rebalances get a 30-day blog post
If a profile’s behavior changes meaningfully, you’ll see a profile_version bump in the response. Pin to a specific profile_version if you need replicable scores across time.

What Locus doesn’t include

Locus is non-PII. We do not include:
  • Individual person data (names, addresses, phone numbers)
  • Mobile-device location traces (Locus uses aggregated patterns, not raw movements)
  • Customer-specific data unless you explicitly upload it via /api/data/upload
Aggregations resolving to fewer than 25 people (or 5 households for residential metrics) are suppressed in responses with a suppressed: true flag.