# Repair an invalid IBAN: check digits and OCR near-misses > An OCR pass over a scanned invoice produces a near-miss IBAN — one wrong digit, an unreadable character. One paid call recomputes the check digits and recovers the missing characters before an agent pays the wrong account. Published 2026-06-28 · Updated 2026-08-15 · HTML version: https://invoket.com/blog/recover-a-garbled-iban-from-ocr-before-paying --- An agent that ingests invoices reads IBANs through OCR, and OCR is lossy: a scanned account number comes back with one transposed digit or a character the scanner could not resolve. Paying that number as-is routes money to the wrong account — or to no account at all. Before the disbursement, one paid call — [`GET /iban/repair`](/docs/api/iban-repair) — recomputes the check digits and reconstructs the unreadable characters, returning valid candidates ranked by known bank. This article shows where it fits an invoice-to-pay pipeline and how to read its result without trusting a guess. ## The problem: OCR turns a valid IBAN into a near-miss A structurally valid IBAN satisfies the country's BBAN layout (ISO 13616) and the mod-97 checksum (ISO 7064). OCR breaks exactly those guarantees: it flips a `5` to a `6`, or hands back a character it could not read at all. The result fails validation — but it fails *near* the truth, usually a single edit away from the correct number. A pure validator can only tell the agent the IBAN is invalid; it cannot recover the right one. Recovering it needs the country's BBAN structure plus the national bank registry to break ties between candidates — bulky, frequently-updated public data that fits a pay-per-call lookup rather than an LLM's weights. ## The call: recompute, enumerate, rank `GET /iban/repair` takes a degraded `iban` and returns a `RepairResult`: whether it could be `repaired`, whether the answer is `ambiguous`, and a `candidates` list. It works two ways: - **Wrong check digits** (positions 3–4) on an otherwise intact body are recomputed and re-validated — no marking needed. - **Unreadable characters** must be marked with a `?`. The service substitutes each `?` with the characters allowed at that position by the country's BBAN structure and keeps only the combinations that parse (structure + checksum). Crucially, it does **not** guess silently: apart from the check digits, it never corrects a character you did not mark — no implicit `O`→`0` or `I`→`1`. If OCR is unsure about a character, mark it `?`; if it is confident but wrong, only the checksum path applies. Each surviving candidate carries `bank_known` and a full `resolution` (the same shape [`GET /iban/resolve`](/docs/api/iban-resolve) returns), so you get bank/BIC/reachability for each candidate **without a second call**. Candidates are ranked **known-bank first** — the registry breaks ambiguity that a validator alone cannot. ## Reading the result honestly A repaired IBAN is a *structurally valid candidate*, not a guarantee the account exists or is the one on the invoice: | Result | What the agent should do | |---------------------------------|-------------------------------------------------------| | `repaired: true`, not ambiguous | One valid candidate — still verify it before paying | | `repaired: true`, `ambiguous` | Several parse; known-bank-first ranking is a hint, not a verdict — escalate | | `already_valid: true` | Input parsed as-is; no repair was needed | | `repaired: false` | `TOO_AMBIGUOUS` or `UNREPAIRABLE` — no confident repair | Two scope facts to keep straight: - A too-ambiguous or unrepairable input is a **200** with `repaired: false`, not an error. Per the x402 golden rule, the agent pays for the *answer to its question*, and "this cannot be repaired" is a successful answer. The `4xx` range is reserved for requests the service genuinely cannot answer. - Repair reconstructs **structure** (a number that passes layout + checksum and, ideally, maps to a known bank). It does **not** confirm the account is live, reachable, or owned by the payee. That confirmation is the next step. ## Where it sits in an invoice-to-pay pipeline Repair is the first gate after extraction, feeding the rest of the loop: 1. **OCR** the invoice; extract the candidate IBAN, marking unreadable characters `?`. 2. **Repair** — `GET /iban/repair` — recompute/enumerate; pick the candidate when unambiguous, escalate when `ambiguous`. 3. **Resolve / screen** the chosen IBAN ([`GET /iban/resolve`](/docs/api/iban-resolve)) to confirm bank, BIC and reachability — and screen it if the workflow requires. 4. **Pay** the confirmed beneficiary through your own rails. Each paid call follows the same x402 pattern as every Invoket endpoint. The [Quickstart](/docs/quickstart) walks the whole discover → `402` → pay → replay cycle with runnable snippets. Price and accepted rails are not pinned here — they are served live by the [catalog](https://api.invoket.com/catalog); see the [endpoint reference](/docs/api/iban-repair) for the current figure. ## Repairing a batch of invoices A reconciliation run rarely has one IBAN. [`POST /iban/repair/batch`](/docs/api/iban-repair-batch) repairs up to **500** degraded IBANs under **one** x402 settlement instead of one settlement per row — the cost is one settlement per call regardless of batch size, which is what makes a whole invoice batch workable as a single pre-payment pass. ## What repair does *not* do - It does **not** invent corrections you did not mark, beyond the check digits — no silent OCR substitution. - It does **not** assert that a repaired candidate is *the* IBAN on the invoice, or that the account exists. A confident-looking single candidate still needs [`GET /iban/resolve`](/docs/api/iban-resolve) to confirm bank/BIC/reachability, and [`GET /iban/screen`](/docs/api/iban-screen) where the workflow demands it. Used for what it is — a structural recovery step that turns an OCR near-miss into ranked, valid candidates — it lets an autonomous accounting agent fix the fixable and escalate the ambiguous, before money leaves. For the full field reference and error codes, see the [`GET /iban/repair` documentation](/docs/api/iban-repair); for how agents discover and call Invoket endpoints, see [For agents](/docs/for-agents).