One thesis: decoding is commoditized — every capture device class in your estate emits the same payload bytes — so the question that decides your architecture is no longer "can it read the code" but "what happens the millisecond after the decode," and that layer is the one nobody sold you with the hardware.
If you own restaurant technology for a multi-unit brand, you own the handhelds, the store systems, and — by inheritance — every integration between them. You have also probably noticed that scanner procurement conversations are still about decode rates while your actual pain is downstream: the beep happens, and then what? Which system receives it, what does it mean, and why does every supplier feed answer differently?
The capability matrix
| Capture class | Reliably decodes | What it emits |
|---|---|---|
| Dedicated scanners (lane, handheld) | the full symbology set — 1D families, QR, DataMatrix, PDF417 | payload bytes, usually prefixed with an AIM symbology identifier; FNC1 preserved per firmware config |
| Phone native camera app | QR (opens URLs); DataMatrix is not a consumer behavior | a URL launched, or raw text shown to a shrugging user |
| Phone vendor SDK / OS frameworks | 1D families, QR, DataMatrix, PDF417 on-device | payload + symbology, structured, no network needed |
| Browser tab | platform-dependent native detection — full on some mobile browsers, partial to absent elsewhere — with a WASM decoder as the dependable fallback | payload + symbology into your web app |
| Fixed cameras (shelf, dock) | vendor-tuned symbology sets | payload streams tied to camera position |
Read the matrix vertically and the commoditization thesis falls out: the same GS1 element string — say (01) GTIN, (10) lot, (17) expiry off a supplier case — arrives byte-identical from a lane gun, a phone SDK, and a browser tab. Feed all three captures to resolve and you get one canonical identity, one AI map, three times. The pipe stopped being the differentiator years ago; open-source decoders and OS frameworks closed the gap for every code your stores will meet at arm's length.
Two rows carry caveats worth keeping precisely. The phone-camera row is the consumer-claims discipline in miniature: native camera apps decode QR and open URLs; GS1 DataMatrix is a professional-scanner symbology, and any plan assuming guests scan DataMatrix is a plan assuming behavior that does not exist. And the browser row is real but uneven — native browser detection is dependable on some mobile platforms and missing on others, which is why a serious web scan path ships a WASM decoder and treats the native API as an opportunistic accelerator.
The payload contract your integrations actually depend on
What the device hands your software is bytes with conventions, and the conventions are where integrations rot. The AIM symbology identifier — a three-character prefix like ]C1 for GS1-128, ]d2 for GS1 DataMatrix, ]Q3 for GS1-mode QR — tells the receiving system what grammar to parse, and firmware configuration decides whether it is transmitted at all. FNC1 separators inside GS1 payloads arrive as GS control characters that middleware routinely strips or mangles. Keyboard-wedge modes helpfully "type" the payload and destroy the non-printing characters your parser needed. Every one of those failure modes is invisible at the demo and expensive at store five hundred.
The architectural answer is to stop letting each integration reinterpret bytes: one resolution layer, fed raw payloads from every device class, returning one canonical form. resolve is that layer, pure and local — payload in (with symbology identifier hints when present), scheme detection, AI parse, canonical identity out, typed errors when the payload is mangled rather than a silent wrong answer. Classifying the payload from its first bytes is a deterministic exercise, and it is the same exercise for the lane gun and the browser.
Where the answer layer went missing
Here is the market fact under your integration pain: the capture industry sells decodes, and the one first-party attempt to sell the answer — a single API turning any scanned identifier into enriched data — was retired by its vendor in late 2023, leaving the installed base of professional scanners with no first-party answer to "what did I just scan?" The capture SDK vendors monetize the decode and the shelf camera vendors monetize their own imagery; the question the scan exists to ask — what is this, is it real, whose is it — still requires someone else's data layer. Your handhelds are proof: you already bought readers that decode everything; nothing that came in the box says what anything is.
That is the layer this property exists to be: after the beep, resolve names the thing (pure, local, every scheme), enrich answers from license-clean rails with per-attribute provenance, and the scan that matters becomes an event — because a serialized 2D case scan at receiving carries enough structure to be a supply-chain event, and the moment you write it down, the question of who received it arrives. The record shows a case arrived at a store; it should show who took custody. That event-side story, payload by payload, is one scan, three layers — and the executive framing of the whole estate question ("you already bought the readers — where does the record live?") is visibility.cloud's brief, in the light register.
What to do with the estate you already own
No hardware decision is required to start. The readers you have emit payloads resolve consumes today, and the browser scan path — camera to decode to resolve to enriched card, every step inspectable — runs behind the same verbs; get an API key and say what your stores scan, and provisioning follows the list. The strategic move is smaller than a rollout and bigger than a pilot: route every decode in one store through one resolution layer and count how many of your per-supplier integration quirks were never supplier problems at all — just bytes nobody canonicalized.
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.