For developers and AI agents
Build with the API
A read-only REST API over every dataset. JSON:API by default, plain JSON or CSV on request, no key needed to start.
Quick start
Start at https://opendata.ssmusoke.dev/api/v1, which links to every collection.
# Every village in Lamwo district, as plain JSON curl -g 'https://opendata.ssmusoke.dev/api/v1/villages?filter[district]=91&format=json'
// Every village in Lamwo district, as plain JSON
$rows = json_decode(file_get_contents(
'https://opendata.ssmusoke.dev/api/v1/villages?filter[district]=91&format=json'
), true);
// Every village in Lamwo district, as plain JSON
$rows = Http::get('https://opendata.ssmusoke.dev/api/v1/villages', [
'filter' => [
'district' => 91,
],
'format' => 'json',
])->json();
# Every village in Lamwo district, as plain JSON
import requests
rows = requests.get(
"https://opendata.ssmusoke.dev/api/v1/villages",
params={"filter[district]": 91, "format": "json"},
).json()
// Every village in Lamwo district, as plain JSON const rows = await fetch( "https://opendata.ssmusoke.dev/api/v1/villages?filter[district]=91&format=json" ).then((r) => r.json());
application/vnd.api+jsonOne page at a time with links, filters, sorting, includes and sparse fieldsets. Up to 100 rows a page.
application/jsonAdd format=json to any list for the whole filtered list as an array of records. Easiest for scripts and agents.
text/csvAdd format=csv (or send Accept: text/csv) for the whole filtered list as a spreadsheet, with nested values as dotted columns.
Lists in JSON or CSV return up to 100,000 rows. For whole datasets use the downloads.
Examples
Open any call in the format you need.
-
Districts of the Acholi sub-region, by name
GET /api/v1/districts?filter[subRegion]=10&sort=name -
Every village in Kalangala district
GET /api/v1/villages?filter[district]=1 -
The sub-counties of a county
GET /api/v1/counties/1/children -
A village's parish, sub-county, county, district, sub-region and region
GET /api/v1/villages/1/ancestors -
Places called Gulu
GET /api/v1/search?q=gulu&limit=5 -
Match a typed address to a village
GET /api/v1/resolve?district=Kalangala&subCounty=Mugoye&village=Bugoma -
Parishes changed since a date (to sync a copy)
GET /api/v1/parishes?filter[updatedSince]=2026-01-01 -
Population of every district (2024 census)
GET /api/v1/statistics?filter[level]=districts&filter[indicator]=population -
Government schools in Lamwo district
GET /api/v1/education/schools?filter[district]=91 -
Constituencies in Kampala
GET /api/v1/elections/constituencies?filter[district]=2
Identifiers
Use the numeric id to identify a place; it never changes. The government ubosCode is only unique within its parent, except for districts.
identifiers.cod-ab-pcode
Regions, districts, counties and sub-counties. Use it to join boundaries and humanitarian data. Matched to the 2020 boundaries, so newer units may have none.
Need more than 60 requests a minute?
A free API key raises your limits to 600 a minute and 100,000 a day, and shows you every request you make.