Open, no-key endpoints for building on Nigeria 2.0's election data — political parties and verified election results, per state, down to the LGA.
The API is free, needs no API key or authentication, and returns JSON. All responses set Access-Control-Allow-Origin: *, so you can call it directly from the browser. Please cache responses where you can — the data changes rarely.
Public endpoints live under /api/v1/. We will not make breaking changes to a version once published.
Paste the prompt below into ChatGPT, Claude, or any tool that can fetch URLs, then ask your question in plain English (e.g. “which Lagos LGAs did the LP win in 2023?” or “list the worst over-voting outliers in Kano”). It's a succinct description of this whole API, so the model knows exactly which endpoint to call.
You can query Nigeria 2.0's open election API (no key, returns JSON, CORS-open).
Base URL: https://api.nigeria2.com
Conventions:
- States are keyed by a canonical geo_id like nga_3 (Akwa Ibom). Get the full list from GET /api/v1/states. In browsable URLs a state is a slug (akwa-ibom), an LGA is "{lga_id}-{name}" (e.g. 162-abak), a ward is its INEC code with / written as - (03-01-01), a polling unit is its number (001). The full INEC pu_code uses slashes: 03/01/01/001.
- Election years are 2019 and 2023. Offices: presidential, governor, senate.
- Every figure is evidence (our best reading of INEC result sheets), not an official count.
Endpoints:
- GET /api/v1/parties[?active=true] — political parties. GET /api/v1/parties/{acronym} for one.
- GET /api/v1/states — every state with its geo_id.
- GET /api/v1/results/{year} — all states with results that year + a national summary.
- GET /api/v1/results/{year}/{geo_id} — one state's LGA-by-party results, senate/house, and evidence.
- GET /elections/{year}/{state}[/{lga}[/{ward}[/{pu}]]] — browse results down to a polling unit (twins the website).
- GET /api/v1/polling-units/{pu_code}/sheets — the INEC result sheet(s) for a unit, with our transcription model's status + comment.
- GET /api/v1/polling-units/{pu_code}/sheets/{office} — the exact transcription JSON we produced for that sheet.
- GET /api/v1/outliers/{year}?state=&office=&rule=&limit=&offset= — polling units that look anomalous (rules: over_voting = votes >= 2x registered; large_roll = registered > 10000; no_roll = no register but > 2000 votes). Each row includes the sheet link and every vote we recorded grouped by source. limit max 100; paginate with offset (response has has_more/next_offset).
To answer a question, choose the narrowest endpoint, fetch it, and read the JSON. Prefer geo_id over names. Cache where you can.The API is read-only and public, so this is safe to share. Every figure is our transcription of INEC sheets — evidence, not an official count.
List every political party we track, with national officers and 2019 activity status.
| Name | Type | Description |
|---|---|---|
| active | boolean · optional | Filter to parties that were active in the 2019 general election (true) or not (false). Omit for all. |
curl "https://api.nigeria2.com/api/v1/parties?active=true"
{
"count": 18,
"parties": [
{
"acronym": "APC",
"name": "All Progressives Congress",
"chairman": "Abdullahi Umar Ganduje",
"secretary": "Ajibola Basiru",
"treasurer": "...",
"financial_secretary": "...",
"legal_adviser": "...",
"address": "...",
"active": true
}
]
}Fetch a single party by its acronym (case-insensitive). Returns 404 if unknown.
| Name | Type | Description |
|---|---|---|
| acronym | string · required | The party acronym, e.g. APC, lp, pdp. |
curl "https://api.nigeria2.com/api/v1/parties/APC"
{
"acronym": "APC",
"name": "All Progressives Congress",
"chairman": "Abdullahi Umar Ganduje",
"secretary": "Ajibola Basiru",
"treasurer": "...",
"financial_secretary": "...",
"legal_adviser": "...",
"address": "...",
"active": true
}Results are organised by year then state. Every state is keyed by a canonical geo_id (e.g. Akwa Ibom is nga_3) — always look a state up by its geo_id, never by name, since spellings vary in the underlying data. Use /api/v1/states to get the full list of ids.
Note: every figure we publish is evidence — our best reading of the sheets and official collation, not a definitive count. A state's score is a merge of the evidence behind it, which each result carries in its evidence array.
List all 36 states + the FCT with the canonical geo_id every results endpoint uses.
curl "https://api.nigeria2.com/api/v1/states"
{
"count": 37,
"states": [
{ "geo_id": "nga_1", "name": "Abia" },
{ "geo_id": "nga_3", "name": "Akwa Ibom" },
...
]
}Every state we hold results for in a given election year, which races are available for each, per-office party totals and winner, plus a national summary. Then drill into one state with the endpoint below.
| Name | Type | Description |
|---|---|---|
| year | string · required | Election year, e.g. 2019 or 2023. |
curl "https://api.nigeria2.com/api/v1/results/2023"
{
"year": "2023",
"states": [
{
"geo_id": "nga_3",
"state": "Akwa Ibom",
"has_presidential": true,
"has_governor": true,
"has_senate": false,
"has_house": false,
"party_totals": {
"presidential": {
"parties": { "PDP": 214012, "LP": 132683, "APC": 160620 },
"total": 507315, "winner": "PDP", "level": "lga"
},
"governor": { "parties": { "...": 0 }, "winner": "PDP", "level": "lga" }
}
}
],
"summary": {
"presidential": { "parties": { "APC": 8794726, "LP": 6101533 }, "winner": "APC", "states": 37 }
}
}One state's full results for a year: presidential and governor as an LGA-by-party table (or a state-level summary where we have no LGA breakdown, e.g. 2019 presidential), Senate and House of Reps as per-constituency candidate lists, and the evidence behind the state's score. Returns 404 for an unknown state.
| Name | Type | Description |
|---|---|---|
| year | string · required | Election year, e.g. 2023. |
| geo_id | string · required | Canonical state id from /api/v1/states, e.g. nga_3. |
curl "https://api.nigeria2.com/api/v1/results/2023/nga_3"
{
"year": "2023",
"geo_id": "nga_3",
"state": "Akwa Ibom",
"presidential": {
"parties": ["PDP", "APC", "LP"],
"party_totals": { "PDP": 214012, "APC": 160620, "LP": 132683 },
"winner": "PDP",
"total_votes": 507315,
"lga_count": 31,
"lgas": [
{ "lga_id": 162, "lga": "Abak",
"parties": { "PDP": 12345, "APC": 6789, "LP": 2100 }, "total": 21713 }
]
},
"presidential_state": null,
"governor": { "parties": ["..."], "lgas": ["..."] },
"senate": null,
"house": null,
"evidence": [
{ "election_type": "presidential", "year": "2023", "kind": "rollup",
"source": "sum of LGAs", "total_votes": 507315,
"party_results": [ { "party": "PDP", "votes": 214012 } ] }
]
}Every results page on the website has a data twin here, using the same URL slugs — so a page you can browse has a JSON endpoint one step away. Walk down the levels: state → LGA → ward → polling unit. Each returns roughly what that page shows.
| Path | Returns |
|---|---|
| /elections/{year}/{state} | A state’s results (pres + gov by LGA, senate/house, evidence) |
| /elections/{year}/{state}/{lga} | One LGA: wards, per-party votes, evidence |
| /elections/{year}/{state}/{lga}/{ward} | A ward’s polling units + ward-level result |
| /elections/{year}/{state}/{lga}/{ward}/{pu} | One polling unit: result, every piece of evidence, and the result sheets |
state = akwa-ibom · lga = 162-abak (the leading number is the LGA id) · ward = 03-01-01 (INEC ward code, / written as -) · pu = 001 (unit number).
curl "https://api.nigeria2.com/elections/2023/akwa-ibom/162-abak/03-01-01/001"
Every INEC result sheet we hold for a polling unit (one per office), each with its link, download status, and our transcription model's analysis of the scan — its confidence status (valid / unsure / blurry), legibility, the check flags, and the model's own validity_notes comment. Use the full INEC code, e.g. 03/01/01/001.
curl "https://api.nigeria2.com/api/v1/polling-units/03/01/01/001/sheets"
One sheet plus the exact transcription(s) we produced of it — the verbatim JSON the model returned: party votes, the poll summary, the validity block (with the model's comment), and its transcription notes. office is presidential | governor | senate. This is the raw data behind everything else.
curl "https://api.nigeria2.com/api/v1/polling-units/03/01/01/001/sheets/presidential"
{
"pu_code": "03/01/01/001", "election_type": "presidential", "year": "2023",
"sheet_url": "https://irev.../result-sheet.pdf", "sheet_status": "saved",
"analysis": {
"status": "valid", "legibility": "readable", "model": "qwen/qwen3.5-9b",
"sum_check_passed": true, "totals_consistent": true,
"validity_notes": "", "discrepancies": null
},
"transcriptions": [
{
"source_image": "001.jpg",
"poll_summary": { "1_registered_voters": "179", "7_total_valid_votes": "153" },
"party_results": [ { "party": "APC", "votes_figures": "87" }, ... ],
"validity": { "status": "valid", "validity_notes": "" },
"transcription_notes": { "legibility": "readable", "discrepancies": "" }
}
]
}Polling-unit results that look anomalous — flagged against the canonical INEC register (not the transcribed one). Each row lists which rules it tripped. These are candidates for review, not proof of fraud. Also reachable at /elections/{year}/outliers.
| Rule | Flagged when |
|---|---|
| over_voting | Total votes ≥ 2× the registered voters |
| large_roll | Registered voters > 10000 |
| no_roll | No registered voters on record, but > 2000 votes |
| Name | Type | Description |
|---|---|---|
| state | string · optional | State slug, e.g. akwa-ibom. Omit for all states. |
| office | string · optional | presidential | governor | senate. |
| rule | string · optional | Limit to one rule (over_voting | large_roll | no_roll). |
| limit | int · optional | Page size, default 200, max 1000. |
| offset | int · optional | Rows to skip (pagination). |
curl "https://api.nigeria2.com/api/v1/outliers/2023?office=presidential&rule=over_voting&limit=50"
{
"year": "2023",
"count": 50,
"total": 4424,
"limit": 50,
"offset": 0,
"rules": { "over_voting": "total votes >= 2x the canonical registered voters", "...": "..." },
"outliers": [
{
"pu_code": "08/24/07/042", "pu_name": "...",
"state": "Borno", "lga": "...", "ward": "...", "ward_code": "08/24/07",
"election_type": "presidential", "year": "2023",
"registered_voters": 512, "total_votes": 1400, "winner": "APC",
"ratio": 2.73, "rules": ["over_voting"],
"sheets": [
{ "election_type": "presidential", "year": "2023",
"url": "https://.../result-sheet.pdf", "status": "saved" }
],
"votes_by_source": [
{ "source": "LLM (qwen3.5-9b)", "kind": "llm", "method": "unsure",
"valid_votes": 1400, "parties": { "APC": 700, "PDP": 500, "LP": 200 } }
]
}
]
}sheets are the INEC result sheet(s) for the unit (with a download link and status, including broken/missing ones). votes_by_source lists every set of party votes we recorded for that unit and office, grouped by contributor (e.g. our qwen transcription) — so you can compare readings side by side.
| Field | Type | Description |
|---|---|---|
| acronym | string | Short party code (unique), e.g. APC. |
| name | string | Full registered party name. |
| chairman | string | National chairman. |
| secretary | string | National secretary. |
| treasurer | string | National treasurer. |
| financial_secretary | string | National financial secretary. |
| legal_adviser | string | National legal adviser. |
| address | string | Registered national headquarters address. |
| active | boolean | Fielded at least one candidate in the 2019 general election. |
Officer and address fields may be empty strings where we don't yet hold that detail.
The data is provided as-is for civic, research and journalistic use. Attribution to Nigeria 2.0 is appreciated. Please don't hammer the endpoints — cache where practical.