Building a bank-transfer validation flow with MansaAPI (Node.js)
A complete Node.js tutorial: validate a NUBAN, resolve the bank code, and confirm the institution before sending a Nigerian bank transfer.
Before your app sends a Naira transfer, you want to catch errors early: a mistyped account number, a wrong bank selection, a non-existent institution. This tutorial builds a complete pre-transfer validation flow in Node.js using the MansaAPI identity suite.
What we're building
A reusable validateTransferDestination() function that:
1. Checks the NUBAN checksum (free, instant)
2. Confirms the bank code maps to a real institution
3. Returns a clean result your payment code can branch onSetup
npm install mansaapiimport { MansaAPI } from "mansaapi";
export const mansa = new MansaAPI({
apiKey: process.env.MANSA_API_KEY!,
});Step 1: NUBAN format check
The NUBAN checksum catches typos and bank/account mismatches before any paid lookup. It's free and instant.
import { mansa } from "./lib/mansa";
async function checkNubanFormat(account: string, bankCode: string) {
const { data } = await mansa.identity.validateNuban(account, bankCode);
return data.valid;
}Step 2: Confirm the institution
import { MansaAPIError } from "mansaapi";
async function resolveBank(bankCode: string) {
try {
const { data: bank } = await mansa.identity.getBank(bankCode);
return bank;
} catch (err) {
if (err instanceof MansaAPIError && err.status === 404) return null;
throw err;
}
}Step 3: Combine into one function
export type TransferCheck =
| { ok: true; bankName: string; bankCode: string; account: string }
| { ok: false; reason: "invalid_format" | "unknown_bank" };
export async function validateTransferDestination(
account: string,
bankCode: string
): Promise<TransferCheck> {
// 1. Format
const formatOk = await checkNubanFormat(account, bankCode);
if (!formatOk) return { ok: false, reason: "invalid_format" };
// 2. Institution
const bank = await resolveBank(bankCode);
if (!bank) return { ok: false, reason: "unknown_bank" };
return { ok: true, bankName: bank.name, bankCode, account };
}Step 4: Use it in your transfer endpoint
import { validateTransferDestination } from "@/validate";
export async function POST(req: Request) {
const { account, bankCode, amount } = await req.json();
const check = await validateTransferDestination(account, bankCode);
if (!check.ok) {
return Response.json({ error: check.reason }, { status: 400 });
}
// check.bankName is safe to show the user for confirmation
// "Send ₦{amount} to {account} at {check.bankName}?"
// ... proceed to your payment provider / name resolution ...
return Response.json({ confirm: check.bankName });
}Why validate before paying
Name-resolution calls cost money per lookup. Running the free NUBAN checksum and bank-code check first means you only pay for lookups that have a real chance of succeeding — typos and wrong-bank selections are rejected for free. On high volume, that's a meaningful saving.
Get a free key and start building — the identity suite (bank codes, NUBAN validation) is on the free tier.