GET /iban/repair

Repairs a degraded IBAN in a single call: it recomputes the check digits when the body (BBAN) is intact, and recovers unreadable characters marked with ? by validated enumeration (country structure + mod-97 checksum). Built for the agent accounting pipeline that ingests invoices — an OCR pass turns a scanned IBAN into a near-miss (one wrong digit, an unreadable character), and this endpoint recovers it. Candidates are ranked known-bank first: the local bank registry breaks the ambiguity that pure validators cannot. Purely local lookup → response in milliseconds.

x402 golden rule: the agent pays for the answer to its question. “This IBAN cannot be repaired” is a successful answer → 200 with repaired: false. The 4xx range is reserved for requests the service cannot answer.

Parameters

ParameterTypeRequiredDescription
ibanstringyesDegraded IBAN to repair; spaces and dashes tolerated, any case

The ? convention

Mark each unreadable character with a question mark ?. The service substitutes every ? with the characters allowed at that position (constrained by the country’s BBAN structure) and keeps only the combinations that parse (structure + checksum):

DE89370400440532013?00

The service does not guess without ?: there is no implicit OCR correction (no O0, I1). The only exception is the check digits (positions 3–4): an input without ? whose only fault is a wrong checksum is repaired by recomputing them, and ?? in those two positions triggers the same recompute.

200 response — UnifiedResponse

{
  "data": { ... },
  "provenance": {
    "source": "national-bank-registries",
    "fetched_at": "2026-06-21T09:30:00Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-20T00:00:00Z" }
  }
}
  • provenance.source: stable identifier of the bank registry.
  • freshness.as_of: date of the registry snapshot (meta.json).

Fields of dataRepairResult

FieldTypeDescription
inputstringThe input as received, normalized (upper-cased, separators removed, ? kept)
repairedbooltrue when at least one valid candidate was found
already_validbooltrue when the input was already a valid IBAN (single candidate = itself)
ambiguousbooltrue when more than one candidate survives (or the candidate cap is hit)
candidatesarrayRepaired candidates, ranked known-bank first (see below)
issuestring | nullDiagnostic code when candidates is empty: TOO_AMBIGUOUS or UNREPAIRABLE

Each entry of candidates carries:

FieldTypeDescription
ibanstringThe repaired IBAN, in electronic form
bank_knownboolWhether (country, bank_code) maps to a bank in the registry (drives the ranking)
resolutionobjectThe full resolve verdict for this IBAN — bank, BIC, reachability

Each resolution is exactly what GET /iban/resolve returns for the repaired IBAN, so you get bank/BIC/reachability without a second call. See the single-call reference for the full field table.

Case 1 — wrong check digits, recomputed

Input has no ? and only its checksum is wrong: the check digits are recomputed (ISO 7064, mod-97-10) and re-validated. A single candidate, the correct IBAN.

{
  "input": "DE89370400440532013001",
  "repaired": true,
  "already_valid": false,
  "ambiguous": false,
  "candidates": [
    {
      "iban": "DE89370400440532013000",
      "bank_known": true,
      "resolution": {
        "iban": "DE89370400440532013000",
        "valid": true,
        "country": "DE",
        "bank_code": "37040044",
        "branch_code": null,
        "bank": { "name": "Commerzbank", "bic": "COBADEFFXXX" },
        "reachable": true,
        "coverage": "full",
        "issue": null
      }
    }
  ],
  "issue": null
}

Case 2 — unreadable character recovered, single candidate

One ? at a digit position; only one substitution parses. Unambiguous.

{
  "input": "DE8937040044053201300?",
  "repaired": true,
  "already_valid": false,
  "ambiguous": false,
  "candidates": [
    { "iban": "DE89370400440532013000", "bank_known": true, "resolution": { "...": "..." } }
  ],
  "issue": null
}

Case 3 — several candidates, ranked known-bank first

When more than one substitution parses, all survivors are returned, known bank first, with ambiguous: true. Ties are ordered lexicographically for a deterministic result.

{
  "input": "DE??370400440532013000",
  "repaired": true,
  "already_valid": false,
  "ambiguous": true,
  "candidates": [
    { "iban": "DE89370400440532013000", "bank_known": true,  "resolution": { "...": "..." } },
    { "iban": "DE12370400440532013000", "bank_known": false, "resolution": { "...": "..." } }
  ],
  "issue": null
}

Case 4 — already valid (successful answer → 200)

The input parses as-is: already_valid: true, repaired: false, a single candidate equal to the input.

{
  "input": "DE89370400440532013000",
  "repaired": false,
  "already_valid": true,
  "ambiguous": false,
  "candidates": [
    { "iban": "DE89370400440532013000", "bank_known": true, "resolution": { "...": "..." } }
  ],
  "issue": null
}

Case 5 — cannot repair (successful answer → 200)

Too many ? to enumerate, or no substitution parses: repaired: false, candidates: [], and issue tells which. This is not an error.

{
  "input": "DE????????440532013000",
  "repaired": false,
  "already_valid": false,
  "ambiguous": false,
  "candidates": [],
  "issue": "TOO_AMBIGUOUS"
}

issue codes: TOO_AMBIGUOUS (more wildcards than the service will enumerate) and UNREPAIRABLE (a structurally wrong BBAN with no ? to recover).

Honest limits

  • No guessing without ?. Apart from the check digits, the service never corrects characters you did not mark — it will not turn O into 0. Mark every unreadable character with ?.
  • A too-ambiguous or unrepairable IBAN is a 200, not an error (repaired: false). Treat it as “no confident repair”, not a failure.
  • For the full per-field bank/BIC/reachability detail of a repaired IBAN, use GET /iban/resolve — each candidate already embeds its resolution.

Errors

StatuscodeCase
400MISSING_PARAMETERiban parameter missing or empty
500INTERNALInternal error (detail logged, not exposed)
{ "error": "missing or empty required parameter: iban", "code": "MISSING_PARAMETER" }

See also

  • GET /iban/resolve — resolve an IBAN to its bank, BIC and reachability; full field reference for each candidate’s resolution.
  • POST /iban/repair/batch — repair many degraded IBANs in one settlement.
  • For agents — discovery surfaces, the live /catalog and how settlement works.