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

ParamTypeRequiredDescription
acc_nostringyesExactly 10 characters (leading zeros count).
bankstringyesBank 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

StatusMeaning
401Missing, invalid, or revoked API key.
404Bank fragment matched nothing (or multiple banks — the error lists the candidates and their codes).
422Validation failed — acc_no must be exactly 10 characters and bank is required.
429Daily rate limit exceeded (free tier: 100/day per key).
502Upstream 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

VariableDefaultDescription
PORT8787HTTP 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_DIRECT0If 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./dataDirectory for the JSON store (users, keys, usage).
KEEPALIVE_INTERVAL240Seconds 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.