There is one thesis in this post: the validation layer of the physical world is free, public, and legally yours to implement — and the answer layer above it never was. Everything about how barcoding.dev is shaped falls out of that split.
If you ship supply-chain software, you have probably rebuilt some of the validation layer yourself: a mod-10 routine here, a VIN transliteration table there, a prefix list somebody pasted into a constants file in 2019 and nobody has audited since. The algorithms were never the hard part. The hard part is that they live in your codebase as folklore — untested against the normative text, unpinned to any source, drifting one hotfix at a time.
So let's do the two most common ones against the primary sources, in full, and then talk about the layer that is actually scarce.
The VIN check digit, from the Code of Federal Regulations
The VIN check digit is not a vendor convention. It is United States public regulation: 49 CFR 565.15 publishes the complete algorithm — the transliteration table, the weight table, the modulus. A worked example, using the well-known test VIN 1M8GDM9AXKP042788:
Transliterate the letters (A=1, B=2, … skipping I, O, Q; the digits stand for themselves), multiply each of the 17 positions by its assigned weight — 8 7 6 5 4 3 2 10 0 9 8 7 6 5 4 3 2 — and sum:
pos char value weight product
1 1 1 8 8
2 M 4 7 28
3 8 8 6 48
4 G 7 5 35
5 D 4 4 16
6 M 4 3 12
7 9 9 2 18
8 A 1 10 10
9 X — 0 0 (position 9 IS the check digit)
10 K 2 9 18
11 P 7 8 56
12 0 0 7 0
13 4 4 6 24
14 2 2 5 10
15 7 7 4 28
16 8 8 3 24
17 8 8 2 16
sum = 351
351 mod 11 = 10, and the regulation says a remainder of 10 is written X. Position 9 of the VIN is X. The VIN validates. That arithmetic is exactly what barcoding verify runs — pure, local, no network, no account — and when a VIN fails, the typed error names the expected position-9 character instead of shrugging.
The EAN-13 check digit, from the GS1 General Specifications
GS1's mod-10 is equally public: the full General Specifications text is openly served by GS1's reference platform, royalty-free to implement under the GS1 IP Policy. For the EAN-13 4006381333931: weight the first twelve digits alternately 1 and 3, left to right:
4·1 + 0·3 + 0·1 + 6·3 + 3·1 + 8·3 + 1·1 + 3·3 + 3·1 + 3·3 + 9·1 + 3·3
= 4 + 0 + 0 + 18 + 3 + 24 + 1 + 9 + 3 + 9 + 9 + 9
= 89
Check digit = (10 − 89 mod 10) mod 10 = 1. The thirteenth digit is 1. It validates.
The same story holds across the registry: the ISBN algorithm is in a free official manual (and an ISBN-13 is a valid GTIN-13 — the 978/979 prefixes route to book enrichment); the FDA's UDI formats document specifies all three issuing agencies' grammars; USPS Pub 199 publishes the IMpb MOD10 with a worked example. Public regulation and royalty-free standards, end to end.
So why did every barcode API feel like a dead end?
Because validation was never what you were paying for — you were paying for the answer layer, and the answer layer has four failure modes:
- Walled. The syndication networks sell relationships, not lookups; there is no "attributes for arbitrary GTIN X" endpoint anywhere in that segment, because an open lookup would cannibalize the network model.
- Dead. The one first-party single-API enrichment family from a major scanner vendor was discontinued at the end of 2023, orphaning the exact demand it proved.
- Shallow. The official verification rail returns seven attributes. Authoritative, and structurally not enrichment.
- Unlicensed. The aggregator tier forbids, in its own terms of service, exactly what an enrichment API is made of: storing, caching, and redistributing. Data you cannot legally keep is not a foundation.
barcoding.dev takes the split seriously in both directions. The validation layer ships the way it deserved to all along: resolve, verify and generate are pure, local verbs over sha256-pinned normative artifacts — the AI table, the prefix ranges, the check-digit vectors, the Digital Link grammar — where a pin changes only by journaled human ruling, never by silent drift. Your parser stops being folklore and starts being a dependency with provenance.
And the answer layer is rebuilt only on rails whose licenses actually permit it — USDA FoodData Central (CC0), openFDA (CC0), NHTSA vPIC (public domain), the Open Facts family (ODbL, held as a segregated source layer) — with every attribute carrying its source, license class, and fetch time. Deep and clean in four verticals; identity-grade on every GTIN on earth; and the licensed long tail named as licensed instead of scraped around.
Why this lands on the ISV's desk
If you are the staff engineer who owns the parsing layer of a supply-chain product, the build-versus-buy arithmetic here is the same one epcis.dev makes for the event layer: the first implementation is a sprint, the maintenance tax is forever. Prefix range tables move. Digital Link grammar versions ratify. A source's license text changes without a diff notification. Embedding the layer that tracks all of that — and being able to print its pins with one verb — is the whole offer.
The check digits above you can verify with a pencil. That is the point: every claim on this site is supposed to sit one step from arithmetic you can re-run. When a scan needs to become an event — GTIN plus lot plus serial, written down with an attested observer — that is the next post in the arc, and the join to epcis.dev and transactions.dev is where the family stops being three sites and starts being one record.
Keys open the network half of the verb set. Get an API key — say what arrives at your door, and the provisioning order follows the list.
We answer in writing. We take at most five conversations a month, only when you ask for one, and only after you already have the written read.