A command-line tool for batch validation of Nigerian bank account numbers (NUBAN). Reads accounts from a CSV file, queries the NUBAN API with bounded concurrency and per-request rate limiting, and writes the results to an Excel workbook with per-row status and a summary sheet.
- Node.js 18 or newer.
- A NUBAN API key. Sign up and generate one at https://app.nuban.com.ng.
git clone <repo-url> nuban-cli
cd nuban-cli
npm install
cp .env.example .env
# Open .env and set NUBAN_API_KEY to your key.Basic run (uses defaults from .env):
node src/cli.js --input accounts.csvCustom output path:
node src/cli.js -i accounts.csv -o reports/may-2026.xlsxOverride concurrency for this run only:
node src/cli.js -i accounts.csv -c 10Show stack traces on error (for debugging):
DEBUG=true node src/cli.js -i accounts.csvThe first row must be headers. Header names are case-insensitive; the following variants are accepted:
| Canonical field | Accepted header variants |
|---|---|
account_number |
account_number, account_no, acc_no, accountnumber |
bank_code |
bank_code, bank_id, bankcode |
Per-row validation:
account_number— exactly 10 digits.bank_code— exactly 3 or 6 digits.
Rows that fail validation are not aborted; they appear in the output with status = VALIDATION_ERROR.
Example:
account_number,bank_code
0123456789,057
1234567890,058
2345678901,057One row per input record, in original CSV order. Failed rows have a light-red background; the header is frozen.
| Column | Contents |
|---|---|
| Account Number | from input |
| Bank Code | from input |
| Bank Name | from API on success; empty on failure |
| Account Name | from API on success; error reason on failure |
| Status | SUCCESS, API_ERROR, or VALIDATION_ERROR |
| Error | error reason on failure; empty on success |
API error reasons (appear in Error, and in Account Name for failed rows):
| Reason | Trigger |
|---|---|
NOT_FOUND |
API returned no matching account. |
INVALID_ACCOUNT |
API rejected the input as malformed. |
TIMEOUT |
Request exceeded REQUEST_TIMEOUT_MS. |
NETWORK_ERROR |
DNS / connection failure. |
RATE_LIMITED |
API returned HTTP 429. |
UNKNOWN_ERROR |
Anything else (5xx, malformed response, etc.). |
VALIDATION_ERROR rows carry a human-readable validation message in Error (e.g. account_number must be exactly 10 digits).
A two-column key/value table:
| Metric | Value |
|---|---|
| Total rows | count |
| Succeeded | count |
| Failed (API) | count |
| Failed (Validation) | count |
Set these in .env. Only NUBAN_API_KEY is required.
| Variable | Default | Purpose |
|---|---|---|
NUBAN_API_KEY |
(required) | Your NUBAN API key. The CLI exits with code 1 if missing. |
CONCURRENCY_LIMIT |
5 |
Max simultaneous in-flight API requests. Override with -c. |
REQUESTS_PER_SECOND |
0.25 |
Token-bucket refill rate. The default 0.25 matches the NUBAN free-tier limit of 15 req/min. Fractional values allowed. |
REQUEST_TIMEOUT_MS |
5000 |
Per-request timeout in milliseconds. |
RETRY_ATTEMPTS |
2 |
Retries per request after the first failure (only TIMEOUT / NETWORK_ERROR). |
OUTPUT_FILE |
output.xlsx |
Default output path. Override with -o. |
CONCURRENCY_LIMIT and REQUESTS_PER_SECOND are independent: concurrency caps how many requests can be in flight simultaneously, while the rate limiter caps long-run throughput. With the default 0.25 rps, throughput is the binding constraint regardless of concurrency — at startup the CLI prints an estimate so you know what to expect (e.g. Estimated time: ~67 min for 1000 rows at 15 req/min).
Error: NUBAN_API_KEY is not set. Copy .env.example to .env and fill in your key.
You haven't created .env, or the key is blank. Run cp .env.example .env and populate NUBAN_API_KEY.
High failure rate (many TIMEOUT or RATE_LIMITED rows).
The API is being asked for more than it can serve. Lower CONCURRENCY_LIMIT in .env, or pass -c 2 and raise gradually until failures stay under your tolerance.
Most or all requests time out.
First, confirm the host is reachable: curl -I https://app.nuban.com.ng. If your network is reachable but slow, raise REQUEST_TIMEOUT_MS (e.g. to 15000). If you suspect a different bug, run with DEBUG=true to see the underlying stack trace.
.env is .gitignored because it holds your NUBAN API key — that key authenticates billable API calls and grants access to account-lookup data.
- Never commit
.env, the raw key, or any log/screenshot containing the key. If a key leaks, rotate it immediately at https://app.nuban.com.ng. - The CLI loads the key into a non-enumerable property of the config object, so
console.log(config)andJSON.stringify(config)cannot expose it. - The logger redacts any metadata field whose name contains
key,token,secret,password, orauthorization. - The HTTP client rewrites the API key out of any error URL or message before it reaches the logger.
These defenses reduce accidental leakage but do not substitute for keeping .env private.