{"openapi":"3.1.0","info":{"title":"IBANtoBIC API","version":"1.0.0","description":"IBAN validation and IBAN-to-BIC lookups backed by the official national bank registries. Authenticate with an API key as a bearer token. Every lookup outcome \u2014 found, valid_but_unknown or invalid \u2014 is a 200 with an explicit `status`; the error envelope is reserved for transport problems (authentication, validation, rate limits, quotas). IBANs are processed in memory and never stored; prefer the POST endpoints to keep IBANs out of URLs and access logs."},"servers":[{"url":"https:\/\/ibantobic.com\/api\/v1"}],"security":[{"apiKey":[]}],"paths":{"\/iban\/{iban}":{"get":{"operationId":"lookupIbanByPath","summary":"Look up the BIC for an IBAN (GET)","description":"Convenience variant with the IBAN in the URL. Note that URLs commonly end up in access logs \u2014 use POST \/lookup when that matters.","parameters":[{"name":"iban","in":"path","required":true,"schema":{"type":"string","maxLength":100},"example":"BE68539007547034"}],"responses":{"200":{"$ref":"#\/components\/responses\/LookupResponse"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/RateLimited"}}}},"\/lookup":{"post":{"operationId":"lookupIban","summary":"Look up the BIC for an IBAN","description":"The recommended lookup endpoint: the IBAN travels in the request body, never in a URL.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LookupRequest"}}}},"responses":{"200":{"$ref":"#\/components\/responses\/LookupResponse"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/RateLimited"}}}},"\/lookup\/batch":{"post":{"operationId":"lookupIbanBatch","summary":"Look up many IBANs in one request","description":"Up to 500 IBANs, answered row by row in input order. Each row consumes one quota unit.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BatchLookupRequest"}}}},"responses":{"200":{"description":"One row per input, plus a summary.","headers":{"X-Quota-Remaining":{"$ref":"#\/components\/headers\/X-Quota-Remaining"}},"content":{"application\/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#\/components\/schemas\/BatchLookupData"}}}}}},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/RateLimited"}}}},"\/validate\/{iban}":{"get":{"operationId":"validateIbanByPath","summary":"Validate an IBAN (GET)","description":"Validation-only variant with the IBAN in the URL; see POST \/validate for the log-free form.","parameters":[{"name":"iban","in":"path","required":true,"schema":{"type":"string","maxLength":100},"example":"NL91ABNA0417164300"}],"responses":{"200":{"$ref":"#\/components\/responses\/ValidateResponse"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"429":{"$ref":"#\/components\/responses\/RateLimited"}}}},"\/validate":{"post":{"operationId":"validateIban","summary":"Validate an IBAN","description":"Runs the staged IBAN checks (country, characters, check digits, length, checksum) without touching the bank directory. Both outcomes are a 200.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LookupRequest"}}}},"responses":{"200":{"$ref":"#\/components\/responses\/ValidateResponse"},"401":{"$ref":"#\/components\/responses\/Unauthenticated"},"422":{"$ref":"#\/components\/responses\/ValidationFailed"},"429":{"$ref":"#\/components\/responses\/RateLimited"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from the dashboard, e.g. `Authorization: Bearer ibtb_live_\u2026`. The `X-Api-Key` header is accepted as an alternative."}},"headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute for the account's plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Metered units allowed per quota period for the account's plan.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Metered units left in the current quota period.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"When the quota period resets (ISO 8601).","schema":{"type":"string","format":"date-time"}}},"responses":{"LookupResponse":{"description":"The lookup result. `data.status` tells you what happened; an invalid IBAN is a successful lookup, not an error.","headers":{"X-RateLimit-Limit":{"$ref":"#\/components\/headers\/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#\/components\/headers\/X-RateLimit-Remaining"},"X-Quota-Limit":{"$ref":"#\/components\/headers\/X-Quota-Limit"},"X-Quota-Remaining":{"$ref":"#\/components\/headers\/X-Quota-Remaining"},"X-Quota-Reset":{"$ref":"#\/components\/headers\/X-Quota-Reset"}},"content":{"application\/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#\/components\/schemas\/LookupResult"},"meta":{"$ref":"#\/components\/schemas\/Meta"}}}}}},"ValidateResponse":{"description":"The validation result. `data.valid` is the verdict; `data.failure.reason` carries the precise, stable failure code when invalid.","content":{"application\/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#\/components\/schemas\/ValidationResult"}}}}}},"Unauthenticated":{"description":"No key, an unknown key, or a revoked key.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"}}}},"ValidationFailed":{"description":"The request body is malformed. `error.errors` maps field names to messages.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"}}}},"RateLimited":{"description":"Too many requests (`rate_limited`), the quota is used up (`quota_exceeded`), or a batch needs more units than remain (`quota_insufficient`). Honour `Retry-After` and `X-Quota-Reset`.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"}}}}},"schemas":{"LookupRequest":{"type":"object","required":["iban"],"properties":{"iban":{"type":"string","maxLength":100,"description":"The IBAN as your user typed it \u2014 spaces and case are tolerated.","example":"BE68 5390 0754 7034"}}},"BatchLookupRequest":{"type":"object","required":["ibans"],"properties":{"ibans":{"type":"array","minItems":1,"maxItems":500,"items":{"type":["string","null"],"maxLength":100}}}},"LookupResult":{"type":"object","description":"The complete answer to \"what is the BIC for this IBAN?\". Branch on `status` first.","required":["status","input","normalized_input","iban","country","bank_identifier","branch_identifier","failure","institution","successor","primary_bic","branch_bics","successor_bic","last_known_bic","recommended_bic","uses_successor_bic"],"properties":{"status":{"type":"string","enum":["found","valid_but_unknown","invalid"],"description":"found: the bank was identified and `recommended_bic` is the BIC to use. valid_but_unknown: the IBAN is well-formed but its bank is not in the directory (or the country is not covered). invalid: the IBAN itself is malformed \u2014 see `failure`."},"input":{"type":"string","description":"Echo of the submitted value."},"normalized_input":{"type":"string","description":"The input upper-cased with spaces removed."},"iban":{"oneOf":[{"$ref":"#\/components\/schemas\/Iban"},{"type":"null"}]},"country":{"oneOf":[{"$ref":"#\/components\/schemas\/Country"},{"type":"null"}]},"bank_identifier":{"type":["string","null"],"description":"The national bank identifier extracted from the IBAN (e.g. the Belgian 3-digit bank code)."},"branch_identifier":{"type":["string","null"]},"failure":{"oneOf":[{"$ref":"#\/components\/schemas\/Failure"},{"type":"null"}]},"institution":{"oneOf":[{"$ref":"#\/components\/schemas\/Institution"},{"type":"null"}]},"successor":{"oneOf":[{"$ref":"#\/components\/schemas\/Institution"},{"type":"null"}],"description":"When the bank was absorbed by another institution, the one to use now."},"primary_bic":{"oneOf":[{"$ref":"#\/components\/schemas\/Bic"},{"type":"null"}]},"branch_bics":{"type":"array","items":{"$ref":"#\/components\/schemas\/Bic"}},"successor_bic":{"oneOf":[{"$ref":"#\/components\/schemas\/Bic"},{"type":"null"}]},"last_known_bic":{"oneOf":[{"$ref":"#\/components\/schemas\/Bic"},{"type":"null"}]},"recommended_bic":{"oneOf":[{"$ref":"#\/components\/schemas\/Bic"},{"type":"null"}],"description":"The BIC a person should actually use: the identifier's own current BIC, or the successor's when the original expired."},"uses_successor_bic":{"type":"boolean"}}},"ValidationResult":{"type":"object","required":["valid","normalized_input","iban","country","failure"],"properties":{"valid":{"type":"boolean"},"normalized_input":{"type":"string"},"iban":{"oneOf":[{"$ref":"#\/components\/schemas\/Iban"},{"type":"null"}]},"country":{"oneOf":[{"$ref":"#\/components\/schemas\/ValidationCountry"},{"type":"null"}]},"failure":{"oneOf":[{"$ref":"#\/components\/schemas\/Failure"},{"type":"null"}]}}},"BatchLookupData":{"type":"object","required":["rows","summary"],"properties":{"rows":{"type":"array","items":{"$ref":"#\/components\/schemas\/BatchRow"}},"summary":{"type":"object","required":["total","found","valid_but_unknown","invalid","duration_ms"],"properties":{"total":{"type":"integer"},"found":{"type":"integer"},"valid_but_unknown":{"type":"integer"},"invalid":{"type":"integer"},"duration_ms":{"type":"integer"}}}}},"BatchRow":{"type":"object","description":"The compact, table-friendly projection of one batch result.","required":["index","input","iban","iban_formatted","status","country_code","country_name","bank_identifier","bank_name","bic","bic8","bic11","uses_successor_bic","successor_name","branch_bics","message","share_url"],"properties":{"index":{"type":"integer","description":"Position in the submitted list."},"input":{"type":"string"},"iban":{"type":["string","null"]},"iban_formatted":{"type":["string","null"]},"status":{"type":"string","enum":["found","valid_but_unknown","invalid"]},"country_code":{"type":["string","null"]},"country_name":{"type":["string","null"]},"bank_identifier":{"type":["string","null"]},"bank_name":{"type":["string","null"]},"bic":{"type":["string","null"],"description":"The recommended BIC."},"bic8":{"type":["string","null"]},"bic11":{"type":["string","null"]},"uses_successor_bic":{"type":"boolean"},"successor_name":{"type":["string","null"]},"branch_bics":{"type":"integer","description":"How many branch BICs the identifier carries (count, not the list \u2014 use the single lookup for the full detail)."},"message":{"type":["string","null"],"description":"The human-readable failure message for invalid rows."},"share_url":{"type":"null","description":"Always null on the API: share URLs embed the IBAN in a URL."}}},"Iban":{"type":"object","required":["value","formatted","country_code","check_digits","bban"],"properties":{"value":{"type":"string","example":"BE68539007547034"},"formatted":{"type":"string","description":"Grouped in fours for display.","example":"BE68 5390 0754 7034"},"country_code":{"type":"string"},"check_digits":{"type":"string"},"bban":{"type":"string"}}},"Country":{"type":"object","required":["code","name","sepa","supports_bank_identifier","covered"],"properties":{"code":{"type":"string"},"name":{"type":"string"},"sepa":{"type":"boolean"},"supports_bank_identifier":{"type":"boolean","description":"Whether this country's IBANs carry a bank identifier at all."},"covered":{"type":"boolean","description":"Whether the bank directory holds data for this country."}}},"ValidationCountry":{"type":"object","description":"Like Country, without `covered` \u2014 validation never touches the directory.","required":["code","name","sepa","supports_bank_identifier"],"properties":{"code":{"type":"string"},"name":{"type":"string"},"sepa":{"type":"boolean"},"supports_bank_identifier":{"type":"boolean"}}},"Institution":{"type":"object","required":["name","short_name","country_code","localized_names"],"properties":{"name":{"type":"string"},"short_name":{"type":["string","null"]},"country_code":{"type":"string"},"localized_names":{"type":"object","additionalProperties":{"type":"string"}}}},"Bic":{"type":"object","required":["bic","bic8","bic11","bank_code","country_code","location_code","branch_code","is_head_office","name","city","postal_code","valid_from","valid_until"],"properties":{"bic":{"type":"string","description":"Canonical form: 8 characters for a head office, 11 for a branch.","example":"GKCCBEBB"},"bic8":{"type":"string"},"bic11":{"type":"string","description":"Always 11 characters \u2014 head offices padded with XXX.","example":"GKCCBEBBXXX"},"bank_code":{"type":"string"},"country_code":{"type":"string"},"location_code":{"type":"string"},"branch_code":{"type":["string","null"]},"is_head_office":{"type":"boolean"},"name":{"type":["string","null"]},"city":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"valid_from":{"type":["string","null"],"format":"date"},"valid_until":{"type":["string","null"],"format":"date"}}},"Failure":{"type":"object","required":["reason","message"],"properties":{"reason":{"type":"string","enum":["empty","missing_country_code","unknown_country","invalid_characters","invalid_check_digits","invalid_length","checksum_mismatch"],"description":"Stable codes. empty: no input. missing_country_code: an IBAN starts with a two-letter country code. unknown_country: the first two letters are not an IBAN-issuing country. invalid_characters: only letters and digits are allowed. invalid_check_digits: the two characters after the country code must be digits. invalid_length: wrong length for the country. checksum_mismatch: the check digits do not match the rest \u2014 likely a typo."},"message":{"type":"string","description":"Human-readable English explanation, safe to show to end users."}}},"Meta":{"type":"object","required":["directory"],"properties":{"directory":{"oneOf":[{"$ref":"#\/components\/schemas\/DirectoryFreshness"},{"type":"null"}],"description":"Freshness of the directory data behind this answer; null when no country applies or the country is not covered."}}},"DirectoryFreshness":{"type":"object","required":["country_code","imported_at","as_of"],"properties":{"country_code":{"type":"string"},"imported_at":{"type":["string","null"],"format":"date-time","description":"When the country's registry was last imported."},"as_of":{"type":["string","null"],"format":"date","description":"The version the registry itself publishes, when it publishes one."}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["status","code","message"],"properties":{"status":{"type":"integer","example":401},"code":{"type":"string","enum":["unauthenticated","forbidden","not_found","method_not_allowed","validation_failed","rate_limited","quota_exceeded","quota_insufficient","unavailable","server_error","http_error"]},"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Only on validation_failed: field names to messages."}}}}}}}}