Unified v2 API contract

September 2, 2026 · View on GitHub

Status: paused as of 2026-09-02. Production returns 404 for /v2 and every path below it before reading a v2 catalog or family object from R2. The Worker implementation, build tooling, and this contract are retained, but no v2 availability or resumption date is promised. The supported production API is currently /search, /reverse, and /id/:gers_id.

The remainder of this document records the dormant contract so work can resume without reconstructing it. It does not describe an available public service.

V2 consolidates division and Places text search, structured exact-address lookup, reverse geocoding, and GERS ID lookup under a small surface. It borrows the familiar forward/reverse split and comma-separated types filter used by hosted geocoders, but it does not claim wire compatibility with Mapbox, TomTom, or Nominatim.

There is deliberately no batch endpoint.

Version identity

Every successful v2 response is pinned to one atomic release and carries:

{
  "data_version": {
    "overture_release": "2026-06-17.0",
    "geocoder_build": "2026-07-19.1"
  }
}

The same values are exposed as X-Overture-Release and X-Geocoder-Build; X-Data-Version remains an alias for the geocoder build. The mutable v2/catalog.json selects one immutable release manifest. That manifest binds exact core, Places, and address entrypoints, so one request never falls back across geocoder builds or mixes Overture releases.

GET /v2/forward

Text mode accepts:

  • q (required, at most 200 bytes);
  • types, a comma-separated set of division types, poi, or address;
  • place as an input alias for poi and neighbourhood as an alias for neighborhood;
  • limit from 1 through 10 (default 10);
  • autocomplete=true|false (default true);
  • proximity=longitude,latitude; and
  • country as a division-search bias.

Without types, text mode searches divisions and POIs. Free-text address search is intentionally not advertised yet. An explicit types=address with q returns an unsupported-capability error rather than silently searching a different family.

The first Places reader has bounded, explicit recall limits. A query without proximity first consults only the packed global head, which supports one to three exact normalized tokens. A head manifest may additionally advertise a category-bounded exact-primary-name phrase lane for two- and three-token queries; older manifests skip that probe. When a three- or four-token global-head query is empty solely because of that token limit, the reader may interpret the final one or two exact tokens as a locality-like division and route the remaining name once at that division's centroid. This fallback does not run for explicit proximity or a non-empty global-head result. The inference is recorded in metadata.places_locality_inference; distance from its routing centroid is not exposed as user-proximity distance.

A located query routes to exactly one stable world-quadkey shard and supports up to four tokens, with optional last-token prefix matching. Reported distance is diagnostic within that bounded candidate set; it is not a claim of exhaustive global nearest-POI ranking.

The index also stores CJK bigrams for later substring work, but v2 query planning currently uses full normalized word tokens. This keeps ordinary long CJK names inside the four-clause bound without pretending that a partial-name substring parser is already supported.

Structured exact-address mode uses the same endpoint without q. Required fields are country, street, and number (or address_number). Optional fields default to the literal empty string:

Canonical fieldAccepted aliases
admin_level_generalstate, region
admin_level_specificcounty
postal_citycity
postcodepostalcode
numberaddress_number

Explicit canonical context fields use one literal exact key. When a request instead supplies state (or region) plus city, with no canonical context field or county, the Worker tries three bounded exact source representations: city in the last address level, in postal_city, then in both. The first non-empty result wins. It does not infer a missing state or treat omitted context as a wildcard. Structured response metadata reports resolution_variant and lookup_attempts.

If types is supplied it must be exactly address. limit, autocomplete, and proximity are rejected in structured mode because an exact lookup returns every duplicate candidate up to the hard 512-candidate safety cap; it does not silently truncate ambiguity.

Forward responses are GeoJSON FeatureCollection objects. metadata.mode is text or structured_address. Structured responses also report coverage, normalization version, candidate count, and ambiguity. Text responses include metadata.places_locality_inference only when the bounded locality-suffix fallback supplied an internal routing centroid.

GET /v2/reverse

lat and lon are required. Missing types means all division types, and an explicit division subset is honored by filtering the returned subtype.

poi and address are served from build 2026-07-31.0 onward, from the point-family spatial reverse indexes built by reverse-v2.yml. Each is requested explicitly by types; neither is returned by an untyped query, which still answers from divisions. A release whose family manifest does not record families/<family>/reverse-catalog.rcat rejects that family's type, so the behavior is per-release, not global.

The response is a GeoJSON FeatureCollection containing zero or one feature.

GET /v2/ids/:id

Looks up a 32-hex-digit or canonical hyphenated Overture GERS UUID in the exact core release selected by v2. The successful response matches the existing /id/:gers_id object shape—id, bbox, and optional locator metadata—and adds the atomic v2 data_version object. A syntactically invalid ID returns 400 without an R2 shard read; a valid absent ID returns 404.

Production and availability behavior

The existing /search, /reverse, and /id/:gers_id endpoints remain in place for current clients and continue using the production catalog/fallback behavior. The former /address, /__address-page-spike, and /__places-page-spike endpoints are removed.

While the production pause is configured, every /v2 path returns 404 regardless of whether an old v2 catalog remains in storage. If the dormant implementation is explicitly re-enabled, a missing v2 catalog/release returns a structured 503 release_unavailable; a missing explicitly requested family also returns 503, and invalid parameter combinations return 400.