Municipal Mapper

Open Municipal Geographic Data

A Revenue Development Foundation initiative supporting local governments with open geographic data infrastructure. Access layers, boundaries, postal codes, and address lookups for all registered municipalities.

Municipalities
Features
Postal Codes

Municipalities

Each municipality exposes its public layers as WMTS tiles, OGC API · Features (QGIS-ready vector data), and a REST API.

Loading municipalities…

API Documentation

Base URL:  ·  All endpoints return JSON  ·  Write operations require X-API-Key

Public Endpoints No auth

GET /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"
  }
]
GET /api/v1/municipalities/{municipality_id}/layers List layers for a municipality

Returns all layers with their style config and geometry type.

Path paramTypeDescription
municipality_idUUIDMunicipality 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
  }
]
GET /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"
  }
]

Map Tiles No auth

GET /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 paramValueNotes
SERVICEWMTSRequired
REQUESTGetCapabilities | GetTileRequired
LAYERlayer UUIDGetTile only
TILEMATRIX0–20Zoom level
TILEROWintegerY tile coordinate
TILECOLintegerX tile coordinate

GET /wmts?SERVICE=WMTS&REQUEST=GetCapabilities


GET /wmts?SERVICE=WMTS&REQUEST=GetTile&LAYER={layer_id}&TILEMATRIX=14&TILEROW=8428&TILECOL=8354

OpenLayers integration

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) });
GET /tiles/basemap/{municipality_id}/{z}/{x}/{y}.png Composite basemap (one layer for other apps)

All of a municipality's public layers flagged for the basemap, rendered together in draw order as a single tile layer — the easiest way for another application to reuse this map as its basemap. Also available via WMTS as layer basemap-{municipality_id}. See BASEMAP_INTEGRATION.md in the repository for ready-made snippets.


L.tileLayer('/tiles/basemap/{municipality_id}/{z}/{x}/{y}.png').addTo(map);
GET /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,
})

Vector Data — OGC API · Features No auth

The modern successor to WFS. Serves every public layer as live vector features (GeoJSON) that you can open directly in QGIS, ArcGIS Pro, or any OGC-compatible GIS client — no GeoServer required. Non-public layers are not exposed. Only the single landing-page URL below is needed; the client discovers every layer from there.

Write Endpoints X-API-Key required

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.

POST /api/v1/municipalities/{id}/layers

Create a new layer.

{
  "name": "Roads",
  "geometry_type": "LineString",
  "style": { "strokeColor": "#e74c3c", "strokeWidth": 2 },
  "z_index": 20
}
POST /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" }
}
PUT /api/v1/features/{id}/postal-code

Assign or update the postal code for a boundary feature.

{
  "code": "1234AB",
  "label": "Central District"
}
POST /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

Live Address Lookup Demo

Enter a coordinate (WGS84) to query which postal code boundary it falls within.

Generated request

        
Response
Results will appear here…