City Memory API
Every Belgian municipality — official names in Dutch, French and German, NIS codes, province and region, WGS84 centroid, bounding box, surface area, which municipalities border which, and boundary geometry as GeoJSON.
It is free, public and needs no key. Every endpoint is a static file on a CDN, which is why there are no quotas, no rate limits and no sign-up — and also why there are no query parameters. Fetch a collection and filter it yourself, or fetch the province you care about.
565 municipalities, 11 provinces, 3 regions. Built from an OpenStreetMap extract of .
Start here
curl https://city-memory.pages.dev/api/v1/municipalities.json
One response, 565 municipalities, no geometry — around 250 kB. It is the file to reach for first, and for most uses the only one you need.
One municipality, with its boundary
curl https://city-memory.pages.dev/api/v1/municipalities/21004.json
A GeoJSON Feature, so it goes straight into Leaflet, MapLibre or QGIS
without unwrapping. 21004 is the NIS code for Brussels; every municipality
has one and it is the stable key across the whole API.
All the shapes at once
curl https://city-memory.pages.dev/api/v1/geo/belgium.geojson
A FeatureCollection of all 565 boundaries,
simplified hard enough to send in one response. For detail, take
/geo/provinces/{id}.geojson instead — those are simplified about forty times less.
Endpoints
Base URL: https://city-memory.pages.dev/api/v1
| Path | What it gives you |
|---|---|
/municipalities.json |
Every municipality, without geometry All 565 in one response, with names, codes, centroid, bbox and area but no boundary. About 250 kB. Fetch this once and filter it locally. |
/municipalities/{nis}.json |
One municipality, with its boundary A GeoJSON Feature: the summary fields under `properties`, and the boundary under `geometry` at roughly 10 m fidelity. |
/provinces.json |
The eleven provinces Brussels is counted as a province here, as the game does. |
/provinces/{id}.json |
One province and all its municipalities Includes the full summary of every municipality in it. |
/regions.json |
The three regions Flanders, Wallonia and Brussels-Capital. |
/regions/{id}.json |
One region and all its municipalities |
/search.json |
A name index for autocomplete Every name in all three languages, lowercased and accent-folded, so a client can match user input without normalising anything itself. |
/geo/belgium.geojson |
All 565 boundaries as one FeatureCollection Simplified hard enough to send in one response. Use the province files when you need detail. |
/geo/provinces/{id}.geojson |
One province's boundaries as a FeatureCollection Simplified about forty times less than the national file. |
/geo/regions/{id}.geojson |
One region's boundaries as a FeatureCollection |
The full description is in openapi.json (OpenAPI 3.1), and index.json is a discovery document listing every endpoint.
What a municipality looks like
{
"nis": "21004",
"name": "Bruxelles / Brussel",
"names": {
"nl": "Brussel",
"fr": "Bruxelles",
"de": "Brüssel"
},
"officialLanguage": "both",
"province": {
"id": "brussels",
"name": "Brussel / Bruxelles"
},
"region": {
"id": "brussels",
"name": "Brussel / Bruxelles"
},
"centroid": [
4.351062,
50.855125
],
"bbox": [
4.313768,
50.796345,
4.437066,
50.913905
],
"areaKm2": 32.97,
"parts": 1,
"neighbourCount": 16,
"osm": {
"relation": "relation/58274",
"wikidata": "Q239"
}
}
nis- The five-digit NIS/INS code Belgian administrations use. The stable identifier here.
name- The name the municipality uses itself: Dutch in Flanders, French in Wallonia, German in the German-speaking Community, both in Brussels.
centroid[longitude, latitude], WGS84, and guaranteed to fall inside the municipality — so you can pin a marker on it even for a shape shaped like a horseshoe.bbox[west, south, east, north], WGS84.areaKm2- Surface area, computed from the boundary on a sphere.
parts- How many disjoint pieces the municipality is made of. Usually 1. Baarle-Hertog is 26.
neighbourCount- How many municipalities share a border. The detail endpoint lists them by name.
Using it from a browser
Every endpoint sends Access-Control-Allow-Origin: *, so fetch it directly:
const res = await fetch('https://city-memory.pages.dev/api/v1/search.json');
const { entries } = await res.json();
// terms are lowercased and accent-folded, so "liege" finds Liège
const hits = entries.filter(e => e.terms.some(t => t.startsWith('liege')));
Stability
The path carries the version. Anything published under /api/v1/ keeps its
shape: fields may be added, but existing ones will not change meaning or disappear.
A breaking change becomes /api/v2/. The data behind it is refreshed when the
OpenStreetMap extract is rebuilt, and generatedAt tells you when that was.
Licence and attribution
The data comes from OpenStreetMap and stays under the Open Database License. In practice:
- Showing it — a map, an app, a chart — needs the credit “© OpenStreetMap contributors”, visible to whoever is looking at it.
- Redistributing the data, or a database you derived from it, means that database is ODbL too, and has to be offered under the same terms.
The code behind this site is MIT. Attribution for City Memory itself is welcome but not required.
What this API is not
- It has no addresses, no postcodes and no population figures. For addresses use Geopunt or BeSt Address.
- It does not geocode. Given a point, it will not tell you which municipality you
are in — though with
/geo/belgium.geojsonand a point-in-polygon test, you can. - It reflects OpenStreetMap, not the Belgian state. Municipal mergers show up when a mapper enters them, which may be before or after they take legal effect.