Geo Search — MDDB API

Radius search (R-tree or geohash) #

POST /v1/geo-search

Find documents within radiusMeters of a (lat, lng) point. Documents must have geo_lat+geo_lng, geo_hash, or a resolvable geo_postcode+geo_country in their metadata. Results are sorted by ascending distance and composable with filterMeta.

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: object

Property Type Description
collection (required) string
lat (required) number (double)
lng (required) number (double)
radiusMeters (required) number (double)
topK integer Default 10.
algorithm string One of "rtree", "geohash". Default "rtree".
filterMeta object
includeContent boolean Default false.
{
  "algorithm": "rtree",
  "collection": "string",
  "includeContent": false,
  "lat": 0,
  "lng": 0,
  "radiusMeters": 0,
  "topK": 10
}

Responses #

Status Description Body
200 OK
400 Invalid request
503 Index still loading

Bounding-box search #

POST /v1/geo-within

Find documents inside an axis-aligned bbox. Does not cross the anti-meridian.

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: object

Property Type Description
collection (required) string
minLat (required) number
maxLat (required) number
minLng (required) number
maxLng (required) number
filterMeta object
includeContent boolean
{
  "collection": "string",
  "includeContent": false,
  "maxLat": 0,
  "maxLng": 0,
  "minLat": 0,
  "minLng": 0
}

Responses #

Status Description Body
200 OK
400 The request is malformed (a body that is not JSON, a missing or invalid field, an unreadable body) or names a subsystem that is not initialized. The message says which. ErrorResponse (application/json)
401 Auth is on (MDDB_AUTH_ENABLED=true) and the request carries no credentials, an invalid or expired JWT, or an unknown API key. ErrorResponse (application/json)
403 The caller lacks the permission the route needs (SEC-019 access gate, auth on: read, write or admin on the collections the request names), or a write meets read-only mode (MDDB_MODE=read or the protocol's own mode). ErrorResponse (application/json)
413 The body is over MDDB_MAX_BODY_BYTES (32 MiB by default). ErrorResponse (application/json)
429 The client is over the API rate limit (MDDB_RATE_LIMIT_ENABLED=true, MDDB_RATE_LIMIT_REQUESTS per MDDB_RATE_LIMIT_WINDOW seconds). A call that embeds can also be refused by the collection's daily embedding budget, with a QuotaExceeded body. RateLimitError (application/json)

400 example (application/json)

{
  "error": "missing collection"
}

401 example (application/json)

{
  "error": "missing authentication"
}

403 example (application/json)

{
  "error": "forbidden"
}

413 example (application/json)

{
  "error": "request body too large"
}

Find documents inside a GeoJSON polygon or multi-polygon #

POST /v1/geo-polygon

Returns every indexed point whose coordinates fall inside the supplied GeoJSON Polygon (outer ring + optional holes) or MultiPolygon (union of polygons). Exactly one of polygon or multiPolygon must be set.

The R-tree's bounding-box query prefilters candidates, so response time tracks the shape's bbox rather than the full collection size. GeoJSON coordinate order is [lng, lat] per RFC 7946. Rings may be open (first ≠ last) or closed (first == last); both forms work.

Does not cross the anti-meridian — split the query into hemispheres if you need that.

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: GeoPolygonRequest

{
  "collection": "venues",
  "includeContent": false,
  "multiPolygon": {
    "coordinates": [
      [
        []
      ]
    ],
    "type": "MultiPolygon"
  },
  "polygon": {
    "coordinates": [
      [
        []
      ]
    ],
    "type": "Polygon"
  }
}

Responses #

Status Description Body
200 Matches (empty array if none) GeoPolygonResponse (application/json)
400 Invalid request — missing collection, both/neither shape supplied, or malformed geometry
503 Geo index still loading

Force-rebuild geo indexes #

POST /v1/geo-reindex

Rebuild both R-tree and geohash indexes from the persisted geo bucket. Optionally load one or more postcode CSVs first.

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: object

Property Type Description
collection string Empty = rebuild all collections
loadPostcodes array of object
loadPostcodes[].country string
loadPostcodes[].csvPath string
{
  "collection": "string",
  "loadPostcodes": [
    {
      "country": "string",
      "csvPath": "string"
    }
  ]
}

Responses #

Status Description Body
200 OK
400 The request is malformed (a body that is not JSON, a missing or invalid field, an unreadable body) or names a subsystem that is not initialized. The message says which. ErrorResponse (application/json)
401 Auth is on (MDDB_AUTH_ENABLED=true) and the request carries no credentials, an invalid or expired JWT, or an unknown API key. ErrorResponse (application/json)
403 The caller lacks the permission the route needs (SEC-019 access gate, auth on: read, write or admin on the collections the request names), or a write meets read-only mode (MDDB_MODE=read or the protocol's own mode). ErrorResponse (application/json)
413 The body is over MDDB_MAX_BODY_BYTES (32 MiB by default). ErrorResponse (application/json)
429 The client is over the API rate limit (MDDB_RATE_LIMIT_ENABLED=true, MDDB_RATE_LIMIT_REQUESTS per MDDB_RATE_LIMIT_WINDOW seconds). A call that embeds can also be refused by the collection's daily embedding budget, with a QuotaExceeded body. RateLimitError (application/json)
503 Not now: the search concurrency limit is reached, the subsystem is disabled, or a write meets the database while its freelist is rebuilt (#333; the body then adds phase and progress). Retry after Retry-After seconds. ErrorResponse (application/json)

400 example (application/json)

{
  "error": "missing collection"
}

401 example (application/json)

{
  "error": "missing authentication"
}

403 example (application/json)

{
  "error": "forbidden"
}

413 example (application/json)

{
  "error": "request body too large"
}

Geo index statistics #

GET /v1/geo-stats

Authorization: BearerAuth or APIKeyAuth or none

Responses #

Status Description Body
200 OK
401 Auth is on (MDDB_AUTH_ENABLED=true) and the request carries no credentials, an invalid or expired JWT, or an unknown API key. ErrorResponse (application/json)
403 The caller lacks the permission the route needs (SEC-019 access gate, auth on: read, write or admin on the collections the request names), or a write meets read-only mode (MDDB_MODE=read or the protocol's own mode). ErrorResponse (application/json)
429 The client is over the API rate limit (MDDB_RATE_LIMIT_ENABLED=true, MDDB_RATE_LIMIT_REQUESTS per MDDB_RATE_LIMIT_WINDOW seconds). A call that embeds can also be refused by the collection's daily embedding budget, with a QuotaExceeded body. RateLimitError (application/json)

401 example (application/json)

{
  "error": "missing authentication"
}

403 example (application/json)

{
  "error": "forbidden"
}

Encode (lat, lng) → geohash string #

POST /v1/geo-encode

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: object

Property Type Description
lat (required) number
lng (required) number
precision integer Default 12. Minimum 1. Maximum 12.
{
  "lat": 0,
  "lng": 0,
  "precision": 12
}

Responses #

Status Description Body
200 OK
400 The request is malformed (a body that is not JSON, a missing or invalid field, an unreadable body) or names a subsystem that is not initialized. The message says which. ErrorResponse (application/json)
401 Auth is on (MDDB_AUTH_ENABLED=true) and the request carries no credentials, an invalid or expired JWT, or an unknown API key. ErrorResponse (application/json)
413 The body is over MDDB_MAX_BODY_BYTES (32 MiB by default). ErrorResponse (application/json)
429 The client is over the API rate limit (MDDB_RATE_LIMIT_ENABLED=true, MDDB_RATE_LIMIT_REQUESTS per MDDB_RATE_LIMIT_WINDOW seconds). A call that embeds can also be refused by the collection's daily embedding budget, with a QuotaExceeded body. RateLimitError (application/json)

400 example (application/json)

{
  "error": "missing collection"
}

401 example (application/json)

{
  "error": "missing authentication"
}

413 example (application/json)

{
  "error": "request body too large"
}

Decode geohash → centroid + bbox #

POST /v1/geo-decode

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: object

Property Type Description
geohash (required) string
{
  "geohash": "string"
}

Responses #

Status Description Body
200 OK
400 The request is malformed (a body that is not JSON, a missing or invalid field, an unreadable body) or names a subsystem that is not initialized. The message says which. ErrorResponse (application/json)
401 Auth is on (MDDB_AUTH_ENABLED=true) and the request carries no credentials, an invalid or expired JWT, or an unknown API key. ErrorResponse (application/json)
413 The body is over MDDB_MAX_BODY_BYTES (32 MiB by default). ErrorResponse (application/json)
429 The client is over the API rate limit (MDDB_RATE_LIMIT_ENABLED=true, MDDB_RATE_LIMIT_REQUESTS per MDDB_RATE_LIMIT_WINDOW seconds). A call that embeds can also be refused by the collection's daily embedding budget, with a QuotaExceeded body. RateLimitError (application/json)

400 example (application/json)

{
  "error": "missing collection"
}

401 example (application/json)

{
  "error": "missing authentication"
}

413 example (application/json)

{
  "error": "request body too large"
}