Build IBAN QA Workflows.
Generate IBANs, validate IBAN lists, create synthetic profiles, export datasets, and build edge-case files. API-key endpoints are metered by your plan; web dataset tools can also use 24h Pass credits for one-day work.
From zero to a verified fixture
Use this four-step path for a first integration: create an API key, generate one deterministic IBAN, inspect the coverage object, then rerun the same request with the seed in CI.
curl -X POST https://ibangen.com/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{"country":"Germany","quantity":1,"seed":"checkout-ci-v1","include_bank_details":true}'
valid == true, the requested country matches, coverage.match_status is matched when you target a bank/BIC, and the returned seed is unchanged. A no-match response is explicit and should not silently fall back to another bank.
Integration artifacts
Use the machine-readable contract and starter assets below to keep integrations reproducible. The OpenAPI and Postman files describe the same stable paths shown in this page; the SDK raises an error with both HTTP status and JSON payload.
202 with status=pending_analysis; poll the review id until completed, then delete it with DELETE /statement-validator/review/{review_id} when the case is closed. The example webhook is a consumer payload contract, not a claim that outbound webhooks are enabled for every account.Authentication
Send your account API key in every REST request. Log in to show your real key in these examples.
X-API-Key: your_api_key_here
X-Request-ID header. You may send a short ASCII X-Request-ID value with a request; otherwise IBANgen generates one. Keep it with your CI or support logs. It is a correlation value, not an idempotency key.API Onboarding Path
Use Pro for self-serve API work. Use Business when a team needs higher monthly volume, saved QA datasets, exact bank/BIC targeting, or annual invoice procurement.
Current Tiers
These are the real product limits currently enforced by the app.
| Plan | Price | API calls | Profiles | SWIFT/BIC reveals | Exports |
|---|---|---|---|---|---|
| Free | Free | 50 | 5 | 0 | 0 |
| 24h Pass | $4.99 one-time | 100 / 24h | 10 / 24h | 40 / 24h | 3 / 24h |
| Starter | $9/month | 2,000 / month | 200 / month | 200 / month | 50 / month |
| Pro | $29/month | 10,000 / month | 1,000 / month | 2,000 / month | 500 / month |
| Business | $99/month | 100,000 / month | 10,000 / month | 10,000 / month | 2,000 / month |
| Enterprise | $190/month | 250,000 / month | 25,000 / month | 25,000 / month | 5,000 / month |
API Playground
Run a small live request from this page. It uses your real API key when you are logged in and consumes the same API credits as a normal request.
Generate IBAN
Generates valid IBANs for supported countries. quantity consumes the same number of API credits, and paid SWIFT/BIC plus bank metadata consumes the same number of reveal credits. Paid results can include official GLEIF legal-entity data, EPC payment-scheme participation, and supported domestic bank-registry fields under bank_intelligence. Free API keys receive locked premium fields. Pro and Business API keys can also request targeted generation against bank records when a country supports bank-code generation.
curl -X POST https://ibangen.com/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{"country":"Germany","quantity":3}'
import requests
response = requests.post(
"https://ibangen.com/api/v1/generate",
headers={
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here",
},
json={"country": "Germany", "quantity": 3},
)
print(response.json())
const response = await fetch("https://ibangen.com/api/v1/generate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here"
},
body: JSON.stringify({ country: "Germany", quantity: 3 })
});
console.log(await response.json());
$headers = @{
"Content-Type" = "application/json"
"X-API-Key" = "your_api_key_here"
}
$body = @{ country = "Germany"; quantity = 3 } | ConvertTo-Json
Invoke-RestMethod -Uri "https://ibangen.com/api/v1/generate" -Method Post -Body $body -Headers $headers
true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: your_api_key_here"
],
CURLOPT_POSTFIELDS => json_encode(["country" => "Germany", "quantity" => 3])
]);
echo curl_exec($ch);
?>
[
{
"iban": "DE89370400440532013000",
"valid": true,
"swift_code": "COBADEFFXXX",
"bank_name": "Commerzbank",
"bank_city": "Frankfurt am Main",
"premium_fields_locked": false,
"bank_intelligence": {
"lei": "851WYGNLUQLFZBSYGB56",
"legal_name": "COMMERZBANK Aktiengesellschaft",
"entity_status": "ACTIVE",
"registration_status": "ISSUED",
"payment_schemes": ["sct", "sct_inst", "sdd_b2b", "sdd_core", "vop"],
"domestic_registry": {
"bank_code": "37040044",
"account_checksum_method": "13"
}
}
}
]
Targeted generation
Use the optional targeting object when you need generated IBANs tied to supported bank records. Free users can browse targeting options in the UI, but API generation with targeting.city, targeting.bank, or targeting.bic requires paid access.
| Field | Plan | Behavior |
|---|---|---|
targeting.city |
Paid access | Generates against a supported bank record from the selected city. It can be combined with bank or BIC targeting. |
targeting.bank |
Pro+ | Generates against a matching bank record, using the selected bank code when that country exposes one. |
targeting.bic |
Business+ | Generates against an exact BIC/branch record when the country generator can honor it. |
Compatibility aliases are accepted for integrations that already send top-level fields: custom_city, custom_bank, custom_bic, bank_name, bic, and swift_code.
curl -X POST https://ibangen.com/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"country": "Luxembourg",
"quantity": 2,
"targeting": {
"city": "LUXEMBOURG",
"bank": "BANQUE DE LUXEMBOURG S.A."
}
}'
{
"country": "Luxembourg",
"quantity": 1,
"targeting": {
"bic": "BLUXLULL"
}
}
[
{
"iban": "LU340088078217992601",
"valid": true,
"swift_code": "BLUXLULL",
"bank_name": "BANQUE DE LUXEMBOURG S.A.",
"bank_city": "LUXEMBOURG",
"premium_fields_locked": false,
"custom_target": {
"scope": "bank",
"bank_name": "BANQUE DE LUXEMBOURG S.A.",
"city": "LUXEMBOURG",
"swift_code": "BLUXLULL",
"match_level": "bank_code",
"generated_bank_code": "008"
}
}
]
{
"error": "advanced_targeting_required",
"required_plan": "Pro",
"pricing_url": "/pricing?checkout=pro&intent=custom_bank",
"message": "Pro is required for this targeted API generation option."
}
Validate IBAN
Validates IBAN structure/checksum. Each IBAN in the list consumes one API credit. City is visible to every API key; SWIFT/BIC, bank name, legal-entity details, payment rails, and domestic-registry fields are premium metadata, so paid API keys spend one reveal credit per IBAN and free API keys receive locked placeholders for those fields.
curl -X POST https://ibangen.com/api/v1/validate \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{"ibans":["GB82WEST12345698765432","DE89370400440532013000"]}'
import requests
response = requests.post(
"https://ibangen.com/api/v1/validate",
headers={"X-API-Key": "your_api_key_here"},
json={"ibans": ["GB82WEST12345698765432", "DE89370400440532013000"]},
)
print(response.json())
const response = await fetch("https://ibangen.com/api/v1/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here"
},
body: JSON.stringify({
ibans: ["GB82WEST12345698765432", "DE89370400440532013000"]
})
});
console.log(await response.json());
$headers = @{
"Content-Type" = "application/json"
"X-API-Key" = "your_api_key_here"
}
$body = @{ ibans = @("GB82WEST12345698765432", "DE89370400440532013000") } | ConvertTo-Json
Invoke-RestMethod -Uri "https://ibangen.com/api/v1/validate" -Method Post -Body $body -Headers $headers
["GB82WEST12345698765432", "DE89370400440532013000"]];
$ch = curl_init("https://ibangen.com/api/v1/validate");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: your_api_key_here"],
CURLOPT_POSTFIELDS => json_encode($payload)
]);
echo curl_exec($ch);
?>
Response examples
Paid account or 24h Pass: validation returns premium bank metadata when available.
[
{
"iban": "FI1623114147337697",
"valid": true,
"swift_code": "NDEAFIHH",
"bank_name": "NORDEA BANK AB (PUBL), FINNISH BRANCH",
"bank_city": "HELSINKI",
"bank_intelligence": {
"legal_name": "Nordea Bank Abp",
"entity_status": "ACTIVE",
"payment_schemes": ["sct", "sct_inst", "sdd_b2b", "sdd_core", "vop"]
},
"premium_fields_locked": false
}
]
Free API key: validation still returns valid/invalid status, but premium bank fields are locked.
[
{
"iban": "FI1623114147337697",
"valid": true,
"swift_code": "Hidden",
"bank_name": "Hidden",
"bank_city": "HELSINKI",
"premium_fields_locked": true,
"locked_fields": ["swift_code", "bank_name", "bank_intelligence"],
"premium_unlock_url": "/pricing?checkout=day_pass&intent=swift"
}
]
Bank Intelligence Registry
Resolve BIC, LEI, domestic clearing codes, regulatory identifiers, and company numbers against normalized official snapshots. Lookup requests consume one API credit per identifier and return at most 25 matches for each identifier. Search requests reserve the requested result limit, so broader searches consume proportionally more API capacity.
curl -X POST https://ibangen.com/api/v1/bank-intelligence/lookup \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"identifiers": [
{"type": "bic", "value": "COBADEFFXXX"},
{"type": "lei", "value": "851WYGNLUQLFZBSYGB56"}
]
}'
curl -X POST https://ibangen.com/api/v1/bank-intelligence/search \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"query": "Commerzbank",
"country_code": "DE",
"record_type": "bank",
"limit": 20
}'
Business responses include source attribution and payment-rail metadata when available. Record detail also exposes GLEIF parent relationships, while /sources lists snapshot dates, attribution, license markers, and row counts. Business can export up to 250 identifier queries as CSV with /export; Enterprise raises that to 1,000. An export consumes the identifier row count from API credits and one export credit. Enterprise can query monitored source changes with /changes?source_id=ecb_mfi&limit=100; the versioned registry-change/1.0 event schema documents the snapshot ID, before/after fields and detection timestamp.
Registry Watchlists
Save a supported source/key pair, inspect field-level changes and generate a deterministic synthetic before/after fixture. Watchlists are user-scoped and plan-limited. The current worker queues pending verification alerts only; outbound email or webhook delivery is not implied by creating a watch.
curl -X POST https://ibangen.com/api/v1/registry/watchlists \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{"source_id":"ecb_mfi","record_key":"DE001"}'
curl -H "X-API-Key: your_api_key_here" \
https://ibangen.com/api/v1/registry/watchlists/{watch_id}/changes
Fixture Manifest
Compile a portable ibangen-fixture-manifest/1.0 around synthetic targets. The manifest stores the seed, registry snapshot, source/licence references, schema versions, expected outcomes and a canonical SHA-256 artifact hash. When configured for the deployment, hosted artifacts also carry an Ed25519 signature that CI can verify with a pinned public key. Pro or higher API access is required to compile hosted artifacts.
curl -X POST https://ibangen.com/api/v1/fixture-manifest/compile \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"fixture_id":"checkout-de-v1",
"seed":"checkout-ci-v1",
"fixtures":[{"country":"DE","iban":"DE00SYNTHETIC","expected_valid":true}],
"schemas":[{"name":"pain.001","version":"pain.001.001.09"}],
"expected_outcomes":["valid_format"]
}'
Read the manifest guide
Payment Scenario Compiler
Business API access can compile a stateful synthetic payment scenario that links a counterparty fixture, VOP outcome, pain.001 initiation, pacs.008 transfer, pacs.002 status, camt.053 statement effect and CI assertions. The current artifact is structured JSON; it does not claim live clearing or account verification.
curl -X POST https://ibangen.com/api/v1/payment-scenarios/compile \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{"scenario":"supplier_payment_close_name_match","country":"DE","bank_target":"Berliner Sparkasse","amount":"1250.00","currency":"EUR","vop_outcome":"CLOSE_MATCH","seed":"ci-v1"}'
Browse payment fixture families
Bank Statement Validator
Upload one bank statement file and receive a structured risk review. The analyzer extracts visible fields, checks detected IBANs and supported domestic routing identifiers with deterministic validators, reviews dates/amounts/statement terminology, and returns a parseable JSON report for KYC workflows. Add expected_bank or expected_bank_slug when a statement should match a specific bank page.
curl -X POST https://ibangen.com/api/v1/statement-validator/analyze \
-H "X-API-Key: your_api_key_here" \
-F "statement_file=@/path/to/statement.pdf" \
-F "expected_bank=Banco Guayaquil"
import requests
with open("statement.pdf", "rb") as f:
response = requests.post(
"https://ibangen.com/api/v1/statement-validator/analyze",
headers={"X-API-Key": "your_api_key_here"},
files={"statement_file": ("statement.pdf", f, "application/pdf")},
data={"expected_bank": "Banco Guayaquil"},
timeout=30,
)
print(response.status_code)
print(response.json())
const form = new FormData();
form.append("statement_file", fileInput.files[0]);
form.append("expected_bank", "Banco Guayaquil");
const response = await fetch("https://ibangen.com/api/v1/statement-validator/analyze", {
method: "POST",
headers: { "X-API-Key": "your_api_key_here" },
body: form
});
console.log(await response.json());
If the response status is pending_analysis, poll the review endpoint until it returns completed. The alias /api/v1/statements/analyze is also available for shorter integrations. US statements return ABA routing checks in domestic_account_checks; account-number entries are format-only because no universal public account-number checksum exists.
retention object with the configured expiry, processor, region, and encryption declaration. The source upload and review artifacts are pruned after that window; call the DELETE endpoint for earlier removal.{
"success": true,
"status": "pending_analysis",
"review_id": "d4f7c94e7d0e4e4b9b3d9c3f1e3a9c1b",
"review_step": "queued",
"review_message": "Document analysis is queued.",
"quota": {"limit": 10, "left": 9, "unlimited": false}
}
curl https://ibangen.com/api/v1/statement-validator/review/d4f7c94e7d0e4e4b9b3d9c3f1e3a9c1b \
-H "X-API-Key: your_api_key_here"
{
"success": true,
"status": "completed",
"score": 82,
"risk_level": "medium",
"is_bank_statement": true,
"summary": "The document resembles a bank statement with verifiable IBAN evidence and some review items.",
"extracted_fields": {
"account_holder": "Example Customer",
"iban": "DE89370400440532013000",
"statement_period": "May 2026"
},
"iban_checks": [{
"iban": "DE89370400440532013000",
"valid": true,
"country_code": "DE",
"bank_name": "Hidden",
"swift_code": "Hidden"
}],
"domestic_account_checks": [],
"positive_signals": [],
"risk_signals": [],
"inconsistencies": [],
"recommendations": []
}
AI Profile
Generates a synthetic QA profile around an IBAN and bank context. Personal identity data is synthetic; bank names/websites use real public references when the model is confident.
curl -X POST https://ibangen.com/api/v1/profile \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"country":"Austria",
"iban":"AT335400061166597241",
"swift_code":"OBLAAT2LXXX",
"bank_name":"Oberbank AG",
"bank_city":"Linz",
"age_min":25,
"age_max":55
}'
import requests
payload = {
"country": "Austria",
"iban": "AT335400061166597241",
"swift_code": "OBLAAT2LXXX",
"bank_name": "Oberbank AG",
"bank_city": "Linz",
"age_min": 25,
"age_max": 55,
}
response = requests.post(
"https://ibangen.com/api/v1/profile",
headers={"X-API-Key": "your_api_key_here"},
json=payload,
)
print(response.json())
const payload = {
country: "Austria",
iban: "AT335400061166597241",
swift_code: "OBLAAT2LXXX",
bank_name: "Oberbank AG",
bank_city: "Linz",
age_min: 25,
age_max: 55
};
const response = await fetch("https://ibangen.com/api/v1/profile", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here"
},
body: JSON.stringify(payload)
});
console.log(await response.json());
$headers = @{
"Content-Type" = "application/json"
"X-API-Key" = "your_api_key_here"
}
$body = @{
country = "Austria"
iban = "AT335400061166597241"
swift_code = "OBLAAT2LXXX"
bank_name = "Oberbank AG"
bank_city = "Linz"
age_min = 25
age_max = 55
} | ConvertTo-Json
Invoke-RestMethod -Uri "https://ibangen.com/api/v1/profile" -Method Post -Body $body -Headers $headers
"Austria",
"iban" => "AT335400061166597241",
"swift_code" => "OBLAAT2LXXX",
"bank_name" => "Oberbank AG",
"bank_city" => "Linz",
"age_min" => 25,
"age_max" => 55
];
$ch = curl_init("https://ibangen.com/api/v1/profile");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: your_api_key_here"],
CURLOPT_POSTFIELDS => json_encode($payload)
]);
echo curl_exec($ch);
?>
{
"success": true,
"profile": {
"iban": "AT335400061166597241",
"provider": "openrouter",
"model": "inclusionai/ling-2.6-1t:free",
"model_tier": "free",
"quality_score": 94,
"quality_tier": "excellent",
"quality_label": "Excellent synthetic QA profile",
"profile": {
"full_name": "Synthetic persona name",
"country": "Austria",
"city": "Linz",
"bank_account": {
"bank_name": "Oberbank AG",
"bank_website": "https://www.oberbank.at",
"swift_bic": "OBLAAT2LXXX"
}
}
},
"generations_left": 199
}
Quality Score
85-100
Excellent or good. Complete profile, realistic address structure, bank context, no weak placeholders.
70-84
Usable but should be reviewed. Some non-critical fields may need regeneration.
Below 70
Needs review. Paid UI should retry or avoid presenting low-quality profiles as final data.
The score is based on completeness, country consistency, bank metadata quality, weak-marker detection,
and whether generated fields avoid placeholders such as N/A, 00000, and test domains.
Dataset Tools
Use these API-key endpoints when you want the same QA dataset features from automation. The `/tools` page is the browser UI; these routes are for scripts and CI jobs.
Bulk Dataset Builder
Paid only. 24h Pass: 40 rows. Starter: 500 rows. Pro/Enterprise: 10,000 rows. Supports JSON/CSV and optional AI profiles.
Test Case Generator
Generates valid and invalid IBAN edge cases: checksum, wrong length, malformed, and country mismatch scenarios. Free users get preview-sized batches.
curl -X POST https://ibangen.com/api/v1/bulk-dataset \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{"country":"Germany","quantity":100,"output":"json","include_profiles":false}'
curl -X POST https://ibangen.com/api/v1/test-cases \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{"country":"Germany","quantity":25,"output":"json"}'
import requests
headers = {
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here",
}
dataset = requests.post(
"https://ibangen.com/api/v1/bulk-dataset",
headers=headers,
json={"country": "Germany", "quantity": 100, "output": "json"},
)
cases = requests.post(
"https://ibangen.com/api/v1/test-cases",
headers=headers,
json={"country": "Germany", "quantity": 25, "output": "json"},
)
print(dataset.json())
print(cases.json())
const headers = {
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here"
};
const dataset = await fetch("https://ibangen.com/api/v1/bulk-dataset", {
method: "POST",
headers,
body: JSON.stringify({ country: "Germany", quantity: 100, output: "json" })
});
const cases = await fetch("https://ibangen.com/api/v1/test-cases", {
method: "POST",
headers,
body: JSON.stringify({ country: "Germany", quantity: 25, output: "json" })
});
console.log(await dataset.json());
console.log(await cases.json());
Errors
| Status | Meaning | Typical response |
|---|---|---|
| 401 | Missing or invalid API key. | {"error":"Invalid API key"} |
| 400 | Invalid country, quantity, or request body. | {"error":"Invalid country"} |
| 429 | API call credits exhausted. | {"error":"API call limit reached"} |
| 403 | Profile generation credits exhausted. | {"error":"generation_limit_reached"} |
| 402 | Paid or 24h Pass access required for a dataset tool. | {"error":"bulk_dataset_requires_paid_access"} |