# Validate IBAN

Checks that an IBAN is well formed and returns its parts. For IBANs from Germany, Austria, Switzerland, Liechtenstein, Belgium and the Czech Republic, the response also contains the bank's name, BIC and town, as far as the national bank directory lists them.

A valid IBAN is not a verified account

A valid IBAN is well formed and has correct check digits. It does not prove that the account exists, is open, or who holds it. Every validation response repeats this in its notice field.

The validation is computed on our servers from the published IBAN formats and bank directories. No bank or other third party is contacted.

# Validate a single IBAN

Request Method: GET
Request URL: https://api.vatcheckapi.com/v2/iban?iban=[[ iban ]]

# Request Parameters

Parameter Type Mandatory Description
apikey string ️ Your API Key
iban string ️ The IBAN in electronic (DE89370400440532013000) or print format (DE89 3704 0044 0532 0130 00). Spaces and lower case are accepted. At most 64 characters of UTF-8 text

# Sample Request

curl -G https://api.vatcheckapi.com/v2/iban \
    -d iban=DE89370400440532013000 \
    -H "apikey: YOUR-APIKEY"

To send the print format, let curl encode the spaces:

curl -G https://api.vatcheckapi.com/v2/iban \
    --data-urlencode "iban=DE89 3704 0044 0532 0130 00" \
    -H "apikey: YOUR-APIKEY"

# Sample Response

{
    "iban": "DE89370400440532013000",
    "iban_print_format": "DE89 3704 0044 0532 0130 00",
    "valid": true,
    "reason": null,
    "checks": {
        "length": true,
        "structure": true,
        "checksum": true,
        "national_checksum": true
    },
    "country_code": "DE",
    "sepa": true,
    "bban": "370400440532013000",
    "bank_code": "37040044",
    "branch_code": null,
    "account_number": "0532013000",
    "bank": {
        "name": "Commerzbank",
        "bic": "COBADEFFXXX",
        "city": "Köln",
        "source": "Quelle: Deutsche Bundesbank"
    },
    "notice": "A valid IBAN is well formed and has correct check digits. It does not prove that the account exists, is open, or who holds it."
}

An IBAN that fails a check is not an error: the response is a 200 with valid: false, and reason names the first check that failed. Once the length and structure checks pass, the parts and the bank are returned even when the check digits are wrong, which helps to spot a typo:

{
    "iban": "DE88370400440532013000",
    "iban_print_format": "DE88 3704 0044 0532 0130 00",
    "valid": false,
    "reason": "invalid_checksum",
    "checks": {
        "length": true,
        "structure": true,
        "checksum": false,
        "national_checksum": null
    },
    "country_code": "DE",
    "sepa": true,
    "bban": "370400440532013000",
    "bank_code": "37040044",
    "branch_code": null,
    "account_number": "0532013000",
    "bank": {
        "name": "Commerzbank",
        "bic": "COBADEFFXXX",
        "city": "Köln",
        "source": "Quelle: Deutsche Bundesbank"
    },
    "notice": "A valid IBAN is well formed and has correct check digits. It does not prove that the account exists, is open, or who holds it."
}

# Validate up to 100 IBANs

Request Method: POST
Request URL: https://api.vatcheckapi.com/v2/iban/batch

Runs the same checks and bank lookup as the single request for up to 100 IBANs.

# Request Body

Field Type Mandatory Description
ibans array of strings ️ Up to 100 IBANs in electronic or print format, each at most 64 characters of UTF-8 text. One comma-separated string is accepted too
  • The IBANs are normalised (spaces removed, upper case) and duplicates are removed before the limit of 100 is checked. The list may hold up to 1,000 entries before that.
  • The result is an object keyed by the normalised IBAN, in the order in which each IBAN first appears. The notice is sent once for the whole batch.
  • The IBANs are read from the request body only: a JSON body as below, or a form-encoded one. An ibans parameter in the query string is refused with a 422.
  • The batch is checked against your remaining quota before it runs. If its cost would use up the remaining quota, it is refused with a 429 and nothing is processed or billed. quota.required holds the batch's cost, and error.code names the quota that runs short: quota_exceeded (monthly quota), grace_quota_exceeded (grace quota after a failed payment) or overage_quota_exceeded (overage budget).
  • If your plan does not include batch requests, the endpoint answers 403 with the code plan_upgrade_required.

# Sample Request

curl https://api.vatcheckapi.com/v2/iban/batch \
    -H "apikey: YOUR-APIKEY" \
    -H "Content-Type: application/json" \
    -d '{"ibans": ["DE89 3704 0044 0532 0130 00", "DE88370400440532013000", "de89370400440532013000"]}'

# Sample Response

The first and third IBAN are the same once normalised, so the batch has two results and costs 2 requests (X-Cost: 2).

{
    "data": {
        "DE89370400440532013000": {
            "iban": "DE89370400440532013000",
            "iban_print_format": "DE89 3704 0044 0532 0130 00",
            "valid": true,
            "reason": null,
            "checks": {
                "length": true,
                "structure": true,
                "checksum": true,
                "national_checksum": true
            },
            "country_code": "DE",
            "sepa": true,
            "bban": "370400440532013000",
            "bank_code": "37040044",
            "branch_code": null,
            "account_number": "0532013000",
            "bank": {
                "name": "Commerzbank",
                "bic": "COBADEFFXXX",
                "city": "Köln",
                "source": "Quelle: Deutsche Bundesbank"
            }
        },
        "DE88370400440532013000": {
            "iban": "DE88370400440532013000",
            "iban_print_format": "DE88 3704 0044 0532 0130 00",
            "valid": false,
            "reason": "invalid_checksum",
            "checks": {
                "length": true,
                "structure": true,
                "checksum": false,
                "national_checksum": null
            },
            "country_code": "DE",
            "sepa": true,
            "bban": "370400440532013000",
            "bank_code": "37040044",
            "branch_code": null,
            "account_number": "0532013000",
            "bank": {
                "name": "Commerzbank",
                "bic": "COBADEFFXXX",
                "city": "Köln",
                "source": "Quelle: Deutsche Bundesbank"
            }
        }
    },
    "notice": "A valid IBAN is well formed and has correct check digits. It does not prove that the account exists, is open, or who holds it."
}

# Response Fields

Field Type Description
iban string The IBAN in electronic format: all whitespace removed, upper case
iban_print_format string / null Groups of four characters. null when reason is invalid_characters
valid boolean true when every check passed. A national_checksum of null does not make an IBAN invalid
reason string / null The first check that failed, see Check order. null when the IBAN is valid
checks.length boolean The IBAN has the length of its country
checks.structure boolean The check digits are digits and the BBAN matches the country's structure
checks.checksum boolean The ISO 7064 MOD 97-10 check digits are correct
checks.national_checksum boolean / null The country's own check digits inside the BBAN, see National check digits
country_code string / null The first two characters when they are letters, otherwise null. Also null when the IBAN has characters other than A-Z and 0-9
sepa boolean / null The country takes part in SEPA, according to the IBAN Registry. null when the country is not in the registry or the IBAN has invalid characters
bban string / null The Basic Bank Account Number: the IBAN without country code and check digits
bank_code string / null The bank identifier as the IBAN Registry defines it for the country (in Germany the Bankleitzahl)
branch_code string / null The branch identifier, for countries where the IBAN Registry defines one (for example ES, IT and GB)
account_number string / null The BBAN without the bank and branch identifiers. In some countries it also holds national check digits: in ES9121000418450200051332, for example, it is 450200051332, the control digits 45 followed by the account number. In IT and SM it starts with the CIN check character, which comes before the bank code in the BBAN: IT60X0542811101000000123456 gives X000000123456
bank object / null The bank from the national directory, see Bank data. null for other countries, for bank codes that are not in the directory, and when the length or structure check failed
bank.name string The bank's name as the directory lists it
bank.bic string / null The BIC as the directory lists it, null when it lists none
bank.city string / null The town as the directory lists it. null for BE and CZ, whose directories list no town
bank.source string The source, worded as the directory's terms of use require
notice string A valid IBAN does not prove that the account exists or who holds it. Top level of the response, once per batch

bban, bank_code, branch_code and account_number are set once the length and structure checks pass, also when the check digits are wrong. Before that they are null.

# Check Order

The checks run in this order and stop at the first failure. reason names that failure; the checks after it are not run and report false, and national_checksum reports null.

# Check reason when it fails
1 Characters: once spaces are removed, only A-Z and 0-9 invalid_characters
2 Country: the first two characters are a country of the IBAN Registry (89 countries) unsupported_country
3 Length: the length of the country's IBAN. A partly typed IBAN such as DE89 fails here invalid_length
4 Structure: the check digits are digits and the BBAN matches the country's structure (which positions are digits, letters or either) invalid_structure
5 Check digits: ISO 7064 MOD 97-10 over the whole IBAN. The check digits 00, 01 and 99 are never valid invalid_checksum
6 National check digits, where a public algorithm is applied, see below invalid_national_checksum

# National Check Digits

Many countries put check digits of their own into the domestic account number. Where a public algorithm exists, the API checks them too, so it catches typos that the MOD 97-10 check digits miss.

Country Algorithm
DE The check digit method that the Deutsche Bundesbank's bank code directory assigns to the bank code (Prüfzifferberechnungsmethode)
BE The last two digits: the first ten digits modulo 97
CZ, SK Modulo 11 over the account prefix and over the account number
EE Weights 7, 3, 1 over the domestic account number
ES The two control digits of the bank account code (CCC)
FI Luhn over the account number in machine format
FR, MC The RIB key
HR ISO 7064 MOD 11,10 over the bank code and over the account number
HU Weights 9, 7, 3, 1 over the bank block and the account block
IT, SM The CIN check character
NO Modulo 11 with weights 5, 4, 3, 2, 7, 6, 5, 4, 3, 2
PL The check digit of the bank's settlement number
PT The NIB check digits
BA, ME, MK, RS, SI, TL, XK ISO 7064 MOD 97-10 over the BBAN

national_checksum is null when:

  • no algorithm is applied for the country, for example AT, CH, LI, GB or NL (Dutch account numbers have not followed the old Dutch check since the IBAN migration, so it is not applied);
  • the account has no check digit to verify (for example German bank codes whose method does not use one);
  • a German IBAN's bank code is not in the Bundesbank directory;
  • an earlier check failed.

# Bank Data

The bank object comes from the bank code directories that the national central banks and, for Switzerland and Liechtenstein, SIX publish. We check every directory daily for a new edition and import it when it has changed. Names, BICs and towns are passed on as the directory publishes them: we only remove padding and the spaces in printed BICs, and treat placeholders such as N/A as no BIC. For Belgium the English name is used where the directory has one.

IBAN country Directory Published bank.source
DE Bankleitzahlendatei, Deutsche Bundesbank Quarterly Quelle: Deutsche Bundesbank
AT SEPA-Zahlungsverkehrsverzeichnis, Oesterreichische Nationalbank (OeNB) Daily Source: Oesterreichische Nationalbank (OeNB), SEPA-Zahlungsverkehrsverzeichnis (excerpt), © OeNB, licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/), provided without warranty
CH, LI Bank Master, SIX Interbank Clearing Daily Source: SIX Interbank Clearing Ltd, Bank Master. BIC are the property of SWIFT SCRL, 1310 La Hulpe, Belgium.
BE Bank identification codes, National Bank of Belgium (NBB) When a code changes Source: National Bank of Belgium (NBB). This information is also available free of charge at https://www.nbb.be/en/payments-and-securities/bank-identification-codes
CZ Číselník kódů platebního styku, Česká národní banka (ČNB) When the list changes Zdroj: ČNB

bank.source carries the wording each directory's terms of use ask for. These terms require the source to be named when the data is passed on, so keep bank.source with the bank data if you show or forward it.

The Belgian bank identification codes are also available free of charge on the National Bank of Belgium's website (opens new window).

For IBANs from other countries bank is null. Swiss and Liechtenstein IBANs share the SIX directory, because banks in both countries are identified by the same institution identification numbers (IIDs).

# IBAN Formats

IBAN formats derived from the SWIFT IBAN Registry (ISO 13616), Release 103, September 2026. The API supports the 89 countries of this release:

AD, AE, AL, AT, AZ, BA, BE, BG, BH, BI, BR, BY, CH, CR, CY, CZ, DE, DJ, DK, DO, EE, EG, ES, FI, FK, FO, FR, GB, GE, GI, GL, GR, GT, HN, HR, HU, IE, IL, IQ, IS, IT, JO, KW, KZ, LB, LC, LI, LT, LU, LV, LY, MC, MD, ME, MK, MN, MR, MT, MU, NI, NL, NO, OM, PK, PL, PS, PT, QA, RO, RS, RU, SA, SC, SD, SE, SI, SK, SM, SO, ST, SV, TL, TN, TR, UA, VA, VG, XK, YE

SWIFT publishes new releases of the registry several times a year. Each release is reviewed before the API's formats are updated from it, so for a short time after a new release the API can still use the previous one.

# Cost

  • Each IBAN costs 1 request, whether it is valid or not. An IBAN that fails validation is a successful call (200 with valid: false).
  • A batch costs 1 request per unique IBAN.
  • Error responses (4xx and 5xx) cost nothing. The request that uses the last unit of your quota is served; the next one gets a 429.
  • The X-Cost response header states what a call cost.
  • On the free plan, the minute rate limit counts each unique IBAN of a batch as one request.

# Sandbox API Keys

With a sandbox API key (opens new window) the checks run exactly as with a live key, and every call costs nothing (X-Cost: 0). The bank object is a placeholder instead of the directory record, for every IBAN from a country with a bank directory that passes the length and structure checks:

"bank": {
    "name": "Sandbox Bank",
    "bic": "XXXXDEXXXXX",
    "city": "Sandbox City",
    "source": "Placeholder for sandbox keys; live keys get the bank from the national bank directory"
}

The placeholder BIC contains the IBAN's country code (XXXXDEXXXXX for a German IBAN). For other countries bank is null, as with a live key.

# Privacy

The single request carries the IBAN in the URL. To validate several IBANs, use the batch request: it takes the IBANs in the request body only. Send your API key in the apikey header rather than the query string.

# Not Covered

  • Whether an account exists, is open, or who holds it (no account holder or payee verification).
  • Calculating an IBAN from a domestic account number.
  • Account numbers that are not IBANs, such as US routing numbers or UK sort codes on their own.