Skip to content
IBANforge
REST API · JSON · MCP

IBAN validation API

One POST checks an IBAN the way a payment run needs it: the check digits and the country's layout, then the bank behind it, read from the national register with its source and its date.

  • 89 IBAN countries
  • Bank and BIC with their source
  • First calls without a key
Try it in the sandbox
Read the docs

What one call checks

POST /v1/iban/validate answers with one JSON object. Each check has its own field, so your code reads exactly what was verified and what was not.

Check digits

checks.iban_checksum

The ISO 13616 mod-97 check on the two digits after the country code. A single mistyped character fails it.

Country structure

checks.iban_structure

The length and the layout of the account part for each of the 89 countries of the IBAN registry. An invalid IBAN is not an HTTP error: the answer is a 200 with valid: false and the reason.

National check digits

checks.national_check_digits

Where a country hides its own key inside the account number: France and Monaco (RIB key), Belgium, Italy and San Marino (CIN), Spain (DC) and the United Kingdom (modulus check). A wrong key shows in this field and never turns valid to false. In Poland, the check digit of the settlement number comes with the bank code, in bank_code_check.check_digit.

The bank and its BIC

bank_code_check · bic.source · as_of

The bank code is looked up in the national register where we read it in full: Germany, Austria, Belgium, Slovakia, Czech Republic, Bulgaria, Switzerland and Liechtenstein. There, a code the register does not hold comes back not_allocated. Elsewhere a partial register or a composite map names the bank, and the answer says it cannot rule a code out. The register and the date of its edition travel with the answer.

SEPA and Verification of Payee

sepa · risk_indicators.vop_coverage

The SEPA schemes that reach the bank (Credit Transfer, Instant, Direct Debit), from the EPC scheme registers when they list it and from the country otherwise, with the basis named. And whether the EPC Verification of Payee register lists the bank as ready.

Bank screening, when you ask for it

POST /v1/iban/compliance

A separate call screens the payee's bank (BIC8) against the OFAC, EU and UN lists, checks the country against FATF and a fixed list of sanctioned jurisdictions, and returns a risk score from 0 to 100. It is informational, and it never screens the payee's name.

What it does not tell you

  • Whether the account exists or is open. No register publishes that: only the payee's bank knows.
  • Whose name is on the account. That check is Verification of Payee, run by the payee's bank; the API only says whether that bank is listed as ready for it.
  • Whether the payee is sanctioned. The optional screening covers the bank and the country, not the person or the company you pay.
  • The German account-number methods and the national keys of the countries not named above: they are not checked yet.
Every register, its licence and the date of the edition we read

Your first call

Copy one of these as it stands. The IBAN is the example the sandbox uses: a valid Swiss IBAN that resolves to a real bank.

The keyless trial serves 25 validations a week on POST /v1/iban/validate, counted for the address the call comes from, ISO week in UTC, reset on Monday 00:00 UTC.

curl
curl -X POST https://api.ibanforge.com/v1/iban/validate \
  -H "Content-Type: application/json" \
  -d '{"iban":"CH1000230000000012345"}'

The answer, as the API gave it

Extract of the answer the API returned for this IBAN on 25 September 2026: the fields that say what was checked, and against which register. The full answer also carries the issuer, the Swiss clearing data, risk indicators and the next step to take. Called with no key, it also carries a trial block that says how many calls are left this week and when the count resets.

json
{
  "iban": "CH1000230000000012345",
  "valid": true,
  "checks": {
    "iban_structure": "pass",
    "iban_checksum": "pass",
    "bank_code": "pass",
    "bic": "pass",
    "national_check_digits": "not_checked",
    "account_exists": "not_checked",
    "payee_name": "not_checked",
    "institution_sanctions": "not_checked",
    "country_sanctions": "not_checked",
    "payee_sanctions": "not_checked"
  },
  "country": {
    "code": "CH",
    "name": "Switzerland"
  },
  "bic": {
    "code": "UBSWCHZH80A",
    "bank_name": "UBS Switzerland AG",
    "city": "Zürich",
    "source": "SIX BankMaster (Swiss IID / BC-Nummer register)",
    "as_of": "2026-09",
    "basis": "national_register",
    "authoritative": true
  },
  "bank_code_check": {
    "value": "00230",
    "status": "verified",
    "register": "SIX BankMaster (Swiss IID / BC-Nummer register)",
    "authoritative": true,
    "as_of": "2026-09"
  },
  "sepa": {
    "member": true,
    "schemes": [
      "SCT",
      "SDD"
    ],
    "vop_required": false
  }
}

Past the keyless trial, send the same request with the header Authorization: Bearer ifk_… and your key.

Why a mod-97 check is not enough

The official Swiss example of the IBAN registry, CH93 0076 2011 6238 5295 7, has correct check digits. Its bank code is allocated to no one in the SIX BankMaster, and the API says so:

json
{
  "iban": "CH9300762011623852957",
  "valid": true,
  "bank_code_check": {
    "value": "00762",
    "status": "not_in_register",
    "reason": "not_allocated",
    "match": null,
    "register": "SIX BankMaster (Swiss IID / BC-Nummer register)",
    "authoritative": true,
    "as_of": "2026-09"
  }
}

Answer of the API to that IBAN, exported on 29 September 2026.

Start free, then pay for what you use

Three free ways in, each with its own allowance. None asks for a card.

No key

The keyless trial

25 validations a week on POST /v1/iban/validate, for the address the call comes from, as a taster. Reset on Monday 00:00 UTC.

Key, no e-mail

A key in one click

25 requests a month, on every endpoint. One empty POST to /v1/keys/generate, or the button below: no e-mail, no card.

Key, with an address

200 requests a month

Claim the same key with a 6-digit code sent to an address you read, or give the address when you create it. Same key, same prefix, no card.

When you need more

  • Pro: $29 a month for 10,000 requests, reset on the 1st, cancel anytime.
  • Credit packs that never expire, by card or in USDC: 1,000 credits for $4, 5,000 for $20, 25,000 for $80.
  • x402: pay per call in USDC on Base, no account at all, $0.005 per validation and $0.002 per IBAN in a batch.
All prices and the cost calculator

Everything around the API

Try it on your own IBANs

The sandbox runs the real API. When you are ready, take a key: no e-mail, no card.

Try it in the sandbox