Clabe.Core 1.1.0

dotnet add package Clabe.Core --version 1.1.0
                    
NuGet\Install-Package Clabe.Core -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Clabe.Core" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Clabe.Core" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Clabe.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Clabe.Core --version 1.1.0
                    
#r "nuget: Clabe.Core, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Clabe.Core@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Clabe.Core&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Clabe.Core&version=1.1.0
                    
Install as a Cake Tool

Clabe.Core - CLABE Validation Library

A validation, parsing, and bank-name resolution library for Mexican CLABE (Clave Bancaria Estandarizada) account numbers, for .NET applications. It mirrors the design of the sibling Iban.Core component.

Why this component exists

A CLABE splits into a stable algorithm and volatile data:

  • Structure + control digit — an 18-digit number (3 bank code + 3 plaza code + 11 account + 1 control digit) validated with a weighted modulus-10 check. This has not changed since 2004, so we implement it directly (no dependency to reinvent a 15-line algorithm).
  • Bank-code → bank-name catalog — the set of Mexican banks changes over time. This is the part that goes stale, so it is kept as refreshable data, not hardcoded logic. The bundled snapshot is sourced from Banxico's SPEI participant list and can be replaced/synced without any code change.

Existing options were unsuitable: the ValidaCLABE NuGet package is a single-dev project last touched ~6 years ago with hardcoded, now-stale bank data, and clabe-validator is TypeScript with the catalog embedded in source.

Features

  • ✅ Structural validation — length, digits, and control digit
  • ✅ Parsing — bank code, plaza code, account number, control digit
  • ✅ Bank-name resolution — display the institution like a SWIFT/BIC lookup
  • ✅ SWIFT/BIC resolution — curated per-institution BIC lists with pick-only-if-identifiable semantics (ResolveSwiftBic)
  • ✅ Refreshable catalog — swap in fresh Banxico data via IBankCatalog
  • ✅ Structured errors — ClabeValidationError codes, not bare booleans
  • ✅ Flexible input — accepts spaces and hyphens

Quick Start

using Clabe.Core;

var service = new ClabeValidationService();

// Quick boolean check
bool ok = service.IsValid("012180012345678909");

// Detailed result + bank name for display
ValidationResult result = service.Validate("012 180 01234567890 9");
if (result.IsValid)
{
    Console.WriteLine(result.BankShortName); // "BBVA BANCOMER"
}
else
{
    Console.WriteLine($"{result.ErrorCode}: {result.ErrorMessage}");
}

// Resolve the bank for display (SWIFT-style), from a full or partial CLABE
BankInstitution? bank = service.IdentifyBank("072320098765432109"); // BANORTE

// An institution carries a LIST of SWIFT/BIC entries (head office + optional
// branch-qualified codes). SPEI-only participants (fintechs, STP, …) have an
// empty list — that's meaningful: do not guess a BIC for them.
IReadOnlyList<SwiftBicEntry> bics = bank!.SwiftBics;

// SwiftBic picks only when identifiable: the sole entry, or the sole head
// office among several. Ambiguous lists yield null rather than a guess.
string? bic = bank.SwiftBic; // "MENOMXMT"

// When you hold extra information, let the resolver pick from the list:
// a city hint matches branch-qualified entries, else falls back to the
// unambiguous default, else null.
string? branchBic = service.ResolveSwiftBic(
    "072320098765432109",
    new SwiftBicResolutionHints { City = "Monterrey" });

// Parse into components
if (service.TryParse("012180012345678909", out var parsed))
{
    var p = parsed!.Value;
    // p.BankCode.Value == "012", p.PlazaCode == "180", p.AccountNumber, p.CheckDigit
}

// Stricter: require the bank code to be a known SPEI participant
ValidationResult strict = service.ValidateWithBankCheck("001180012345678900");
// strict.ErrorCode == ClabeValidationError.ERR_BANK_CODE_UNKNOWN

Keeping the bank catalog current

The default ClabeValidationService() uses a bundled snapshot (BankCatalog.EmbeddedDefault). To use fresher data, build a catalog from a list you fetch/sync (e.g. from Banxico) and inject it:

IBankCatalog catalog = new BankCatalog(freshInstitutions, snapshotInfo);
var service = new ClabeValidationService(catalog);

Refreshing the embedded snapshot

tools/update-bank-catalog.fsx regenerates the bundled snapshot from Banxico's live participant list. It maps each 5-digit SPEI code to its 3-digit CLABE code, merges with the existing file (retaining historical codes such as 032/IXE that current-participant lists drop), and is fail-safe — it aborts without writing if the response can't be parsed into a plausible catalog.

dotnet fsi tools/update-bank-catalog.fsx --dry-run   # preview added/renamed/retained
dotnet fsi tools/update-bank-catalog.fsx             # write the snapshot

Refreshing may update bank names to Banxico's current forms (e.g. "BBVA BANCOMER" → "BBVA MEXICO"); tests assert names against a fixed catalog, not the shipped snapshot, so a refresh won't break the build.

swiftBics entries are curated by hand (Banxico's list carries no BIC data) and are preserved as-is by the refresh script. Each entry is { "bic": "…" } with an optional "city" for branch-qualified codes; the entry without a city is the head office. When adding one, verify it against an authoritative SWIFT directory first — a wrong BIC misroutes payments.

SWIFT/BIC data is best-effort, not absolute truth

BICs change in the real world: banks merge (Interacciones → Banorte), split (Banamex separating from Citi), rename (Bansefi → Banco del Bienestar), and deactivate codes — and public directories lag those events by months or years. The bundled entries were verified against at least two independent SWIFT directories at curation time (see git history for dates and sources), and the major banks additionally against SWIFT's published SCORE participant list, but none of that makes them a live registry:

  • Treat a resolved BIC as a strong default, not a guarantee. For flows where a misroute is costly, confirm against a SWIFTRef subscription or the beneficiary's bank.
  • An empty swiftBics means "no BIC verified", which usually — but not provably — means the institution has no SWIFT membership.
  • Corrections welcome: update the data file with two independent sources cited in the commit message.

Dependency Injection

services.AddSingleton<IBankCatalog>(_ => BankCatalog.EmbeddedDefault);
services.AddScoped<IClabeValidationService, ClabeValidationService>();

Requirements

  • .NET 8.0 or later
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 1,057 8/5/2026
1.0.0 1,718 7/1/2026