Bank account lookup
Confirm an account number exists and read back the name on it — the standard guard before a first payout to a new beneficiary.
check |
Country | Required fields | Price |
|---|---|---|---|
bank_account_ke |
Kenya | account_no, bank_id |
55 |
bank_account_ng |
Nigeria | number, bank_code |
25 |
Both bank_id and bank_code come from a published list — see
Bank codes.
Kenya takes a numeric bank_id from FinoQ’s own list, not a SWIFT or
clearing code.
curl -X POST "$PH_CONNECT_URL/api/v1/kyc/verify/bank_account_ke" \ -u "$PH_API_USERNAME:$PH_API_PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "account_no": "2096844395", "bank_id": "34" }'const res = await fetch(`${process.env.PH_CONNECT_URL}/api/v1/kyc/verify/bank_account_ke`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Basic ' + Buffer.from( `${process.env.PH_API_USERNAME}:${process.env.PH_API_PASSWORD}`, ).toString('base64'), }, body: JSON.stringify({ account_no: '2096844395', bank_id: '34' }),})
const check = await res.json()
if (check.status !== 'verified') { throw new Error('Account could not be resolved')}
console.log(check.subject_name) // the name on the accountimport os, requests
res = requests.post( f"{os.environ['PH_CONNECT_URL']}/api/v1/kyc/verify/bank_account_ke", auth=(os.environ["PH_API_USERNAME"], os.environ["PH_API_PASSWORD"]), json={"account_no": "2096844395", "bank_id": "34"},)check = res.json()
if check["status"] != "verified": raise RuntimeError("Account could not be resolved")
print(check["subject_name"]){ "lookup_id": "b83f0c2ad95e4711a6de3f40", "check": "bank_account_ke", "category": "bank_account", "country": "KE", "actor_type": "I", "subject_name": "JANE WANJIRU DOE", "status": "verified", "verification_status": "VERIFIED", "source": "prembly", "charged_amount": 55, "charge_currency": "KES", "charge_status": "charged"}Kenyan bank IDs
Section titled “Kenyan bank IDs”| ID | Bank | ID | Bank | ID | Bank |
|---|---|---|---|---|---|
| 1 | KCB | 15 | Consolidated Bank | 29 | SBM |
| 2 | Standard Chartered Bank | 16 | Credit Bank | 30 | Housing Finance |
| 3 | Absa Bank | 17 | Access Bank | 31 | Diamond Trust Bank |
| 4 | Bank of India | 18 | Stanbic Bank | 32 | Mayfair Bank |
| 5 | Bank of Baroda | 19 | ABC Bank | 33 | Sidian Bank |
| 6 | NCBA | 20 | Eco Bank | 34 | Equity Bank |
| 7 | Prime Bank | 21 | SPIRE Bank | 35 | Family Bank |
| 8 | Co-operative Bank | 22 | Paramount Bank | 36 | Gulf African Bank |
| 9 | National Bank | 23 | Kingdom Bank | 37 | First Community Bank |
| 10 | M-Oriental | 24 | Guaranty Trust Bank | 38 | DIB Bank |
| 11 | Citi Bank | 25 | Victoria Bank | 39 | UBA Bank |
| 12 | Habib Bank AG Zurich | 26 | Guardian Bank | 40 | KWFT |
| 13 | Middle East Bank | 27 | I&M Bank | 41 | Faulu Bank |
| 14 | Bank of Africa | 28 | Development Bank | 42 | Post Bank |
Bank codes
Section titled “Bank codes”Both checks take a bank from a fixed list, so neither code should be typed by hand. Fetch the directory and render it as a select:
curl "$PH_CONNECT_URL/api/v1/kyc/banks/NG" \ -u "$PH_API_USERNAME:$PH_API_PASSWORD"{ "country": "NG", "label": "Nigeria", "field": "bank_code", "check": "bank_account_ng", "banks": [ { "value": "404", "label": "Abbey Mortgage Bank" }, { "value": "044", "label": "Access Bank Nigeria Plc" }, { "value": "058", "label": "Guaranty Trust Bank Plc" } ]}field names the request field the chosen value belongs in — bank_code for
Nigeria, bank_id for Kenya — so one piece of UI can drive either check.
Drop the country to get every directory at once:
curl "$PH_CONNECT_URL/api/v1/kyc/banks" \ -u "$PH_API_USERNAME:$PH_API_PASSWORD"Nigeria lists 61 banks by CBN code, Kenya 42. The same list is embedded
in the options array of the relevant field in
GET /api/v1/kyc/checks, so a form built from the catalogue already renders a
select without a second call.
Nigeria
Section titled “Nigeria”Nigeria takes the standard three-digit CBN bank_code:
curl -X POST "$PH_CONNECT_URL/api/v1/kyc/verify/bank_account_ng" \ -u "$PH_API_USERNAME:$PH_API_PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "number": "0123456789", "bank_code": "058" }'Name matching is yours to do
Section titled “Name matching is yours to do”The check returns the name on the account. It does not compare that name to whatever you were expecting — comparing “JANE W DOE” against “Jane Doe” is a judgement call about how much divergence you will tolerate, and it belongs in your code, not in the API.
const onAccount = check.subject_name ?? ''const expected = beneficiary.name
const normalise = (s: string) => s.toUpperCase().replace(/[^A-Z ]/g, '').split(/\s+/).filter(Boolean).sort().join(' ')
if (normalise(onAccount) !== normalise(expected)) { // Surface for review rather than failing outright — middle names, // initials and married names all diverge legitimately.}