Reject a mistyped CLABE before requesting a paid bank-name check
A Mexico payout form or payment-file import receives an 18-digit CLABE. If one digit is mistyped, a later paid bank-name or account check is spent on an input that could never pass. This article shows how a local format check returns structure_valid, checksum_valid and an institution code without network calls, and why a correct checksum still proves nothing about whether the account exists, can receive funds or belongs to a person.
gridzen tools --product clabe-formatThe problem and your decision
Your payout onboarding collects a CLABE and then, in a separate authorized workflow, may request a paid verification such as a bank-name comparison. Typos are common: a swapped pair of digits, a missing digit, stray spaces from copy and paste. Sending those inputs onward costs a request and produces a confusing failure for the user. The decision is where to stop a bad input. The proposal here: run a local checksum check first, reject only inputs that are structurally wrong or fail the checksum, and treat a pass as permission to ask the next question, not as an answer to it.
What the local utility actually does
The implemented behavior is narrow. The check_clabe_format tool accepts an 18-digit CLABE, optionally separated by spaces or hyphens, and runs locally with no network. It reports structure_valid (the input normalizes to 18 digits), checksum_valid (the final control digit matches the weighted calculation over the first 17 digits) and institution_code (the first three digits). It performs no live bank query and makes no account-ownership assertion. A correct checksum does not prove that an account exists, can receive funds or belongs to a person. Anything beyond these fields, such as routing the user or calling a paid check, is proposed application design that your code must own.
Worked hypothetical scenario and expected fixture output
Hypothetically, a payment-file import row contains the sample value 032180000118359719. The tested local output is: structure_valid true, checksum_valid true, institution_code "032", scope "checksum_only", account_exists null, ownership_verified false, network_calls 0, charged false. Read each field literally. account_exists is null because nothing was asked about existence, not because existence was confirmed or denied. ownership_verified is false because ownership was never in scope. network_calls 0 and charged false confirm that the check cost nothing and contacted no one. In the proposed design, this row may proceed to the next authorized step. If an operator instead typed 032180000118359791, swapping the last two digits, you should expect checksum_valid to be false and the row to stop before any paid request; confirm that expectation in your own tests rather than assuming it.
Failure handling
Separate three outcomes. Structure failure: fewer or more than 18 digits, or non-digit characters after removing spaces and hyphens; ask the user to re-enter the value and show the digit count. Checksum failure: 18 digits but the control digit does not match; say the number appears mistyped and request correction, without suggesting the account is fraudulent or closed. Pass: proceed, but keep the record labelled checksum_only. Do not translate a pass into account_verified in your database, and do not auto-release payouts on it. For batch imports, flag failing rows individually instead of rejecting the whole file, and never silently correct a digit, because a guessed digit can point to someone else's valid-looking number.
Limits you should state plainly
This utility is a local input filter. It does not query banks, confirm that an institution code is currently active for payouts, verify a beneficiary name or establish who controls the account. Merchant examples here are synthetic contract illustrations, not live acceptance. Any paid identity or beneficiary-account verification is a separate workflow that requires current capabilities, authorization and an accepted quote. No product feedback supports claims of saved cost or improved conversion; the observed counts are zero and imply nothing causal.
Acceptance checklist
Before shipping: the sample input yields exactly the eight fields above; spaced and hyphenated forms of the same number give the same result; a 17-digit input sets structure_valid false; a swapped-digit input sets checksum_valid false and triggers no downstream request; stored records keep scope checksum_only and ownership_verified false; user messages for structure and checksum failures are distinct; no code path marks an account verified or releases funds from this check alone; batch imports report failing rows individually; and the later paid check is only called through its own authorized workflow.
Inspect this product
https://gridzen.ai/tools/clabe-format/ · Inspect the documented input, output and boundary. This command lists the product without executing a live request.
gridzen tools --product clabe-formatSources and scope
https://gridzen.ai/tools/clabe-format/ https://gridzen.ai/guides/current-capabilities/ Based on the checked source snapshot and local fixture; proposed application rules are design advice, not proven production behavior. Written with AI assistance and reviewed independently.