API Reference
Everything you need to integrate nuAlt in under 5 minutes.
Authentication
All requests require your API key. Pass it in the Authorization header (preferred):
Authorization: Bearer nualt_yourkeyhere
…or as a query parameter (useful for quick tests, not recommended for production since it can leak into logs):
https://api.nualt.app/v1/resolve?acc_no=...&bank=...&key=nualt_yourkeyhere
Get a free key at the dashboard — instant, no credit card. Keys are shown in full only once, at creation — copy it immediately. Revoking a key takes effect instantly.
Base URL
https://api.nualt.app/v1
Endpoints
Resolve account GET /resolve
Returns the account holder name for a Nigerian NUBAN account.
Query parameters
| Param | Type | Required | Description |
|---|---|---|---|
acc_no | string | yes | Exactly 10 characters (leading zeros count). |
bank | string | yes | Bank code (e.g. 100004) or a unique name fragment (e.g. opay). Must match exactly one bank — ambiguous fragments return 404. |
Not sure which bank? Call /banks first to find the right code.
Example request
# curl curl "https://api.nualt.app/v1/resolve?acc_no=0123456789&bank=100004" \ -H "Authorization: Bearer nualt_yourkey"
Example response (200)
{
"ok": true,
"bank": { "code": "100004", "name": "Opay" },
"result": [{
"account_name": "JANE DOE",
"account_number": "0123456789",
"bank_code": "100004"
}]
}
Error responses
| Status | Meaning |
|---|---|
401 | Missing, invalid, or revoked API key. |
404 | Bank fragment matched nothing (or multiple banks — the error lists the candidates and their codes). |
422 | Validation failed — acc_no must be exactly 10 characters and bank is required. |
429 | Daily rate limit exceeded (free tier: 100/day per key). |
502 | Upstream NUBAN switch failed (all proxies exhausted) or returned no match for the account. |
List banks GET /banks
Returns all 517 supported Nigerian banks, optionally filtered by a case-insensitive substring on bank name or code.
curl "https://api.nualt.app/v1/banks?q=opay" \ -H "Authorization: Bearer nualt_yourkey"
{
"count": 1,
"query": "opay",
"banks": [{ "bank_name": "Opay", "code": "100004" }]
}
Rate limits
The free tier allows 100 lookups per day per API key. If you exceed the limit, you'll get 429 Too Many Requests. Your dashboard shows current usage.
Self-hosting
nuAlt is self-hostable — the resolver rotates a pool of Nigerian proxies and solves the upstream ALTCHA proof-of-work challenge on each request.
git clone <repo> && cd nu-alt
pip install -r requirements.txt
python3 server.py # http://127.0.0.1:8787
Environment variables
| Variable | Default | Description |
|---|---|---|
PORT | 8787 | HTTP port to listen on. |
RESEND_API_KEY | — | If set, dashboard sign-in emails a magic link via Resend; otherwise the session token is returned directly (dev mode). |
NU_ALLOW_DIRECT | 0 | If 1, fall back to a direct (proxy-less) connection when the whole proxy pool is dead. Off by default so your server IP isn't exposed to the upstream. |
NU_DATA_DIR | ./data | Directory for the JSON store (users, keys, usage). |
KEEPALIVE_INTERVAL | 240 | Seconds between self-pings (Render free-tier anti-spin-down; auto-enabled when RENDER_EXTERNAL_URL is set). |
Ops endpoints: GET /health, GET /proxies, POST /proxies/refresh, POST /proxies/recheck.
Code samples
JavaScript (fetch)
const r = await fetch( "https://api.nualt.app/v1/resolve?acc_no=0123456789&bank=100004", { headers: { Authorization: "Bearer nualt_yourkey" } } ); if (!r.ok) throw new Error(`HTTP ${r.status}: ${await r.text()}`); const { result } = await r.json(); console.log(result[0].account_name);
Python (requests)
import requests r = requests.get( "https://api.nualt.app/v1/resolve", params={"acc_no": "0123456789", "bank": "100004"}, headers={"Authorization": "Bearer nualt_yourkey"}, timeout=60, ) r.raise_for_status() data = r.json() print(data["result"][0]["account_name"])
Node.js (axios)
const axios = require("axios"); const { data } = await axios.get( "https://api.nualt.app/v1/resolve", { params: { acc_no: "0123456789", bank: "100004" }, headers: { Authorization: "Bearer nualt_yourkey" }, timeout: 60000, } ); console.log(data.result[0].account_name);
PHP (cURL)
$ch = curl_init("https://api.nualt.app/v1/resolve?acc_no=0123456789&bank=100004"); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer nualt_yourkey"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 60); $res = json_decode(curl_exec($ch), true); if (!isset($res['ok'])) { http_response_code(502); exit('resolve failed'); } echo $res['result'][0]['account_name'];
cURL (retry on 502)
# lookups can occasionally exhaust the proxy pool - retry up to 3 times for i in 1 2 3; do curl -sf "https://api.nualt.app/v1/resolve?acc_no=0123456789&bank=100004" \ -H "Authorization: Bearer nualt_yourkey" && break sleep 2 done
Need help?
Open an issue or email hello@nualt.app.