Liking cljdoc? Tell your friends :D

stdnum-clj

Unified validation, parsing, and formatting of standard identifier numbers for Clojure - credit cards, IBAN/BIC, ISBN, ISSN, ISIN, US bank routing (ABA), IMEI, and the raw Luhn check, behind one small API.

Stack

Clojure Apache Commons Validator iban4j

Clojars Project cljdoc

Unofficial, community-maintained. Not affiliated with Apache, iban4j, or any card network.

Why

Clojure has plenty of one-identifier libraries (an IBAN parser here, a Luhn checker there), most of them tiny and unmaintained, each with its own API. There was no single library that validates the common, checksummable identifiers under one consistent interface - the way Python's python-stdnum does. stdnum-clj is that facade. It does not reimplement the algorithms: it wraps the maintained Apache Commons Validator and iban4j engines, so the checks are as correct as those libraries and stay correct as they're updated.

Install

Leiningen / Boot:

[net.clojars.savya/stdnum-clj "0.1.0"]

deps.edn:

net.clojars.savya/stdnum-clj {:mvn/version "0.1.0"}

Usage

(require '[stdnum.core :as stdnum])

;; valid? - dispatch on an identifier-type keyword
(stdnum/valid? :iban "GB82 WEST 1234 5698 7654 32")  ;=> true
(stdnum/valid? :credit-card "4111 1111 1111 1111")   ;=> true (spaces/hyphens tolerated)
(stdnum/valid? :isbn "978-0-306-40615-7")            ;=> true
(stdnum/valid? :iban "GB82 WEST 1234 5698 7654 33")  ;=> false (bad check digit)

;; parse - validity plus the useful extracted fields
(stdnum/parse :credit-card "378282246310005")
;=> {:valid? true, :network :amex}
(stdnum/parse :iban "GB82WEST12345698765432")
;=> {:valid? true, :country "GB", :bban "WEST12345698765432",
;    :formatted "GB82 WEST 1234 5698 7654 32"}
(stdnum/parse :isin "US0378331004")
;=> {:valid? false}

;; format - canonical human form (nil if invalid)
(stdnum/format :iban "GB82WEST12345698765432")  ;=> "GB82 WEST 1234 5698 7654 32"
(stdnum/format :credit-card "4111111111111111")  ;=> "4111 1111 1111 1111"

;; detect - which types consider this value valid
(stdnum/detect "4111111111111111")  ;=> [:credit-card :luhn]
(stdnum/detect "nonsense")          ;=> []

;; convenience
(stdnum/card-network "6011111111111117")  ;=> :discover
stdnum/types  ;=> #{:credit-card :iban :bic :isbn :issn :isin :aba :imei :luhn}

valid?, parse, and format throw IllegalArgumentException only on an unknown identifier type (a programming bug). Bad data never throws: valid? returns false, parse returns {:valid? false}, format returns nil.

Supported identifiers

TypeMeaningEngine
:credit-cardCard number + network (Visa/Mastercard/Amex/Discover/Diners)Commons Validator
:ibanInternational Bank Account Number (+ country/BBAN)iban4j
:bicBank Identifier Code (SWIFT)iban4j
:isbnISBN-10 and ISBN-13Commons Validator
:issnInternational Standard Serial NumberCommons Validator
:isinInternational Securities Identification NumberCommons Validator
:abaUS bank routing number (ABA)Commons Validator
:imeiMobile device IMEI (Luhn over 15 digits)Commons Validator
:luhnRaw Luhn (mod-10) checkCommons Validator

National identifier formats (per-country tax/VAT/company IDs, à la python-stdnum) are intentionally out of scope for this core artifact; they are a possible future companion.

License

Copyright (c) 2026 Savyasachi. Released under the Eclipse Public License 1.0.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close