Recover a garbled IBAN from OCR before paying

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.

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 — 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 O0 or I1. 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 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:

ResultWhat the agent should do
repaired: true, not ambiguousOne valid candidate — still verify it before paying
repaired: true, ambiguousSeveral parse; known-bank-first ranking is a hint, not a verdict — escalate
already_valid: trueInput parsed as-is; no repair was needed
repaired: falseTOO_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. RepairGET /iban/repair — recompute/enumerate; pick the candidate when unambiguous, escalate when ambiguous.
  3. Resolve / screen the chosen IBAN (GET /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 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; see the endpoint reference for the current figure.

Repairing a batch of invoices

A reconciliation run rarely has one IBAN. POST /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 to confirm bank/BIC/reachability, and screening/Verification of Payee 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; for how agents discover and call Invoket endpoints, see For agents.