Access layers, boundaries, postal codes, and address lookups for all registered municipalities. Integrate our WMTS basemap or query the REST API directly.
Each municipality exposes its geographic layers as WMTS tiles and a REST API.
Base URL:
· All endpoints return JSON · Write operations require X-API-Key
/api/v1/municipalities
List all municipalities
Returns the id and name of every registered municipality.
GET /api/v1/municipalities
Response 200:
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Springfield",
"created_at": "2025-01-15T09:00:00Z"
}
]
/api/v1/municipalities/{municipality_id}/layers
List layers for a municipality
Returns all layers with their style config and geometry type.
| Path param | Type | Description |
|---|---|---|
municipality_id | UUID | Municipality identifier |
GET /api/v1/municipalities/{municipality_id}/layers
Response 200:
[
{
"id": "a1b2c3d4-...",
"municipality_id": "3fa85f64-...",
"name": "Admin Boundaries",
"geometry_type": "Polygon",
"style": { "fillColor": "rgba(100,200,100,0.3)", "strokeColor": "#4CAF50" },
"z_index": 10,
"visible": true
}
]
/api/v1/municipalities/{municipality_id}/postal-codes
List postal codes with boundaries
Returns all postal codes assigned to boundary features, including GeoJSON geometry.
GET /api/v1/municipalities/{municipality_id}/postal-codes
Response 200:
[
{
"id": "...",
"feature_id": "...",
"code": "1234AB",
"label": "Central District",
"geometry": {
"type": "Polygon",
"coordinates": [[[4.89, 52.37], ...]]
},
"properties": { "district": "Central" },
"created_at": "2025-02-01T10:00:00Z",
"updated_at": "2025-02-01T10:00:00Z"
}
]
/api/v1/municipalities/{municipality_id}/address-lookup
Reverse address lookup (point-in-polygon)
Address System
Given a WGS84 coordinate, returns the postal code(s) whose boundary polygon contains that point.
Uses PostGIS ST_Contains for accurate point-in-polygon matching.
| Param | In | Type | Required | Description |
|---|---|---|---|---|
municipality_id | path | UUID | Yes | Target municipality |
lon | query | float | Yes | Longitude in WGS84 (EPSG:4326), e.g. 4.8952 |
lat | query | float | Yes | Latitude in WGS84 (EPSG:4326), e.g. 52.3702 |
| Field | Type | Description |
|---|---|---|
code | string | Postal code, e.g. 1234AB |
label | string | null | Human-readable area name |
feature_id | UUID | ID of the boundary feature |
boundary_properties | object | Custom properties from the boundary feature |
GET /api/v1/municipalities/{municipality_id}/address-lookup?lon=4.8952&lat=52.3702
Response 200:
[
{
"code": "1012AB",
"label": "City Centre",
"feature_id": "b3d9e2f1-...",
"boundary_properties": {
"district": "Central",
"population": 12400
}
}
]
Response 404 (no match):
{ "detail": "No postal code found for the given coordinates" }
curl "/api/v1/municipalities/3fa85f64-5717-4562-b3fc-2c963f66afa6/address-lookup?lon=4.8952&lat=52.3702"
const res = await fetch(
`/api/v1/municipalities/${municipalityId}/address-lookup` +
`?lon=${longitude}&lat=${latitude}`
);
if (res.ok) {
const results = await res.json();
console.log(results[0].code, results[0].label);
} else if (res.status === 404) {
console.log("No postal code at this location");
}
/wmts
OGC WMTS 1.0.0
Implements the OGC Web Map Tile Service standard. Supports
GetCapabilities and GetTile operations
over the WebMercatorQuad tile matrix set (zooms 0–20).
| Query param | Value | Notes |
|---|---|---|
SERVICE | WMTS | Required |
REQUEST | GetCapabilities | GetTile | Required |
LAYER | layer UUID | GetTile only |
TILEMATRIX | 0–20 | Zoom level |
TILEROW | integer | Y tile coordinate |
TILECOL | integer | X tile coordinate |
GET /wmts?SERVICE=WMTS&REQUEST=GetCapabilities
GET /wmts?SERVICE=WMTS&REQUEST=GetTile&LAYER={layer_id}&TILEMATRIX=14&TILEROW=8428&TILECOL=8354
import WMTSCapabilities from 'ol/format/WMTSCapabilities';
import { optionsFromCapabilities } from 'ol/source/WMTS';
import TileLayer from 'ol/layer/Tile';
import WMTS from 'ol/source/WMTS';
const parser = new WMTSCapabilities();
const res = await fetch('/wmts?SERVICE=WMTS&REQUEST=GetCapabilities');
const caps = parser.read(await res.text());
const options = optionsFromCapabilities(caps, {
layer: '{layer_id}',
matrixSet: 'WebMercatorQuad',
});
const layer = new TileLayer({ source: new WMTS(options) });
/tiles/{layer_id}/{z}/{x}/{y}.png
Slippy map XYZ tiles
Standard XYZ tile endpoint, compatible with Leaflet, OpenLayers, Maplibre, and any tile-based client.
L.tileLayer('/tiles/{layer_id}/{z}/{x}/{y}.png').addTo(map);
new ol.source.XYZ({
url: '/tiles/{layer_id}/{z}/{x}/{y}.png',
maxZoom: 20,
})
All mutation endpoints require the municipality's API key in the
X-API-Key request header.
API keys are issued when a municipality is created via the admin interface.
/api/v1/municipalities/{id}/layers
Create a new layer.
{
"name": "Roads",
"geometry_type": "LineString",
"style": { "strokeColor": "#e74c3c", "strokeWidth": 2 },
"z_index": 20
}
/api/v1/layers/{id}/features
Add a GeoJSON feature to a layer.
{
"geometry": {
"type": "Polygon",
"coordinates": [[[4.89,52.37],[4.91,52.37],[4.91,52.38],[4.89,52.38],[4.89,52.37]]]
},
"properties": { "name": "City Park" }
}
/api/v1/features/{id}/postal-code
Assign or update the postal code for a boundary feature.
{
"code": "1234AB",
"label": "Central District"
}
/api/v1/features/{id}/documents
Upload a supporting document (multipart/form-data, 50 MB max).
curl -X POST \
-H "X-API-Key: {api_key}" \
-F "file=@report.pdf" \
/api/v1/features/{id}/documents
Enter a coordinate (WGS84) to query which postal code boundary it falls within.
Results will appear here…