← All posts
🇬🇭DevOps

I Built GhanaAPI Because Ghana's Reference Data Deserved Better Than a PDF

Michael Sintim-Koree · July 2026

The specific frustration that started this was a form field. Building a project that needed a validated list of Ghana's regions and districts, the most authoritative source available was a PDF from the Ghana Statistical Service, last updated inconsistently, with no machine-readable version anywhere obvious. To get a dropdown of Ghana's regions you had to type them manually or scrape a government portal that returned different spellings depending on which page you landed on.

That's a solved problem in most places. The UK has its open data registers. Nigeria has a few reasonable third-party APIs. Ghana didn't have anything worth trusting in production. That gap is what GhanaAPI is for.


What GhanaAPI actually covers

The core data is Ghana's administrative hierarchy: regions, districts, and constituencies. After the 2019 creation of six new regions, most existing datasets were out of date. Brong-Ahafo became three separate regions (Bono, Bono East, and Ahafo). Western Region split into Western and Western North. Volta spawned Oti. Any dataset that hadn't been updated since before that reorganization was serving wrong data, silently.

Beyond administrative divisions, GhanaAPI covers public holidays (actual Ghanaian holidays, not just a generic calendar anyone could have generated), area codes, major cities with coordinates, and Ghana Card number format validation. The validation endpoint gets the most questions. Ghana Card is the national identity card issued by the National Identification Authority, and has a specific format structure; a validator that doesn't require hitting a government system is useful for form validation when you don't want an external dependency on government uptime.

The API is REST, returns JSON, and is free to use. No authentication for read-only endpoints.


Why sourcing the data was harder than writing the code

The hardest part of this project was not the code. Sourcing accurate, current, authoritative data for Ghana is genuinely difficult. Government portals are inconsistent. Wikipedia is sometimes right. The Electoral Commission's district list differs from the Ghana Statistical Service's depending on which boundary delimitation exercise they're referencing.

For the administrative data, three sources were cross-referenced: the Electoral Commission's official constituency list, the GSS's 2021 Population and Housing Census district data, and the Local Government Service district registry. Where they disagreed, primary government publications were used to resolve it. That reconciliation process took longer than building the API itself.

Public holidays had their own complications. Ghana has a mix of fixed-date holidays and moveable ones tied to the Islamic calendar (Eid al-Fitr and Eid al-Adha), which means the API has to handle date calculation, not just lookup. The government's official holiday announcements sometimes don't come until weeks before the date, which creates a gap between what the calendar should say and what's officially confirmed. GhanaAPI handles this with calculated dates and a manual update process when official confirmation comes. It's not a perfect solution, but it's honest about what it doesn't know.


How it's built

The stack is straightforward. Node.js with Express for the API layer, data stored as structured JSON with a validation layer on top, deployed on Railway. No database for the reference data; it changes infrequently enough that flat JSON files in the repo are the right call. Querying a database for a list of regions that changes once a decade is overhead with no return.

The endpoints are read-only lookups with filtering. Get all regions, get districts by region, get constituencies by district, validate a Ghana Card format. Response times are fast because there's almost nothing between the request and the response: no ORM, no joins, just a JSON lookup with some filtering logic.

Rate limiting was added early to prevent the free tier from becoming a liability if something went unexpectedly viral. The limits are permissive for normal use. You'd have to be intentionally abusing it to hit the ceiling.


What went wrong in the first version

The first version had no versioning. That was caught before it became a real problem, but only barely. A breaking change to the response schema would have required anyone using the API to update their integration with no migration path. v1 is now the stable path and any future breaking changes will go through a new version.

The spelling and diacritics issue also turned out to matter more than anticipated. Some district names have variant spellings in common use. Ashanti Region is spelled correctly in the Electoral Commission's list but shows up as Ashanti, Asante, or Asanti in other sources and in how people actually type it. The API now handles common variants through normalized search, so you can query with either spelling and get the canonical result back.

The documentation was an afterthought in version one. A developer found a bug by using an endpoint in a way that hadn't been clearly documented, which meant the documentation was broken, not their usage. The docs were rewritten after that, with explicit examples for every endpoint and clear notes on the edge cases.


Why an API and not a dataset download

Releasing it as a static dataset (a GitHub repository with JSON files that anyone could download and use locally) was considered. That would work for most use cases. The API format is better for a few reasons that add up.

  • When data changes (new holiday announced, district boundary updated), the API shows it immediately. A downloaded JSON file stays stale until someone manually updates it.
  • Form validation in browser applications needs a network call anyway. Calling GhanaAPI directly is simpler than bundling the dataset into the application and keeping it current.
  • The Ghana Card validation endpoint does computation, not just lookup. That logic belongs server-side regardless.
  • Filtering server-side is faster than downloading the full dataset and filtering client-side, particularly for mobile applications where bandwidth matters.

The static dataset approach is still available. The underlying data is on GitHub and the repository is public, so anyone who wants to use it without an API dependency can.


What's next: bank codes, then GhanaPost GPS

The next thing on the list is Ghana's bank codes and branch data. Getting programmatic access to which bank codes map to which institutions is currently a manual lookup exercise, and that's exactly the kind of friction GhanaAPI was built to remove.

After that, the goal is to tackle Ghana Post GPS data. GhanaPostGPS is Ghana's official digital property addressing system, dividing the country into 5m x 5m grids and assigning each a unique digital address. The system exists, the codes are assigned, and there's an official app on both iOS and Android. A clean API for looking up locations by their GhanaPost address, or converting coordinates to a GhanaPost code, doesn't exist yet. The data sourcing challenges are real, and getting it right matters more than shipping something half-baked. Bank codes first, then GPS, and the state of the sourcing will determine the timeline from there.

Whether bank codes or GPS lookup comes next depends partly on what people are actually trying to do with GhanaAPI. That's the honest answer. The project started because of a specific gap; future additions will follow the same logic.


Wrong data is worse than no data

Developers building for Ghanaian users keep running into the same problem that started this project. The reference data exists somewhere, in a PDF, on a government portal, in someone's spreadsheet. It just doesn't exist in a form that's easy to use in software.

The thing that matters most is correctness. Wrong reference data is worse than no reference data, because at least no data produces an obvious error instead of a silent wrong answer. A 404 is genuinely preferable to returning the wrong district name with a 200. That's the standard applied when cross-referencing those three administrative sources, and it's the standard that will apply when the bank codes go in.


If you're building something for the Ghanaian market and hitting a reference data gap that GhanaAPI doesn't cover, I'd genuinely like to know what it is. Bank codes and GhanaPost lookup are next on my list, but if something else is actually blocking you right now, that changes the priority.