N2.0
LOGIN
Developers

Public API

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.

Getting started

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.

Base URL
https://api.nigeria2.com
Versioning

Public endpoints live under /api/v1/. We will not make breaking changes to a version once published.

Query with AI

Let an LLM query the data for you

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.

Political Parties

GET/api/v1/parties

List every political party we track, with national officers and 2019 activity status.

Query parameters
NameTypeDescription
activeboolean · optionalFilter to parties that were active in the 2019 general election (true) or not (false). Omit for all.
Example request
curl "https://api.nigeria2.com/api/v1/parties?active=true"
Example response
{
  "count": 18,
  "parties": [
    {
      "acronym": "APC",
      "name": "All Progressives Congress",
      "chairman": "Abdullahi Umar Ganduje",
      "secretary": "Ajibola Basiru",
      "treasurer": "...",
      "financial_secretary": "...",
      "legal_adviser": "...",
      "address": "...",
      "active": true
    }
  ]
}
GET/api/v1/parties/{acronym}

Fetch a single party by its acronym (case-insensitive). Returns 404 if unknown.

Path parameters
NameTypeDescription
acronymstring · requiredThe party acronym, e.g. APC, lp, pdp.
Example request
curl "https://api.nigeria2.com/api/v1/parties/APC"
Example response
{
  "acronym": "APC",
  "name": "All Progressives Congress",
  "chairman": "Abdullahi Umar Ganduje",
  "secretary": "Ajibola Basiru",
  "treasurer": "...",
  "financial_secretary": "...",
  "legal_adviser": "...",
  "address": "...",
  "active": true
}

Election Results

How results are organised

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.

GET/api/v1/states

List all 36 states + the FCT with the canonical geo_id every results endpoint uses.

Example request
curl "https://api.nigeria2.com/api/v1/states"
Example response
{
  "count": 37,
  "states": [
    { "geo_id": "nga_1", "name": "Abia" },
    { "geo_id": "nga_3", "name": "Akwa Ibom" },
    ...
  ]
}
GET/api/v1/results/{year}

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.

Path parameters
NameTypeDescription
yearstring · requiredElection year, e.g. 2019 or 2023.
Example request
curl "https://api.nigeria2.com/api/v1/results/2023"
Example response
{
  "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 }
  }
}
GET/api/v1/results/{year}/{geo_id}

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.

Path parameters
NameTypeDescription
yearstring · requiredElection year, e.g. 2023.
geo_idstring · requiredCanonical state id from /api/v1/states, e.g. nga_3.
Example request
curl "https://api.nigeria2.com/api/v1/results/2023/nga_3"
Example response
{
  "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 } ] }
  ]
}
Browsable results (mirrors the website)

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.

PathReturns
/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
Slugs (same as the website)

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).

Example request
curl "https://api.nigeria2.com/elections/2023/akwa-ibom/162-abak/03-01-01/001"

Sheets & Transcriptions

GET/api/v1/polling-units/{pu_code}/sheets

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.

Example request
curl "https://api.nigeria2.com/api/v1/polling-units/03/01/01/001/sheets"
GET/api/v1/polling-units/{pu_code}/sheets/{office}

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.

Example request
curl "https://api.nigeria2.com/api/v1/polling-units/03/01/01/001/sheets/presidential"
Example response (abridged)
{
  "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": "" }
    }
  ]
}

Outliers

GET/api/v1/outliers/{year}

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.

Rules
RuleFlagged when
over_votingTotal votes ≥ 2× the registered voters
large_rollRegistered voters > 10000
no_rollNo registered voters on record, but > 2000 votes
Query parameters
NameTypeDescription
statestring · optionalState slug, e.g. akwa-ibom. Omit for all states.
officestring · optionalpresidential | governor | senate.
rulestring · optionalLimit to one rule (over_voting | large_roll | no_roll).
limitint · optionalPage size, default 200, max 1000.
offsetint · optionalRows to skip (pagination).
Example request
curl "https://api.nigeria2.com/api/v1/outliers/2023?office=presidential&rule=over_voting&limit=50"
Example response
{
  "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.

Reference

Party response fields
FieldTypeDescription
acronymstringShort party code (unique), e.g. APC.
namestringFull registered party name.
chairmanstringNational chairman.
secretarystringNational secretary.
treasurerstringNational treasurer.
financial_secretarystringNational financial secretary.
legal_adviserstringNational legal adviser.
addressstringRegistered national headquarters address.
activebooleanFielded 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.

Terms

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.

NIGERIA 2.0
A movement for every Nigerian
Projects
Data
About Us
Follow
© 2026 Nigeria 2.0 · Techies for a Better Nigeria