Works out which features of layer A are related to features of layer B by the chosen type of relation and returns a summary of those links in numbers.

| API name | Type | Required | Default | Range or allowed values |
|---|---|---|---|---|
| layer_a | one of the listed values | yes | — | buildings | roads | poi | water | green_areas | railways | boundaries | landuse | waterways |
| layer_b | one of the listed values | yes | — | buildings | roads | poi | water | green_areas | railways | boundaries | landuse | waterways |
| join_type | one of the listed values | no | intersects | intersects | contains | within |
The table is generated from the tool's own parameter contract: API names, types, defaults and the ranges its validator accepts.
The input is a rectangular bounding box in WGS84 plus one of nine data layers; some tools also take a point. The output is GeoJSON, JSON metrics or a GeoTIFF.
| Layer | What it holds |
|---|---|
| buildings | buildings |
| roads | roads and streets |
| poi | points of interest: services, shops, tourism |
| water | water bodies |
| green_areas | green areas: parks, forests, lawns |
| railways | railways |
| boundaries | administrative boundaries |
| landuse | land use |
| waterways | waterways |
Every tool in the section is free. The bounding box may cover up to 100 km². Rate limits are 10 requests per minute per tool run and 30 requests per minute for reading the catalogue. Without signing in you get up to 10 successful calculations a day; after that the service asks you to register and answers 402 with the code login_required. A box larger than the allowed area is also 402, and an unknown tool id is 404.
| Code | Reason |
|---|---|
| 400 | A parameter failed the tool's own check (the answer carries a validation_errors list) or the bbox does not hold four numbers. |
| 402 | The bounding box is larger than 100 km² — or a visitor who is not signed in has used up 10 calculations for the day and the answer asks them to sign in (login_required). |
| 403 | Access guard: every tool is free today, so this refusal reaches nobody. |
| 404 | There is no tool with that identifier. |
| 429 | Rate limit exceeded: 10 requests per minute per tool run. |
The tool is free. Visitors who are not signed in get 10 calculations a day; after signing in there is no daily cap. The bounding box may cover up to 100 km². OpenStreetMap data: snapshot of 2026-08-24.
curl -X POST https://osm2cdr.com/api/geo-analysis/spatial_join \
-H 'Content-Type: application/json' \
-d '{"bbox":[37.6,55.74,37.64,55.76],"params":{"layer_a":"buildings","layer_b":"landuse","join_type":"within"}}'import requests
r = requests.post(
"https://osm2cdr.com/api/geo-analysis/spatial_join",
json={'bbox': [37.6, 55.74, 37.64, 55.76], 'params': {'layer_a': 'buildings', 'layer_b': 'landuse', 'join_type': 'within'}},
)
print(r.json()["meta"])Full parameter schema: GET /api/geo-analysis/spatial_join/schema
{
"tool": "spatial_join",
"meta": {
"elapsed_ms": 101,
"method": "postgis_sql",
"data_snapshot": "2026-08-24"
},
"result": {
"data": {
"pair_count": 500,
"join_type": "within",
"layer_a": "buildings",
"layer_b": "landuse"
}
}
}The numbers come from the run that baked the sample above. A live answer also carries meta.quota — how many calculations the visitor has left for today. The response is shown as an excerpt; the full result is larger.