How to List a Region’s Subdivisions as GeoJSON with consists-of
- API or service
- Boundaries API
- Task
- Region place ID → subdivisions as points or polygons
- Examples
- Difficulty
- Beginner
- Time
- 10 min
List a region's subdivisions as GeoJSON
You have a country, a state, or a city and need the areas it is divided into: the states of a country, the districts of a state, or the boroughs of a city, as a list or as polygons. The Boundaries API consists-of endpoint takes the place ID of a boundary and returns the boundaries inside it, one level down or several levels down with sublevel.
This guide lists the subdivisions of Bavaria, Germany: its 7 administrative regions (Regierungsbezirke) and its 96 districts (71 Landkreise and 25 kreisfreie Städte), then compares the credits and response size of points and polygons. The examples use Germany because its administrative levels are mapped consistently in OpenStreetMap, the data source of the Boundaries API.
Task flow: region name → place ID → Boundaries API consists-of with sublevel → subdivisions as points or polygons.
Get the place ID of the region
consists-of needs the id of the region. Get it from the Geocoding API, searching by name with a result type:
https://api.geoapify.com/v1/geocode/search?text=Bayern&type=state&lang=de&format=json&limit=1&apiKey=YOUR_API_KEY
Reduced response:
{
"results": [
{
"state": "Bayern",
"result_type": "state",
"place_id": "51528f7e45c8ce2640598324a24e2f794840f00101f901f4bb200000000000c0020a92030642617965726e"
}
]
}
Other ways to get an ID:
- From coordinates: the
place_idof any feature returned by the Boundaries APIpart-ofendpoint, for example theBayernfeature for a point in Munich. See How to Get a City Boundary as GeoJSON. - From a previous
consists-ofresponse: each subdivision has its ownplace_id, so you can go one level deeper with another request.
Use the place ID as it is; don't build it from an OpenStreetMap ID.
Request the subdivisions
Send the place ID to consists-of. Without other parameters, it returns the direct administrative subdivisions as center points:
https://api.geoapify.com/v1/boundaries/consists-of?id=51528f7e45c8ce2640598324a24e2f794840f00101f901f4bb200000000000c0020a92030642617965726e&apiKey=YOUR_API_KEY
For Bavaria, that is the 7 Regierungsbezirke: Oberbayern, Niederbayern, Oberpfalz, Oberfranken, Mittelfranken, Unterfranken, and Schwaben.
Add sublevel=2 to skip one level and get the subdivisions of the subdivisions:
https://api.geoapify.com/v1/boundaries/consists-of?id=51528f7e45c8ce2640598324a24e2f794840f00101f901f4bb200000000000c0020a92030642617965726e&sublevel=2&apiKey=YOUR_API_KEY
The response has 96 features: 71 Landkreise and 25 kreisfreie Städte, the number the Bavarian State Office for Statistics publishes. More results from the same requests, tested on November 5, 2026:
id of |
sublevel |
Features | What they are | admin_level |
|---|---|---|---|---|
| Deutschland | 1 | 16 | States (Länder) | 4 |
| Bayern | 1 | 7 | Administrative regions (Regierungsbezirke) | 5 |
| Bayern | 2 | 96 | Districts (Landkreise and kreisfreie Städte) | 6 |
| München | 1 | 25 | City districts (Stadtbezirke) | 9 |
Reduced response, one of the 96 districts:
{
"type": "Feature",
"properties": {
"name": "Landkreis Miesbach",
"county": "Landkreis Miesbach",
"state": "Bavaria",
"datasource": {
"sourcename": "openstreetmap",
"raw": { "osm_id": 2168231, "admin_level": 6, "ref:nuts:3": "DE21F" }
},
"place_id": "514ef0b6a711a627405955cca1678ee14740f00101f901a715210000000000c002099203124c616e646b72656973204d69657362616368"
},
"geometry": { "type": "Point", "coordinates": ["…"] }
}
datasource.raw keeps the OpenStreetMap tags of each boundary. admin_level tells you which level a feature is at, and official codes such as ref:nuts:3 (DE21F) let you join the boundaries with statistics. Not every region has the same levels, so check admin_level when a result mixes levels, and keep the place_id of each subdivision for later requests.
Choose points or polygons
geometry decides what each feature contains. The default point returns a center point; geometry_1000, geometry_5000, and geometry_10000 return simplified polygons; the number is the documented accuracy in meters. Polygons cost extra credits and make the response much larger.
Credits are calculated per request: every 20 boundaries returned cost 1 credit, and every polygon adds 1 credit. For the 96 districts of Bavaria (sublevel=2), tested on November 5, 2026:
geometry |
Credits | Response size |
|---|---|---|
point (default) |
ceil(96 / 20) = 5 | about 164 KB |
geometry_10000 |
5 + 96 = 101 | about 1.2 MB |
geometry_5000 |
5 + 96 = 101 | about 3.7 MB |
A practical order:
- Request the subdivisions with
geometry=pointto show a list or let the user pick, for 5 credits. - Request polygons only when you draw or analyze the areas. For a whole state on one screen,
geometry_10000is usually enough and keeps the response small. - Store the result. Administrative boundaries change rarely, so a cached response saves credits on every later view.
The Boundaries API pricing and the Free plan's 3,000 credits per day apply.
Region subdivisions with an AI coding agent
Copy this prompt into Codex, Claude Code, Cursor, or another coding agent to list or draw the subdivisions of a region in your project.
Add region subdivisions to my project with the Geoapify Boundaries API.
Before you start
- Inspect the existing project first. Reuse its current framework, map library, HTTP client, caching, and conventions. Make the smallest necessary changes.
- Ask only what the project does not answer: which region the user starts from, how many levels down it needs, whether the subdivisions are listed or drawn, and whether requests run in a backend or use a restricted browser API key.
- Read the Geoapify API key from the project's environment configuration. Never hardcode, print, or log it.
Place ID
- Get the region's place_id from the Geocoding API (GET https://api.geoapify.com/v1/geocode/search with text, type such as state or city, and format=json), or from a Boundaries API part-of feature.
API request
- GET https://api.geoapify.com/v1/boundaries/consists-of with id, optional sublevel (1 = direct subdivisions, 2 = one level deeper), and geometry.
- Use geometry=point for lists; request polygons (geometry_10000 for a large region) only when drawing or analyzing.
- Credits: ceil(features / 20) plus 1 per polygon. Show the estimate before requesting polygons for large regions, and cache responses.
Result
- Read features[].properties: name, place_id, datasource.raw.admin_level, and official codes in datasource.raw (for example ref:nuts:3) when joining statistics.
- Group or filter by admin_level when a result mixes levels. Keep each subdivision's place_id to go deeper.
- If a map is used, add the FeatureCollection as a GeoJSON source and draw fills and outlines.
Errors
- Show the API message for HTTP 400 responses, retry 429 responses a limited number of times with backoff, and add a test with a mocked response of mixed admin levels.
Review the generated code against this guide. Check the place ID source, the sublevel value, the credit estimate for polygons, and the API-key handling.