1Quick start
Get a free key, then call any endpoint with it. That's the whole flow — no signup form, no approval wait.
# 1. Get a key curl -X POST https://ngscorecard.com/api/v1/keys \ -H "Content-Type: application/json" \ -d '{"email":"you@example.com"}' # → { "key": "ngs_live_...", "tier": "free", "rateLimit": "60 requests/minute" } # 2. Use it curl https://ngscorecard.com/api/v1/tinubu/promises \ -H "X-API-Key: ngs_live_..."
2Authentication & rate limits
Every data endpoint requires an X-API-Key header. Keys are free, self-serve, and tied to an email (requesting a key again with the same email returns your existing one, so you can't accidentally pile up duplicates).
| Tier | Rate limit | Auth |
|---|---|---|
| Free (current) | 60 requests/minute per key | X-API-Key header |
| Widget summary | 30 requests/minute per caller IP | none — public, CORS-open |
Exceeding the limit returns 429 with a JSON error body. Missing or invalid keys return 401. Requesting an unknown administration key returns 400 (or 404 for the widget endpoint).
3Endpoints
Presidents and governors are separate lists, each with their own valid :admin keys — every other data route follows the same shape: /api/v1/:admin/:category. (e.g. tinubu is a president, otti and ododo are governors) — GET /api/v1/presidents for the 5 federal presidents, GET /api/v1/governors for the 36 state governors.
| Method | Path | Returns |
|---|---|---|
| GET | /api/v1/presidents | The 5 federal presidents and their :admin keys |
| GET | /api/v1/governors | The 36 state governors and their :admin keys |
| GET | /api/v1/:admin/promises | Campaign promises, status, and sourcing |
| GET | /api/v1/:admin/inherited | Inherited problems and their resolution status |
| GET | /api/v1/:admin/fraud | Fraud allegations, amounts, and outcomes |
| GET | /api/v1/:admin/orders | Executive orders and directives |
| GET | /api/v1/:admin/ministers | Ministers/commissioners and performance notes |
| GET | /api/v1/:admin/bills | Legislation (federal administrations only) |
| GET | /api/v1/:admin/appointments | Key appointments across government |
| GET | /api/v1/:admin/judgments | Court judgments and compliance |
| GET | /api/v1/:admin/budget | Annual budgets, revenue, and debt service (see note below) |
| GET | /api/v1/:admin/governors | Historical state governors listed under a president's own profile — not the same list as GET /api/v1/governors above (federal administrations only) |
| GET | /api/v1/:admin/indicators | Tracked economic/performance indicators over time |
| POST | /api/v1/keys | Issue (or retrieve) a free API key for an email |
On budget data: where a figure isn't publicly reported anywhere, the field is null — never a guessed number. A null means "not published," not "zero."
4Embeddable widget
Drop a live, self-updating promise-tracking bar into any page. No API key needed — it's public and CORS-open by design.
<div data-ngscorecard-admin="tinubu"></div> <script src="https://ngscorecard.com/widget.js" async></script>
Or, for a single widget, skip the <div> and put the admin key directly on the script tag:
<script src="https://ngscorecard.com/widget.js" data-ngscorecard-admin="tinubu" async></script>
Live example — this is the actual widget script, running on this actual page:
5Example response
GET /api/v1/otti/promises — trimmed to one item:
[
{
"id": 1,
"title": "Rebuild Port Harcourt Road in Aba",
"category": "Infrastructure",
"status": "kept",
"promise": "Promised to restore major abandoned Aba roads...",
"assessment": "The reconstruction of Port Harcourt Road in Aba became...",
"source": "https://abiastate.gov.ng/...",
"sourceLabel": "Abia State Government",
"updated": "May 2025"
}
]6Stability & deprecation
This API is public infrastructure. Downstream users shouldn't be broken without warning.
- Additive changes are not breaking. New fields on a response, new endpoints, and new optional parameters can land in
v1at any time — write clients that ignore fields they don't recognise. - Breaking changes get a new version. Removing or renaming a field, changing a type, or changing the meaning of a value happens under
/api/v2, never in place. - Old versions stay up for at least 12 months after a successor ships.
- Sunsets are announced, not silent. We post the notice on this page and email everyone who holds an API key, and the old version keeps working for the whole window.