Recipes — validate an IBAN in your stack
Every recipe below does the same one call: POST /v1/iban/validate, which returns structure + checksum, the issuing bank (BIC), the bank-code check against the national register, EMI/vIBAN classification and SEPA/VoP reachability. Get a free key first (200 requests/month, no card):
curl -X POST https://api.ibanforge.com/v1/keys/generate \
-H "Content-Type: application/json" \
-d '{"email": "you@company.com"}'The honest note that belongs in every integration: a local mod-97 check catches typos and nothing else. Three of the four official example IBANs pass every checksum and still point at bank codes no register allocated — the full story. The register check is the part you cannot do locally.
Python
With the official SDK (pip install ibanforge):
from ibanforge import IBANforge
client = IBANforge(api_key="ifk_your_key")
result = client.validate("DE89370400440532013000")
print(result["valid"], result["bic"]["code"], result["bank_code_check"]["status"])
# True COBADEFFXXX verifiedOr plain requests:
import requests
r = requests.post(
"https://api.ibanforge.com/v1/iban/validate",
json={"iban": "DE89370400440532013000"},
headers={"Authorization": "Bearer ifk_your_key"},
timeout=15,
)
data = r.json()
print(data["valid"], data["bank_code_check"]["status"]) # True verifiedNode.js / TypeScript
Native fetch, no dependency:
const res = await fetch("https://api.ibanforge.com/v1/iban/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer ifk_your_key",
},
body: JSON.stringify({ iban: "DE89370400440532013000" }),
});
const data = await res.json();
console.log(data.valid, data.bic?.code, data.bank_code_check?.status);
// true COBADEFFXXX verifiedThe official SDK (npm install @ibanforge/sdk) wraps the same call with types.
PHP
No extension needed beyond what ships with PHP:
<?php
$payload = json_encode(["iban" => "DE89370400440532013000"]);
$ctx = stream_context_create(["http" => [
"method" => "POST",
"header" => "Content-Type: application/json\r\nAuthorization: Bearer ifk_your_key",
"content" => $payload,
"timeout" => 15,
]]);
$data = json_decode(file_get_contents(
"https://api.ibanforge.com/v1/iban/validate", false, $ctx), true);
echo $data["valid"] ? "valid" : "invalid", " — ",
$data["bank_code_check"]["status"] ?? "n/a", PHP_EOL;
// valid — verifiedJava
The official Java SDK (Java 17+, Jackson only) mirrors the TypeScript client method for method. It is on Maven Central: depend on com.ibanforge:ibanforge-sdk:1.5.0.
IBANforge client = IBANforge.builder().apiKey(System.getenv("IBANFORGE_API_KEY")).build();
IBANValidationResult r = client.validateIban("DE89 3704 0044 0532 0130 00");
System.out.println(r.valid() + " " + r.bic().code() + " " + r.bankCodeCheck().status());Errors are typed under IBANforgeException: PaymentRequiredException (402, the x402 challenge in accepts), RateLimitException, InvalidInputException, ApiException. client.formatIban(...) and the other free routes need no key. README and the full method table.
C# / .NET
The official .NET SDK (net8.0, no dependency beyond the framework) exposes the same methods as async calls. NuGet publication is pending; until then reference the project or dotnet pack it from sdks/dotnet (package id IBANforge.Sdk, version 1.5.0).
using var client = new IBANforgeClient(new IBANforgeOptions { ApiKey = Environment.GetEnvironmentVariable("IBANFORGE_API_KEY") });
var r = await client.ValidateIbanAsync("DE89 3704 0044 0532 0130 00");
Console.WriteLine($"{r.Valid} {r.Bic?.Code} {r.BankCodeCheck?.Status}");Pass your own HttpClient (IHttpClientFactory) to the constructor when you have one; exceptions mirror the Java and TypeScript hierarchy. README.
Google Sheets
Extensions → Apps Script, then a custom function you can use as =VALIDATE_IBAN(A2):
function VALIDATE_IBAN(iban) {
const res = UrlFetchApp.fetch("https://api.ibanforge.com/v1/iban/validate", {
method: "post",
contentType: "application/json",
headers: { Authorization: "Bearer ifk_your_key" },
payload: JSON.stringify({ iban: String(iban) }),
muteHttpExceptions: true,
});
const d = JSON.parse(res.getContentText());
return [[d.valid, d.bic ? d.bic.code : "", d.bank_code_check ? d.bank_code_check.status : ""]];
}Mind your quota: one call per cell evaluation. For a whole column, prefer the batch endpoint from a script (up to 100 IBANs per call).
n8n
Install the community node — it wraps validation, BIC lookup, Swiss clearing and the compliance pre-check with a credentials screen:
Settings → Community nodes → Install → n8n-nodes-ibanforge
Self-hosted: npm install n8n-nodes-ibanforge. (Unverified community nodes run on self-hosted n8n; the verified listing for n8n Cloud is in progress.)
Odoo
An Odoo 18 module (AGPL-3) fills the BIC and the bank name on a partner bank account the moment an IBAN is typed, and creates or reuses the matching bank record. It is not on the Odoo Apps store yet; install it from the repository, at the root of the branch named after the Odoo version:
git clone -b 18.0 https://github.com/cammac-creator/ibanforge-odoo.git addons/ibanforge_bank_autofill
Update the apps list, install IBANforge bank autofill, then open Settings → IBANforge and paste your API key. Without a key the module stays offline and Odoo behaves exactly as stock. The README covers the SEPA and risk badge, and what it adds over native Odoo and the OCA module.
AI agents (MCP)
Claude Desktop, Claude Code, Cursor and any MCP client:
npx -y ibanforge-mcp # stdio, 5 tools, free-tier key optionalOr the hosted transport, no install: https://api.ibanforge.com/mcp — it answers 10 free tool calls per IP per day with no key at all, which is the fastest way for an assistant to evaluate the data before you commit to anything.
What you get back
The response the recipes print (production answer, abridged):
{
"valid": true,
"bic": { "code": "COBADEFFXXX", "bank_name": "Commerzbank", "city": "Köln" },
"bank_code_check": {
"value": "37040044",
"status": "verified",
"register": "Deutsche Bundesbank Bankleitzahlendatei",
"authoritative": true,
"as_of": "2026-08"
}
}authoritative: true means the national register itself answered. Fields the data cannot support are null, never guessed — the full semantics explain what verified does and does not promise.
Related: What "verified" means · IBAN to BIC · Test IBAN generator · Data sources