GS1 · VIN · ISBN · UDI · NDC · SSCC — and everything in your building that carries no barcode at all

Scan it. Name it.
Prove where the answer came from.

barcoding.dev answers the question every scanner asks and no neutral API answers — what is this, and how do you know? — and the harder one standing behind it: what do you scan when the thing has no barcode? Reading a mark and giving a mark to something that never had one are the same door, and this is it. Everything below is a real encoding of real bytes, drawn to scale and decoded in the build that published it.

UPC · GS1 DataMatrix · Digital Link · PDF417 — the same grid, drawn to scale

Twelve digits, then everything else.

A UPC holds a class of product and nothing more — thirteen digits, 95 modules, no room for the lot, the expiry or the serial. Everything to its right is a real encoding of real bytes, drawn at the same module pitch, decoded in the build that published it.

01 EAN-13 9521234567899 13 B · 95 modules 37.3 mm at X = 0.33 decoded  byte-exact  PASS A class of product, not an item. 95 modules wide, and the height carries nothing.

the complete payload, exactly as it was handed to the encoder

9521234567899
build gate · round-trip
encoded   13 B → 95 modules
decoded   zxing-cpp (zxing-wasm 3.1.2) → 13 B
compare   byte-exact  PASS
02 GS1 DataMatrix (01)09521234567899(10)L26A0417…[+18 B elided]…212300047719 60 B · 22 × 22 modules 6.0 mm at X = 0.25 decoded  byte-exact  PASS Four fields — GTIN, lot, expiry, serial. The same four in GS1-128 is 431 modules: 223.2 mm at GS1's general-distribution minimum. Or a 6.0 mm square.

the same four fields, at the same module pitch

GS1-128 · 431 modules · 223.2 mm at X = 0.495 GS1 QR · v3 · 29 × 29 · 12.2 mm at X = 0.33

Capacity grows while the mark shrinks. The GS1-128 above is the site's own encoder, drawn at one pixel per module because it does not fit the ladder's pitch on any screen.

the complete payload, exactly as it was handed to the encoder

(01)09521234567899(10)L26A0417(17)271231(21)SN95212300047719
build gate · round-trip
encoded   60 B → 22 × 22 modules
decoded   zxing-cpp (zxing-wasm 3.1.2) → 60 B
compare   byte-exact  PASS
03 QR · Digital Link https://barcoding.dev/01/09521…[+39 B elided]…19?17=271231 81 B · v5 · 37 × 37 modules 14.9 mm at X = 0.33 decoded  byte-exact  PASS The same identity as an address. It resolves; it also reads with nothing behind it.

the complete payload, exactly as it was handed to the encoder

https://barcoding.dev/01/09521234567899/10/L26A0417/21/SN95212300047719?17=271231
build gate · round-trip
encoded   81 B → 37 × 37 modules, QR v5, ECC M
decoded   zxing-cpp (zxing-wasm 3.1.2) → 81 B
compare   byte-exact  PASS
04 PDF417 @  ANSI 000000100001DL0031025…[+248 B elided]…CUNONE DDAF 290 B · 239 × 57 modules 46.2 mm at X = 0.19 decoded  byte-exact  PASS Hundreds of millions of people carry one of these. The card's printed face is a rendering of exactly these fields — and at 290 bytes it is already 1.5× wider than the square beside it carrying 595.

the complete payload, exactly as it was handed to the encoder

@

ANSI 000000100001DL00310259DLDCAC
DCBNONE
DCDNONE
DBA20311231
DCSSPECIMEN
DACPATTERN
DADNONE
DBD20260804
DBB19900417
DBC1
DAYBRO
DAU070 IN
DAG1400 DEPOT RD
DAILA VERGNE
DAJTN
DAK370860000
DAQS952123000477
DCFSPECIMEN952123000477
DCGUSA
DCK952123000477190001
DDEN
DDFN
DDGN
DCUNONE
DDAF
build gate · round-trip
encoded   290 B → 239 × 57 modules
decoded   zxing-cpp (zxing-wasm 3.1.2) → 290 B
compare   byte-exact  PASS

The payload is invented and shaped like an AAMVA record; it is not anyone's licence and this platform stores no licence data — parse, verify, never store.

05 QR · Digital Link on an SSCC https://barcoding.dev/00/00952…[+553 B elided]…1800.PREPAID 595 B · v17 · 85 × 85 modules 30.7 mm at X = 0.33 decoded  byte-exact  PASS The document's own fields, in the query string of its own address. No network, no resolver, no account.

the complete payload, exactly as it was handed to the encoder

https://barcoding.dev/00/009521230000000019?402=95212300000000093&401=GINC-95212-260804-0093&400=PO-4471-0093&403=LTL-DIRECT.DOCK-14&410=0952123000019&411=0952123000026&412=0952123000033&413=0952123000040&414=0952123000057&415=0952123000064&417=0952123000071&420=37086&422=840&30=18&37=1440&3302=009435&3922=1875500&8008=260804140000&7003=2608061800&90=SCAC.NRFC-CLASS.85-NMFC.156600&91=SHIPFROM.NORTHRIDGE-FOODS-CO.1400-DEPOT-RD.LA-VERGNE.TN.37086.US&92=SHIPTO.CENTRAL-GROCERS-DC-14.220-INTERMODAL-PKWY.LA-VERGNE.TN.37086.US&93=TRAILER.NRFC-48221.SEAL.0951447.APPT.2608041400-2608041800.PREPAID
build gate · round-trip
encoded   595 B → 85 × 85 modules, QR v17, ECC M
decoded   zxing-cpp (zxing-wasm 3.1.2) → 595 B
compare   byte-exact  PASS

A valid GS1 Digital Link on an SSCC primary key: it resolves at https://barcoding.dev/00/009521230000000019 when there is a network, and it reads with nothing behind it when there is not.

ratified barcode typespiloted; not an approved barcode type

the scan line is applied from outside and is part of no barthe run is cropped by the frame on both sides — the shelf never ends

the climb — the same header, plus line items at a measured 32 B each

0 line items 595 B · v17 · 85 × 85 30.7 mm at X = 0.33 decoded  byte-exact  PASS
8 line items 851 B · v22 · 105 × 105 37.3 mm at X = 0.33 decoded  byte-exact  PASS
12 line items 979 B · v23 · 109 × 109 38.6 mm at X = 0.33 decoded  byte-exact  PASS

Three symbols, not one that animates: a symbol must arrive whole and be scannable whenever it is visible. Error correction is M on every symbol on this page. The same 595-byte header at the other three levels: L v15 (77) · M v17 (85) · Q v21 (101) · H v24 (113).

This is where it stops. 12 line items is 979 bytes. The build keeps adding line items until the encoder refuses, and prints the wall it hits: 66 line items — 2707 bytes, QR v40 at error correction M. The label programs that actually run in production stop far below it. The mark carries the document's fields; it was never going to carry the page. This site's own Archivo subset is 54,336 bytes — 20 times everything a QR code can hold at this error-correction level.

What this is, said plainly: ratified GS1 Application Identifiers, in a Digital Link URI's query string exactly where the URI syntax puts data attributes. A plain QR carrying that URI is not one of the barcode types the General Specifications approve for this job. We show it because it works, and we say what it is.

19 of these fields are ratified GS1 Application Identifiers with a public meaning any conformant reader already knows — the shipment number, the seven party GLNs, the weights, the counts, the dates. The 4 that carry the party names, the addresses and the trailer are AIs 90–94, mutually agreed information: real Application Identifiers, but their meaning is agreed between two parties, not defined by the standard. GS1 has ratified party-and-address AIs in the 4300 range; this property's pinned AI table is a GenSpecs 26.0 subset that does not yet include them, so we do not claim them.

The same 595-byte header in PDF417, in specification and decoding, is a stripe: 579 modules × 12 rows — 145.8 mm × 9.0 mm at X = 0.25 — or 60.8 mm × 26.3 mm at 10 columns. The comparison is shape, not failure.

Every barcode above was encoded from the exact bytes printed beneath it and decoded back through zxing-cpp before this page was allowed to ship. The machine form of this figure, with every measurement: /demo/ladder.json.

Then: what is it, and how do you know?

resolve and verify run pure and local on every identifier family — no network, no account, no key. enrich is not built yet (P0-2); when it answers it will draw on license-clean rails only, and every attribute will ship inside a provenance envelope: source, license class, fetch time, digest. No bare value anywhere in the API is the rule the live verbs already keep.

barcoding resolve '(01)09506000134352(17)261231(10)ABC123(21)1234'

scheme      gs1.element-string
gtin        09506000134352            check: mod10 pass
ai.17       2026-12-31 (expiry)
ai.10       ABC123 (lot)
ai.21       1234 (serial)
identity    sgtin: urn:epc:id:sgtin:9506000.013435.1234
digital-link https://barcoding.dev/01/09506000134352/21/1234

One parser for both 2D label forms — GS1 element strings and Digital Link URIs — normalized to the same canonical identity and AI map. The same run works on a VIN, an ISBN, a UDI, an SSCC, a tracking number.

fork the scan

From December 2027 the register reads the whole square — and keeps only the part it already had.

GS1's Sunrise 2027 programme expects retail point of sale to read and process 2D barcodes by the end of December 2027, extracting the GTIN. That is the whole obligation. It is cited here as GS1's programme, on GS1's timeline, and never as our forecast — the six things it is routinely claimed to require, each against its primary source, are stated exactly on the blog.

Here is the part nobody budgets. When a brand encodes lot, expiry and serial, all of it arrives in the same square, on the same scan, at the same instant — and this is not hypothetical: every US prescription-drug package already carries exactly that under DSCSA, which is a rollout that already happened rather than a forecast. The register takes the GTIN for the price lookup, because that is the number it has always had, and drops the rest on the floor. That is not a bug in anybody's till: a sale record is item, price, basket. It has nowhere to put this crate, from this batch, received at this door, sold at this lane at 4:52pm.

So fork it. The GTIN goes to the register exactly as it does today, untouched, on the same path. Lot, expiry and serial go out the other side of the fork, as named fields, to something built to hold them.

Nothing at the lane changes. No new step for a cashier. No new hardware — an imager that clears the December 2027 date already reads the whole square; keeping the rest of what it read is a software decision, not a capital one. The scan is already happening, the data is already in the read, and the ask is not to throw it away.

Where the fork runs, and where it stops.

Said on the page rather than discovered in an invoice, because a fork that quietly grows into a platform is how these programmes die.

This door's half is the split, and it is deliberately small. Read the square, split what it said, hand the GTIN out one side unchanged, and hand lot, expiry and serial out the other as named fields with the check verdict computed from the digits alone. That is decode, resolve and verify — pure, local, no key, no account, no network call. It is a split, not a system.

The other side of the fork is not this door's, and this page will not pretend otherwise. What happened, where, and who did it becomes an event at epcis.dev. Rolling it up across lanes, stores, docks and suppliers — and getting it back out as tables you own — is visibility.cloud. barcoding.dev holds no history at all: no query, no trace, alone among the family's doors. Your own history is queried and traced there, never here.

The explainer arc runs on the blog: barcodes → Sunrise 2027 → what a 2D mark means for the record layer → what a scan can and cannot say on its own. Start the arc →

The closed verb set.

Eight verbs answer today. --json on every verb; typed errors on stderr; exit codes 0 ok / 1 negative domain verdict / 2 usage. The same engine behind npx barcoding.dev and the hosted doors on this origin — four of them are listed as MCP tools — resolve, verify, generate, pins — all readOnlyHint: true; the rest are reachable on the CLI door only.

That number is not typed into this page. It is counted, at build time, out of the shipped verb table the CLI and the MCP door are both generated from, and the build refuses to publish if this table and that table disagree.

They come in four movements, and the order is the argument: read a mark, draw a mark, create an identifier for a thing that has none, and say what it means. The third one is the half of this door that has nothing to do with retail, and it is the next section.

verbwhat it doesnetworkexit-1 verdict
decodea frame or a photo → what the mark actually says. Runs on the hosted door and, unchanged, in the browser at /scan — frames are decoded in memory and discarded, never stored, never loggedpure · localnothing decodable in the frame
resolveany identifier-bearing string — what a scanner read, bare GTIN-8/12/13/14, EPC URN, GS1 element string, GS1 Digital Link URI, VIN, ISBN, SSCC, tracking number — to canonical identity: scheme, canonical form, parsed AIs and fieldspure · localunrecognized / unparseable
verifycheck digit + structure + prefix legitimacy (GS1 prefix ranges → issuing MO; WMI → manufacturer; ISBN group), from pinned tablespure · localfails validation
generatethe write-side twin of resolve: id + AI map → element string, Digital Link URI, rendered symbol (QR / DataMatrix / GS1-128 / ITF-14). resolve(generate(x)) === x is the round-trip lawpure · localunencodable input
serializenothing → one serial, derived from the request with no stored counter, on a GS1 AI(21)-safe alphabet. Free and transparent: the response states, in the response, exactly what the serial disclosespure · local
pinsprint the pinned artifact and data-source-manifest digestspure · local
versionpackage, engine-core and pin-set versionspure · local
mcpthe agent door on stdio: the tarball's verbs as MCP tools, generated from the same table, readOnly-hinted

And five that do not.

The rest of the closed set is designed and not built. It is listed here, in its own table, in the future tense, each row naming the blocker that has to close — because a design listed beside a working verb with nothing to tell them apart is the way this page was wrong until 2026-08-05.

Every row below returned 404 · no door at that path from a terminal on 2026-08-05, and none of them is in the tarball. The build asserts both.

verbwhat it will dobuild state
labela template + the fields it accepts → a print-ready artifact: PNG, SVG, PDF and ZPL. The meter will be the template, never the call — open templates keep the free loop completable; the curated library and the regulated packs are the thing that is boughtnot built · P0-29
enrichcanonical id → attributes, every attribute inside the provenance envelope: source, license class, fetched-at, source digestnot built · P0-2
bridgeSKU / ASIN / vendor code / free text → GTIN candidates with confidence, plus the evidence for each candidatenot built · P0-3
hierarchyGTIN → packaging-level graph (each / inner / case / pallet); inference always labelled as inferencenot built · P0-3
partyGLN / GS1 company prefix → party: licensee name, issuing MO, address grain where licensednot built · P0-3

The other half: the thing that has no barcode.

Every argument about barcodes assumes there is one. Walk the building and most of what moves has no identifier at all — totes, bins, returnable crates, a pallet built forty minutes ago, a fixed asset, a dock door, a rack position, a form that exists only as a PDF. They are counted from memory and reconciled by argument, and no amount of retail standards work touches them.

serialize gives one of them a number, and it needs nobody's permission — no licence to buy, no membership to join, no vendor to schedule, no key, no account. That is why this is the act that comes first for assets, locations and returnables, and it is why it is free. One curl, and the number is yours.

The identifier is derived from the request, not handed out by a counter, so there is no range to run out of and nothing to reserve. Reserved ranges and serials that reveal nothing are a different, paid class — and the difference is stated here rather than discovered later.

Getting that number onto a printed tag is not yet this door's. Templates and print-ready output — PNG, SVG, PDF and ZPL for the printers you already own — are designed, gated on P0-29, and will ship as the label verb in the table above. Until they do, nothing here renders a tag, and this section stands on the call that is live.

$ curl -sX POST https://api.barcoding.dev/serialize

{ "serial": "Gs21hefO3IX74Lfk",
  "profile": "T1 compact",
  "alphabet": "tsp-1",
  "decodes_to": { "issued_at": "2026-08-05T11:12:52.000Z",
                  "entropy_bits": 48 },
  "discloses": [ "issuance time (1 s precision)" ],
  "honesty": "This serial decodes publicly to: issuance time
     (1 s precision). A collection of our serials therefore
     reveals issuance volume and cadence, business hours and
     timezone. That is the disclosed cost of free + stateless
     + transparent. If serials must reveal nothing, that is
     the opaque class." }

A real response from that address, run on 2026‑08‑05. The disclosure is a field in the response, not a line in a policy page — a free serial anyone can take apart is legible to anyone, including whoever is counting yours, and the honest place to say so is where the serial is handed over. No key, no account.

The provenance envelope.

Per attribute, not per record — because real records are mosaics: nutrition may be public-domain USDA while the category is ODbL Open Facts. The license class travels with the value, so a downstream agent can filter by what it is allowed to do with each field.

{
  "attribute": "servingSize",
  "value": "30 g",
  "source": {
    "id": "usda-fdc",
    "record": "https://fdc.nal.usda.gov/…",
    "dataset_version": "FDC 2026-04 full download",
    "digest": "sha256:…"
  },
  "license": "public-domain",
  "fetched_at": "2026-07-31T18:20:11Z",
  "confidence": 1.0
}

The license enum is closed — public-domain · open-attribution · share-alike-odbl · gs1-licensed-display-only · commercial-restricted — and enforced at assembly time, not disclaimed in a footer.

The barcode registry. GS1 is the largest family in it, not the boundary.

One pinned registry file per identifier family: grammar, check-digit algorithm, canonicalization, barcode-type bindings, enrichment sources with license class, and the join rule into events and transactions where one exists. AccessGUDID proved the pattern at government scale — one endpoint, three issuing agencies' grammars; this registry generalizes it.

schemevalidation railenrichment raillicense class
GTIN / GLN / SSCCGS1 GenSpecs mod-10, prefix rangesfood: USDA FDC (CC0) + Open Facts (ODbL, segregated)public-domain · share-alike-odbl
VIN49 CFR 565.15 — transliteration, weights, mod-11NHTSA vPIC (public domain); auto.dev as the owned railpublic-domain · first-party
UDI (GS1 / HIBCC / ICCBBA)FDA UDI formats docAccessGUDID / openFDA (CC0; GMDN fields stripped)public-domain
NDCstructural (no check digit)openFDA drug/ndc, updated daily (CC0)public-domain
ISBN (978/979 — a valid GTIN-13)free ISBN Users' Manualrouted to book enrichmentopen · confirm-before-redistribution
USPS IMpbPub 199 MOD10, worked example publicidentity open; tracking status per-calleridentity: open · status: per-caller
DL/ID PDF417 (AAMVA)parse and verify ONLYnone — statutoryno_retention, hard flag

Seven laws, not seven features.

The parts that cannot be renegotiated later. The incumbents in this category were walled, dead, shallow, or unlicensed; every law below is the structural answer to one of those four failure modes.

  1. 01
    No bare value anywhere.

    The live verbs keep this already: a resolve answer states computed from the digits · nothing was looked up rather than handing back a bare string. It is also the law enrich is being built to (not built yet — P0-2): every attribute it returns will travel inside a provenance envelope — source, license class, fetched-at, source digest — the license class a closed enum, enforced rather than descriptive, so a response assembled for storage cannot contain display-only attributes.

  2. 02
    Identity is free. It stays free.

    resolve, verify and generate are pure and local — no network, no account, no key. The validation layer of the physical world is public regulation and royalty-free standards, and this door keeps it that way.

  3. 03
    License-clean rails only.

    The enrichment corpus is built exclusively on rails whose licenses permit it: USDA FoodData Central (CC0), openFDA (CC0), NHTSA vPIC (public domain), the Open Facts family (ODbL, as a segregated source layer). No scraped aggregator, ever — their upstream rights are unverifiable and their downstream rights are contractually zero.

  4. 04
    Sources are pinned like schemas.

    Each source has a manifest recording the license text URL, retrieval date and the sha256 of the license text itself — an upstream license change is a failed pin, not a silent drift. pins prints the digests.

  5. 05
    Conformant to the standard; explicit about everything beyond it.

    For GS1 keys the /01/* door serves the GS1-Conformant Resolver 1.2.0 surface — RFC 9264 linksets, the description file at /.well-known/gs1resolver — and it is a delegating door: resolution itself is id.org.ai's, served here. For every other identifier family it is the same contract extended, and labeled as such.

  6. 06
    One door for people and for agents.

    The same closed verb set over MCP; resolve and verify ship readOnlyHint: true with complete tool descriptions, so an agent's first value moment fires inside already-granted authority. Refusals are honest tool errors, never fabricated answers.

  7. 07
    Joined, not adjacent.

    A serialized 2D scan constructs a valid EPCIS 2.0 ObjectEvent, validated against epcis.dev's pinned schema before it leaves the function; its bizTransactionList carries the PO/ASN context via transactions.dev; the attested observer rides in id.org.ai terms. Identity → event → transaction, one scan wide.

What enrich will be, stated plainly.

It is not built — P0-2, and it returned 404 on 2026-08-05. The identity half beneath it is: resolve, verify and generate work on every GTIN on earth today, because the standards layer is royalty-free and the check-digit universe is public regulation. What is being designed on top is deep and clean in four verticals — food, medical devices, drugs, vehicles — and identity-grade everywhere.

It will not be a 500-million-row general-merchandise lookup. The general-merchandise long tail is licensed territory — display-scoped and membership-gated — and this API names it as such rather than papering over it with scraped data. That is the shape of the thing: serve what is free and clear by construction, mark what is gated as gated. The live verbs are already built that way, and this page's own gated table is that rule applied to itself.

The two flagship chains: UPC → nutrition facts on wholly public rails, and VIN → vehicle, with live listing chain on the family's own auto.dev. One per family; both worked examples on the blog.

Before you believe any of it, go check one thing.

The record layer the other side of the fork lands in is EPCIS 2.0 — GS1's, published, free to read, and worth ten minutes of anybody's afternoon. It defines what, when, where, why and how. It carries no dimension for the person or the agent who did it; a company appears, as a party running a step, and the individual does not.

Whether that gap matters to your week is entirely your call, and plenty of readers will decide it does not. The point is that you can settle it without asking us anything — and a claim you can close by reading a public specification is worth more than one we assert here.

Then close the other half the same way. translate, validate and hash answer at epcis.dev with no key and no account: XML in, conformant JSON out; a document validated against the pinned official 2.0.1 schema with its sha256 printed in the response; the CBV 2.0 §8.9 event hash. Three curls, no signup, and the answer is the artifact rather than our description of it.

Verified from a terminal on 2026‑08‑05: POST epcis.dev/hash returned a ni:///sha-256;…?ver=CBV2.0 hash; POST epcis.dev/validate returned valid: true against epcis-json-schema.json 2.0.1, sha256 0f46ff69…; POST epcis.dev/translate turned an EPCIS 2.0 XML document into its JSON-LD twin, and refused a JSON body with a typed 415 naming the two media types it takes.

Get an API key.

You do not need one to start. decode, resolve, verify, generate and serialize are pure and local — no key, no account, and the fork above runs entirely inside them. A key will open the network half — enrich, bridge, hierarchy and party — and that half is not built: it is the gated table above, and every one of those four returned 404 on 2026-08-05. Everything this door can do today, it does without a key.

Say what arrives at your door and we email you when your key is ready. Agents are first-class here: read the offer, take a key, run the free half, no human in the loop.

Access is provisioned from this list. We use your address to tell you when yours is ready and to follow up about it; you can tell us to stop at any time. We don’t sell it or hand it to advertisers. If we stop working on this, we say so rather than go quiet.