Developer docs
Your first request in a minute
One key, one header, and every dataset answers in the same JSON shape. Everything below works with a free account.
Quickstart
- Create a free account. Your API key is shown once, on your account page; copy it somewhere safe.
- Send it in the
X-API-Keyheader with any request:
curl "https://connect.apighana.com/api/data/districts?limit=5" \ -H "X-API-Key: $APIGHANA_KEY"
Five districts come back. districts is one of the free reference tables (with regions and public_holidays), so this works on any key. The same request in other languages:
curl "https://connect.apighana.com/api/data/districts?page=1&limit=50" \
-H "X-API-Key: $APIGHANA_KEY"
# → { "status": "success", "data": [ … ], "meta": { … } }const response = await fetch(
"https://connect.apighana.com/api/query/schools",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.APIGHANA_KEY,
},
body: JSON.stringify({
select: ["name", "school_type", "district"],
where: [{ column: "region", operator: "=", value: "Northern Region" }],
limit: 50,
}),
},
);
const { data } = await response.json();import os, requests
response = requests.post(
"https://connect.apighana.com/api/query/major_roads",
headers={"X-API-Key": os.environ["APIGHANA_KEY"]},
json={
"select": ["route_ref", "name", "surface", "lanes"],
"where": [
{"column": "road_class", "operator": "=", "value": "Trunk"},
{"column": "surface", "operator": "=", "value": "Asphalt"},
],
"order": {"column": "route_ref", "direction": "asc"},
"limit": 100,
},
)
rows = response.json()["data"]Authentication
Send your key (64 characters) as the X-API-Key header on every request to https://connect.apighana.com. Keys are stored hashed: we cannot show yours again, only rotate it (account page → Regenerate), which stops the old one at once.
Keep the key on your server. A key in a web page or a mobile app can be copied and used by anyone.
Responses and paging
Every answer is the same envelope: status, message, data, and on lists a meta with the page, the limit and the total.
{
"status": "success",
"message": "Records fetched from 'districts'.",
"data": [ { "id": 1, "name": "Accra Metropolitan", "region": "Greater Accra Region", … } ],
"meta": { "page": 1, "limit": 5, "total": 261, "total_pages": 53 }
}Ask for pages with page and limit. The most rows per page depends on your plan (below); a larger limit is capped and the message says so.
Endpoints
| GET/api/datasets | The catalogue: every dataset with its name, sector, row count and price. Public. |
| GET/api/datasets/{name} | One dataset's documentation: columns, types, source, licence and examples. Public. |
| GET/api/data/{name} | The rows. page, limit, search= across text columns, filter=column:value,column:value. |
| POST/api/query/{name} | Choose columns, filter with operators (=, !=, <, <=, >, >=, IN, CONTAINS) and sort, in one JSON body. |
| GET/api/live | Every live series (exchange rates, bank rates, fuel, food, commodities) with its latest value. Public. |
| GET/api/live/{slug} | One series with its history; longer history on paid plans. |
| GET/api/market/{group} | A market board: rates, banks, fuel, food, commodities or indicators. |
| GET/api/news | Ghana news, checked and sectioned, with sources. Through your API key on Developer and up (the News API). |
| GET/api/status | Whether the API, the live feeds and the daily dataset checks are working. Public. |
Dataset names are the ones in the catalogue; each dataset page lists its columns.
Limits by plan
Errors
Errors use the same envelope with status: "error", a message written to be shown, and sometimes a code.
{
"status": "error",
"message": "'hospitals' is not on your key. Licence it for a year, use a free pick if you have one left, or move to the Developer plan for the whole catalogue.",
"code": "ACCESS_REQUIRED"
}400The request is malformed: an unknown column, a bad filter. The message says which.401No key, or the key is wrong or revoked. Send it as X-API-Key.403The dataset is not on your key (code ACCESS_REQUIRED); the message and data.options say how to get it.404No dataset or series by that name.429Over your plan's requests per minute, or the ceiling of 1,000 requests per 15 minutes. Wait for Retry-After seconds.5xxOur side. Retry with a short backoff, and quote the X-Request-Id header when you write to us.
Use it from an AI assistant (MCP)
API Ghana is also an MCP server, so Claude, ChatGPT, Cursor and other assistants that speak the Model Context Protocol can search the catalogue, read rows, query datasets and read the market boards themselves. The tools are read-only and use your key, so your plan's access and limits apply.
{
"mcpServers": {
"api-ghana": {
"type": "http",
"url": "https://connect.apighana.com/mcp",
"headers": {
"X-API-Key": "YOUR_API_KEY"
}
}
}
}Tools: search_datasets, describe_dataset, get_rows, query_dataset, get_market, get_series and search_news. A client that only sends Authorization: Bearer can put the key there instead.
Full reference
Every endpoint, parameter, answer and error, with samples in cURL, JavaScript and Python: the API reference.
To try them in Postman, download the collection and the environment, then paste your key into the environment. For client generators and other tools there is an OpenAPI 3 file.
Questions or a dataset you need: info@apighana.com.