blog · 2026-07-31 · written for: ED-4 — the self-principal integration-class agent (AC-2 × ED-4), whose value is a machine-readable result, not a narrative; B2A reference content

An ISBN is a GTIN: what Bookland means for a universal resolver

One thesis: ISBN-13 is a valid GTIN-13 under the 978 and 979 prefixes, so a resolver that handles books correctly is not a resolver with a books feature — it is a resolver whose scheme detection is registry data, and the ISBN row is the cleanest proof that detection is a table, not a heuristic.

If you are an integration agent reconciling a catalog, the practical question is never "is this a book?" — it is "what canonical identity does this string resolve to, and does the same identity come back no matter which form the source system stored?" Books are where source systems disagree most: a publisher feed carries ISBN-10, a retail feed carries the EAN-13 digits, a scanner emits the symbol payload. Three forms. One identity. Here is the whole mechanism.

Two check digits, both public

The grammar is free — the ISBN Users' Manual is published at no cost by the International ISBN Agency (isbn-international.org) — and the two algorithms take a minute each.

ISBN-10 uses mod-11 with descending weights 10…2. For 0-306-40615-2:

0·10 + 3·9 + 0·8 + 6·7 + 4·6 + 0·5 + 6·4 + 1·3 + 5·2
= 0 + 27 + 0 + 42 + 24 + 0 + 24 + 3 + 10 = 130
130 + check(2) = 132 = 12·11  →  ≡ 0 (mod 11)  →  valid

Mod-11 needs eleven symbols, which is why an ISBN-10 check digit can be X — the one place a letter appears in an otherwise numeric code.

ISBN-13 is not a new algorithm at all. Prefix the same core with 978, drop the old check digit, and compute the standard GS1 mod-10 — the identical arithmetic every EAN-13 on every grocery shelf uses. For 978-0-306-40615-?:

9·1 + 7·3 + 8·1 + 0·3 + 3·1 + 0·3 + 6·1 + 4·3 + 0·1 + 6·3 + 1·1 + 5·3 = 93
check = (10 − 93 mod 10) mod 10 = 7   →  9780306406157

That is the tell. The moment ISBN adopted the 978/979 "Bookland" prefixes, every ISBN-13 became a syntactically valid GTIN-13 — same length, same check digit, same symbol (EAN-13), same POS lanes. The book industry did not join the GTIN system as a guest; it is a prefix range inside it.

One identity, three forms

resolve is pure and local — no network, no account — and all three source forms land on the same canonical identity:

$ barcoding resolve 0306406152 --json
{"scheme":"isbn","carrier":"isbn-10","canonical":"9780306406157",
 "gtin13":"9780306406157","gtin14":"09780306406157","check":"mod11 pass"}

$ barcoding resolve 9780306406157 --json
{"scheme":"isbn","carrier":"isbn-13","canonical":"9780306406157","check":"mod10 pass", … }

$ barcoding resolve ']E09780306406157' --json
{"scheme":"isbn","carrier":"ean-13-symbol","canonical":"9780306406157","check":"mod10 pass", … }

Exit 0 all three times; byte-identical canonical all three times. The ISBN-10 path recomputed mod-11, converted, and recomputed mod-10; the symbol path stripped the AIM symbology identifier first. A diff across the three outputs is empty where it matters — which, for an integration agent, is the entire product.

Prefix routing is data, not code

The reason there is no "books mode" is that there is nothing modal about it. The scheme registry is one pinned file per scheme (schemes/*.json, digests printed by barcoding pins), and the ISBN row is a routing rule over the GTIN grammar:

{
  "scheme": "isbn",
  "detect": { "within": "gtin", "prefix": ["978", "979"] },
  "grammar": { "isbn10": "mod11-desc-weights", "isbn13": "gs1-mod10" },
  "canonical": "isbn13",
  "enrichment": [
    { "id": "open-library-dumps", "license": "open-intent-unstated" },
    { "id": "google-books", "license": "commercial-restricted", "note": "display-only" }
  ]
}

Detection reads: a GTIN-13 whose prefix is 978 or 979 is also an ISBN; route it to book enrichment; keep the GTIN identity. No regular-expression folklore, no if-ladder someone pasted in 2019. When ISBN International someday activates more of the 979 range, that is a pin change under a journaled human ruling — not a code deploy. Every other row in the registry works the same way; the ISBN row is just the one where the "detection is a table" claim is easiest to verify by hand, because you can check both algorithms with a pencil.

The enrichment column, stated honestly

Identity is free and clear; the answer layer above it is where licenses live, and the book vertical is a working lesson in per-source honesty:

  • Open Library publishes monthly bulk dumps (editions ~9.2 GB) and sanctions them for exactly this use — while its API terms prohibit use as "a bulk data backend or high-traffic commercial infrastructure." The dumps are the rail; the API is not. And the dumps pages state no explicit license — open intent, license unstated — so the registry row carries that class verbatim rather than rounding it up to "open."
  • Google Books is display-only by its branding terms (mandatory link-back, no reordering or altering results): structurally unusable as a cache backend, and labeled commercial-restricted accordingly.

So resolve on an ISBN answers today, locally, for free — and enrich on an ISBN routes through the same per-attribute provenance envelope as every other scheme, with the license class carried on each value so an agent can filter mechanically by what it is permitted to do. If your workload needs the book-enrichment rail at volume, tell us who you are — the identity half never waits on that; the licensed half is honest about being licensed.

What the row teaches

Every scheme in the registry is some remix of this row. UDI is three grammars behind one door. NDC is a GTIN embedding with no check digit of its own. VIN is a non-GS1 grammar published in federal regulation. The ISBN row is the smallest complete example: a foreign identifier that turns out to be a native one plus a prefix, two public algorithms, one canonical form, and an enrichment column that names its licenses instead of hiding them. The full generalization — one resolve, every scheme, one linkset contract — is the universal-resolver post, and the GTIN grammar this all rests on is /schemes/gtin. The ISBN page itself lives at /schemes/isbn.

Run the three-form check on any book within reach: npx barcoding.dev resolve on the number printed above the barcode, the number on the copyright page, and the scan itself. Same canonical, or it is a bug — ours, and typed on stderr.

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.