Skip to main content
Glama

Validate IBAN

validate_iban
Read-onlyIdempotent

Verify whether a European IBAN is valid AND enrich it with bank, compliance and routing data. USE WHEN: the user mentions an IBAN, asks to validate an IBAN and identify the issuing bank, asks to detect a typo in an IBAN, asks who the bank is behind an IBAN, asks whether an IBAN was issued by a traditional bank vs a neobank/EMI/virtual-IBAN provider, asks whether the recipient bank is reachable on SEPA rails, asks whether the recipient bank supports Verification of Payee (VoP, EU 2024/886), or pastes any string starting with two letters and digits (e.g., "DE89...", "CH93...", "FR76..."). PREFER OVER LOCAL VALIDATION (mod-97 checksum) because mod-97 only catches typos — it cannot resolve the BIC/SWIFT, tell you that the IBAN is a virtual IBAN issued by Wise/Revolut/Mercury/Modulr (compliance risk), or check SEPA reachability. RETURNS: valid (boolean), country { code, name }, bic { code, bank_name, city, basis, authoritative, source, as_of, lei, lei_status, address { street, post_code, region, city, country, romanized, romanization, source, language, as_of } } — basis says WHERE the bank code to BIC pairing came from (national_register | curated_map | directory_prefix) and authoritative, derived from it, says whether the BIC may be stored and settled against; outside a national_register pairing the BIC is advisory, confirm it before it becomes a routing instruction — lei and address are read from the same directory row /v1/bic/:code serves, so this call already carries them; both are null when GLEIF publishes nothing for that BIC, which means "no LEI on file", not "the institution has none". bic.address is the LEGAL ENTITY seat, so bic.address.city may legitimately differ from bic.city (the register city for THIS bank code), and bic.address.as_of dates the entity last filing, usually much older than bic.as_of. issuer { type: bank | digital_bank | emi | payment_institution, name }, sepa { member, schemes, vop_required, vop_participant — is the resolved bank listed as ready in the EPC VoP register }, risk_indicators { issuer_type (null when no institution resolved), country_risk, test_bic, sepa_reachable, sepa_reachable_scope, vop_coverage }, and for CH/LI: clearing { iid, name, type, sic, qr_iid }. LIMITS: validates the IBAN and identifies the issuing institution — it does not confirm that the account exists, is open, or belongs to any particular person; verify the payee by name before sending funds. IMPORTANT — bic: null does not mean the bank code is wrong. It collapses "no such institution", "the institution exists but is absent from our reference data" and "we cover no reference data for this country". Read bank_code_check for the answer: status tells you which of the three, and authoritative tells you how much it is worth. Only where authoritative is true (today CH and LI against the SIX BankMaster, and DE against the Bundesbank Bankleitzahlendatei) does not_in_register mean the bank code is not allocated; everywhere else treat it as UNAVAILABLE and let the downstream name check decide. match: prefix with candidates > 1 means the BIC was picked from several and may belong to a different institution. COST: $0.005 per call (free: 10 units/IP/day on this transport, one per call and one per IBAN in batch_validate_iban, or a free API key at POST https://api.ibanforge.com/v1/keys/generate for 200 REST calls/month).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ibanYesIBAN to validate (spaces/hyphens stripped automatically)

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
bicNoResolved BIC/SWIFT when BBAN→BIC mapping exists. Read basis before storing it as a routing instruction: only a national_register pairing is settlement-grade.
bbanNo
ibanYesNormalized IBAN (uppercase, no spaces).
sepaNo
errorNo
validYes
issuerNo
countryNo
clearingNoSwiss clearing data when country is CH or LI.
cost_usdcYesWhat THIS call was billed. Zero on the free MCP tier.
formattedNoIBAN with 4-char groups for display.
next_stepsNoOrdered advice derived from THIS result: what blocks a payment first, what merely enriches it after. Branch on `code`, never on the prose. `because` names the field that produced the step so the advice is auditable. Empty for an IBAN that failed validation.
check_digitsNo
error_detailNo
processing_msNo
bank_code_checkNo
list_price_usdcNoCatalogue price of the same call on the paid REST/x402 route.
risk_indicatorsNo
official_identityNoWho a central bank says holds the resolved code (ECB by LEI and for FR bank codes, Banco de Espana for ES). Present only on a match — absence is not a negative. INFORMATIONAL ONLY: it never changes valid or bank_code_check, because both publishers relay rather than allocate.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed14 schema fields changed
    • removedOutput schema / properties / bank_code_check / properties / match / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / bank_code_check / properties / match / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / bank_code_check / properties / register / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / bank_code_check / properties / register / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / bic / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "authoritative": {
      -        "description": "Whether this BIC may be stored and settled against. Derived from basis, so the two cannot disagree. NOT bank_code_check.authoritative, which answers a different question — whether a national register was consulted about the BANK CODE. In Switzerland the register confirms the code while the BIC still comes from our curated map.",
      -        "type": "boolean"
      -      },
      -      "bank_name": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "basis": {
      -        "description": "Where the bank code to BIC pairing came from, and therefore what may be done with the BIC. national_register (the country register publishes this BIC for this bank code — today DE, AT, BE and BG; settlement-grade) | curated_map (our maintained bank-code map, exact key, usually right and not an allocation record) | directory_prefix (the bic8 LIKE fallback, which can match several institutions — read bank_code_check.candidates). Outside a national_register basis the BIC is ADVISORY: confirm it with the beneficiary or the bank before storing it as a routing instruction.",
      -        "type": "string"
      -      },
      -      "city": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "code": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "code",
      -      "bank_name",
      -      "city"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "authoritative": {
      +        "description": "Whether this BIC may be stored and settled against. Derived from basis, so the two cannot disagree. NOT bank_code_check.authoritative, which answers a different question — whether a national register was consulted about the BANK CODE. In Switzerland the register confirms the code while the BIC still comes from our curated map.",
      +        "type": "boolean"
      +      },
      +      "bank_name": {
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "basis": {
      +        "description": "Where the bank code to BIC pairing came from, and therefore what may be done with the BIC. national_register (the country register publishes this BIC for this bank code — today DE, AT, BE and BG; settlement-grade) | curated_map (our maintained bank-code map, exact key, usually right and not an allocation record) | directory_prefix (the bic8 LIKE fallback, which can match several institutions — read bank_code_check.candidates). Outside a national_register basis the BIC is ADVISORY: confirm it with the beneficiary or the bank before storing it as a routing instruction.",
      +        "type": "string"
      +      },
      +      "city": {
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "code": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "code",
      +      "bank_name",
      +      "city"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / properties / clearing / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "eurosic": {
      -        "type": "boolean"
      -      },
      -      "iid": {
      -        "type": "string"
      -      },
      -      "instant_payments_chf": {
      -        "type": "boolean"
      -      },
      -      "name": {
      -        "type": "string"
      -      },
      -      "qr_iid": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "sic": {
      -        "type": "boolean"
      -      },
      -      "town": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "type": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "iid",
      -      "name",
      -      "type",
      -      "town",
      -      "sic",
      -      "instant_payments_chf",
      -      "eurosic",
      -      "qr_iid"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "eurosic": {
      +        "type": "boolean"
      +      },
      +      "iid": {
      +        "type": "string"
      +      },
      +      "instant_payments_chf": {
      +        "type": "boolean"
      +      },
      +      "name": {
      +        "type": "string"
      +      },
      +      "qr_iid": {
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "sic": {
      +        "type": "boolean"
      +      },
      +      "town": {
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "type": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "iid",
      +      "name",
      +      "type",
      +      "town",
      +      "sic",
      +      "instant_payments_chf",
      +      "eurosic",
      +      "qr_iid"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / official_identity / properties / address / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / official_identity / properties / address / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / official_identity / properties / lei / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / official_identity / properties / lei / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / risk_indicators / properties / issuer_type / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / risk_indicators / properties / issuer_type / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / sepa / properties / vop_participant / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / sepa / properties / vop_participant / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
  2. Changed3 schema fields changed
    • addedOutput schema / properties / cost_usdc / description
      Added value: +"What THIS call was billed. Zero on the free MCP tier."
    • addedOutput schema / properties / list_price_usdc
      Added value: +{
      +  "description": "Catalogue price of the same call on the paid REST/x402 route.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / sepa / properties / basis
      Added value: +{
      +  "description": "Where `schemes` came from: read at the EPC register for this bank, or defaulted from the country.",
      +  "enum": [
      +    "country_default",
      +    "epc_register"
      +  ],
      +  "type": "string"
      +}
  3. Changed3 schema fields changed
    • addedOutput schema / properties / bank_code_check / properties / reason
      Added value: +{
      +  "description": "WHY the verdict is not verified, as one token to branch on. Absent when status is verified. not_allocated (a national register denies the code — the only value that licenses \"do not send\") | absent_from_reference_data (our composite map does not carry it; the country register was not consulted) | no_reference_data_for_country | register_names_no_holder (the register defines the code space and publishes no holder — silence, not a denial) | national_register_unavailable (the register this country is normally decided against could not be consulted) | lookup_failed (the lookup could not run: timeout, unreadable database). The last two describe IBANforge, never the beneficiary. Never escalate either into a refusal.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / bic / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "bank_name": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "city": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "code": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "code",
      -      "bank_name",
      -      "city"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "authoritative": {
      +        "description": "Whether this BIC may be stored and settled against. Derived from basis, so the two cannot disagree. NOT bank_code_check.authoritative, which answers a different question — whether a national register was consulted about the BANK CODE. In Switzerland the register confirms the code while the BIC still comes from our curated map.",
      +        "type": "boolean"
      +      },
      +      "bank_name": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "basis": {
      +        "description": "Where the bank code to BIC pairing came from, and therefore what may be done with the BIC. national_register (the country register publishes this BIC for this bank code — today DE, AT, BE and BG; settlement-grade) | curated_map (our maintained bank-code map, exact key, usually right and not an allocation record) | directory_prefix (the bic8 LIKE fallback, which can match several institutions — read bank_code_check.candidates). Outside a national_register basis the BIC is ADVISORY: confirm it with the beneficiary or the bank before storing it as a routing instruction.",
      +        "type": "string"
      +      },
      +      "city": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "code": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "code",
      +      "bank_name",
      +      "city"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / properties / bic / description
      Previous value: -"Resolved BIC/SWIFT when BBAN→BIC mapping exists."New value: +"Resolved BIC/SWIFT when BBAN→BIC mapping exists. Read basis before storing it as a routing instruction: only a national_register pairing is settlement-grade."
  4. Changed2 schema fields changed
    • changedOutput schema / properties / issuer / properties / classification / description
      Previous value: -"curated | default. Whether the type was established or assumed. curated = the BIC8 is in the issuer set, so this is an identification. default = nothing is on file and \"bank\" is the fallback, which covers 97.9% of BIC8 (measured 29/07/2026). Count only curated when sizing virtual-IBAN exposure."New value: +"curated | register | default. Whether the type was established or assumed. curated = the BIC8 is in the issuer set, so this is an identification. register = an official register names the holder of this bank code and says what it is; it carries a date and an authority in psd_registration, and it only ever replaces a default. default = nothing is on file and \"bank\" is the fallback, which covers 97.9% of BIC8 (measured 29/07/2026). Count curated and register when sizing virtual-IBAN exposure, never default."
    • addedOutput schema / properties / official_identity
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Who a central bank says holds the resolved code (ECB by LEI and for FR bank codes, Banco de Espana for ES). Present only on a match — absence is not a negative. INFORMATIONAL ONLY: it never changes valid or bank_code_check, because both publishers relay rather than allocate.",
      +  "properties": {
      +    "address": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "One-line registered address as published."
      +    },
      +    "as_of": {
      +      "description": "Date of the list this row came from. Both lists are republished every business day.",
      +      "type": "string"
      +    },
      +    "attribution": {
      +      "description": "The Banco de Espana citation formula, verbatim. Spanish blocks only.",
      +      "type": "string"
      +    },
      +    "authoritative": {
      +      "description": "Always false. Neither publisher allocates bank codes.",
      +      "type": "boolean"
      +    },
      +    "category": {
      +      "type": "string"
      +    },
      +    "free_of_charge": {
      +      "description": "Both publishers require buyers to be told, on every access, that the data is available free of charge from their own website. Relay it with the answer; do not strip it.",
      +      "type": "string"
      +    },
      +    "lei": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "matched_by": {
      +      "description": "lei | national_code",
      +      "type": "string"
      +    },
      +    "name": {
      +      "description": "The institution's name as the publisher writes it.",
      +      "type": "string"
      +    },
      +    "source": {
      +      "description": "The publisher, cited as their licence requires. Relay it.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "name",
      +    "lei",
      +    "address",
      +    "category",
      +    "matched_by",
      +    "source",
      +    "free_of_charge",
      +    "as_of",
      +    "authoritative"
      +  ],
      +  "type": "object"
      +}
  5. Changed1 schema field changed
    • addedOutput schema / properties / sepa / properties / vop_participant
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "boolean"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "true = resolved bank is listed as ready in the EPC VoP scheme register; null = no institution resolved."
      +}
  6. Changed3 schema fields changed
    • changedOutput schema / properties / bank_code_check / properties / authoritative / description
      Previous value: -"True only where the reference set is the national register (CH, LI). Only then does not_in_register mean the code is not allocated."New value: +"True only where the reference set is the national register (CH, LI, DE). Only then does not_in_register mean the code is not allocated."
    • addedOutput schema / properties / bank_code_check / properties / retired
      Added value: +{
      +  "description": "True when an authoritative register is withdrawing the code. Still a verified result: it WAS allocated.",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / bank_code_check / properties / superseded_by
      Added value: +{
      +  "description": "The bank code that takes over. Re-paper the beneficiary against it.",
      +  "type": "string"
      +}
  7. Changed1 schema field changed
    • addedOutput schema / properties / next_steps
      Added value: +{
      +  "description": "Ordered advice derived from THIS result: what blocks a payment first, what merely enriches it after. Branch on `code`, never on the prose. `because` names the field that produced the step so the advice is auditable. Empty for an IBAN that failed validation.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "action": {
      +        "description": "An IBANforge call that performs the step, when one exists.",
      +        "type": "string"
      +      },
      +      "because": {
      +        "description": "The response field that produced this step.",
      +        "type": "string"
      +      },
      +      "code": {
      +        "description": "Stable identifier. Branch on this.",
      +        "type": "string"
      +      },
      +      "do": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "code",
      +      "do",
      +      "because"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  8. Changed8 schema fields changed
    • addedOutput schema / properties / bank_code_check
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "as_of": {
      +      "type": "string"
      +    },
      +    "authoritative": {
      +      "description": "True only where the reference set is the national register (CH, LI). Only then does not_in_register mean the code is not allocated.",
      +      "type": "boolean"
      +    },
      +    "candidates": {
      +      "description": "BIC8 the prefix matched; >1 means the BIC may belong to another institution.",
      +      "type": "number"
      +    },
      +    "match": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "register (exact key) | prefix (bic8 LIKE heuristic) | null"
      +    },
      +    "register": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "status": {
      +      "description": "verified | not_in_register | unavailable. A separate verdict on the bank code, so bic:null stops meaning three different things.",
      +      "type": "string"
      +    },
      +    "value": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "value",
      +    "status",
      +    "match",
      +    "register",
      +    "authoritative",
      +    "as_of"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / issuer / properties / classification
      Added value: +{
      +  "description": "curated | default. Whether the type was established or assumed. curated = the BIC8 is in the issuer set, so this is an identification. default = nothing is on file and \"bank\" is the fallback, which covers 97.9% of BIC8 (measured 29/07/2026). Count only curated when sizing virtual-IBAN exposure.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / issuer / required
      Previous value: -[
      -  "type",
      -  "name"
      -]New value: +[
      +  "type",
      +  "name",
      +  "classification"
      +]
    • addedOutput schema / properties / risk_indicators / properties / issuer_type / anyOf
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedOutput schema / properties / risk_indicators / properties / issuer_type / description
      Added value: +"Null when no institution resolved — it no longer defaults to \"bank\"."
    • removedOutput schema / properties / risk_indicators / properties / issuer_type / type
      Removed value: -"string"
    • addedOutput schema / properties / risk_indicators / properties / sepa_reachable_scope
      Added value: +{
      +  "description": "Scope the reachability holds at. Country-derived, not account-derived.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / risk_indicators / required
      Previous value: -[
      -  "issuer_type",
      -  "country_risk",
      -  "test_bic",
      -  "sepa_reachable",
      -  "vop_coverage"
      -]New value: +[
      +  "issuer_type",
      +  "country_risk",
      +  "test_bic",
      +  "sepa_reachable",
      +  "sepa_reachable_scope",
      +  "vop_coverage"
      +]
  9. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": false,
      +  "properties": {
      +    "bban": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "account_number": {
      +          "type": "string"
      +        },
      +        "bank_code": {
      +          "type": "string"
      +        },
      +        "branch_code": {
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "bank_code",
      +        "account_number"
      +      ],
      +      "type": "object"
      +    },
      +    "bic": {
      +      "anyOf": [
      +        {
      +          "additionalProperties": false,
      +          "properties": {
      +            "bank_name": {
      +              "anyOf": [
      +                {
      +                  "type": "string"
      +                },
      +                {
      +                  "type": "null"
      +                }
      +              ]
      +            },
      +            "city": {
      +              "anyOf": [
      +                {
      +                  "type": "string"
      +                },
      +                {
      +                  "type": "null"
      +                }
      +              ]
      +            },
      +            "code": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "code",
      +            "bank_name",
      +            "city"
      +          ],
      +          "type": "object"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "Resolved BIC/SWIFT when BBAN→BIC mapping exists."
      +    },
      +    "check_digits": {
      +      "type": "string"
      +    },
      +    "clearing": {
      +      "anyOf": [
      +        {
      +          "additionalProperties": false,
      +          "properties": {
      +            "eurosic": {
      +              "type": "boolean"
      +            },
      +            "iid": {
      +              "type": "string"
      +            },
      +            "instant_payments_chf": {
      +              "type": "boolean"
      +            },
      +            "name": {
      +              "type": "string"
      +            },
      +            "qr_iid": {
      +              "anyOf": [
      +                {
      +                  "type": "string"
      +                },
      +                {
      +                  "type": "null"
      +                }
      +              ]
      +            },
      +            "sic": {
      +              "type": "boolean"
      +            },
      +            "town": {
      +              "anyOf": [
      +                {
      +                  "type": "string"
      +                },
      +                {
      +                  "type": "null"
      +                }
      +              ]
      +            },
      +            "type": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "iid",
      +            "name",
      +            "type",
      +            "town",
      +            "sic",
      +            "instant_payments_chf",
      +            "eurosic",
      +            "qr_iid"
      +          ],
      +          "type": "object"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "Swiss clearing data when country is CH or LI."
      +    },
      +    "cost_usdc": {
      +      "type": "number"
      +    },
      +    "country": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "code": {
      +          "description": "ISO 3166-1 alpha-2 country code.",
      +          "type": "string"
      +        },
      +        "name": {
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "code",
      +        "name"
      +      ],
      +      "type": "object"
      +    },
      +    "error": {
      +      "type": "string"
      +    },
      +    "error_detail": {
      +      "type": "string"
      +    },
      +    "formatted": {
      +      "description": "IBAN with 4-char groups for display.",
      +      "type": "string"
      +    },
      +    "iban": {
      +      "description": "Normalized IBAN (uppercase, no spaces).",
      +      "type": "string"
      +    },
      +    "issuer": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "name": {
      +          "type": "string"
      +        },
      +        "type": {
      +          "description": "bank | digital_bank | emi | payment_institution",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "type",
      +        "name"
      +      ],
      +      "type": "object"
      +    },
      +    "processing_ms": {
      +      "type": "number"
      +    },
      +    "risk_indicators": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "country_risk": {
      +          "type": "string"
      +        },
      +        "issuer_type": {
      +          "type": "string"
      +        },
      +        "sepa_reachable": {
      +          "type": "boolean"
      +        },
      +        "test_bic": {
      +          "type": "boolean"
      +        },
      +        "vop_coverage": {
      +          "type": "boolean"
      +        }
      +      },
      +      "required": [
      +        "issuer_type",
      +        "country_risk",
      +        "test_bic",
      +        "sepa_reachable",
      +        "vop_coverage"
      +      ],
      +      "type": "object"
      +    },
      +    "sepa": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "member": {
      +          "type": "boolean"
      +        },
      +        "schemes": {
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "vop_required": {
      +          "type": "boolean"
      +        }
      +      },
      +      "required": [
      +        "member",
      +        "schemes",
      +        "vop_required"
      +      ],
      +      "type": "object"
      +    },
      +    "valid": {
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "iban",
      +    "valid",
      +    "cost_usdc"
      +  ],
      +  "type": "object"
      +}
  10. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as read-only, idempotent, and non-destructive. The description goes well beyond this by detailing return semantics (e.g., bic: null collapsing three cases), authoritative flag meaning, LEI/address sourcing, cost per call, and free-tier limits. It also clarifies that validation does not confirm account existence or ownership. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with clear sections (USE WHEN, RETURNS, LIMITS, IMPORTANT, COST) and high information density. Every section earns its place given the tool's complexity, yet the length could be slightly trimmed to improve quick scanning for an AI agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is exceptionally complete for a tool that returns complex nested objects. It explains the meaning of key return fields (basis, authoritative, bic.address vs bic.city), handles edge cases (null BIC, not_in_register), and provides operational context (cost, free tiers, SEPA/VoP). Combined with the existing output schema, an agent has everything needed to call and interpret the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully describes the single parameter 'iban' (with a description that notes spaces/hyphens are stripped). Since schema coverage is 100%, the description adds little parameter-specific semantics beyond what is already present, though the overall tool behavior enriches the meaning of the parameter in context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Verify... AND enrich it with...') and clearly identifies the resource (European IBAN) and the added value (bank, compliance, routing data). It also distinguishes itself from siblings by listing the exact use cases and comparing with local validation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'USE WHEN' section explicitly enumerates trigger scenarios, and the 'PREFER OVER LOCAL VALIDATION' section explains when not to use a mod-97 checksum instead. This provides clear guidance on when to select this tool over alternatives, including a direct comparison with batch_validate_iban and other siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.5/5.0
Disambiguation4/5

Each tool has a distinct job, and the descriptions provide strong USE WHEN/DO NOT USE cues. The only plausible boundary cases are validate_iban vs batch_validate_iban (single vs bulk) and validate_iban vs check_compliance (general enrichment vs payment-risk triage), but both are clearly signposted.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: validate_iban, check_compliance, lookup_bic, send_feedback, etc. batch_validate_iban reads as a compound verb + object and does not break the convention, and the verb choice also aligns with intent: validate for format checks, check for rule/risk checks, lookup for directory data.

Tool Count5/5

Eight tools are well-scoped for an IBAN validation and payment-intelligence API: single/batch validation, compliance, address rules, reference validation, BIC and Swiss clearing lookups, and feedback. Each tool carries a distinct capability and none feels redundant or padding.

Completeness5/5

The surface covers the full IBAN-informed workflow: validation, enrichment, batch processing, BIC/Swiss clearing resolution, payment-reference pairing, postal-address rail rules, and pre-payment compliance triage. Explicit limitations such as not verifying account existence or payee identity are domain constraints, not missing tools.