One thesis: packaging-level relationships come in exactly two kinds — licensed and inferred — and an API that returns a packaging graph without labeling which edges are which is manufacturing certainty it does not have; hierarchy types every edge with its source, and inference always says it is inferring.
If you integrate WMS feeds for a living, you already live this problem at the field level. The ecommerce-native WMS platforms carry real per-level identity — item UPC, package-unit UPC, pallet-unit UPC — which is the demand evidence in miniature: warehouses need the each/case/pallet graph so badly they modeled it into their item records. But nothing in those fields says how the levels relate, whether the case UPC is a licensed statement by the brand owner or somebody's data entry, or what a receiving scan of one level implies about the others. That relation is the graph hierarchy resolves — with the honesty bit carried per edge.
What the indicator digit does and does not promise
The GTIN-14's first digit — the indicator digit — is the standard's own gesture at packaging levels: a brand owner may allocate GTIN-14s sharing a base item reference with indicator values one through eight for different packaging configurations of the same trade item (nine is reserved for variable-measure). Two things follow, and they pull in opposite directions.
What it supports: seeing 10850012345677 and 00850012345673 share company prefix and item reference is real evidence of a family relationship, and an ITF-14 case mark carrying the indicator-1 form beside a consumer unit carrying the indicator-0 form strengthens it.
What it does not support: the indicator digit encodes no ordering and no quantity. Nothing in the standard says indicator 1 is "the case," says a case contains twelve eaches, or even guarantees the brand owner used shared item references across levels at all (allocating an unrelated GTIN per level is equally conformant). Any API that turns an indicator digit into "case of 12" silently has left the standard and started guessing.
The graph, with the guessing labeled
barcoding hierarchy 00850012345673 --json
{
"family": [
{ "gtin": "00850012345673", "level": "each" },
{ "gtin": "10850012345677", "level": "case" },
{ "gtin": "20850012345670", "level": "pallet-load" }
],
"edges": [
{ "parent": "10850012345677", "child": "00850012345673",
"quantity": null,
"source": "inference",
"basis": ["shared-prefix+item-ref", "indicator-digit", "itf14-case-mark"],
"confidence": 0.72 },
{ "parent": "20850012345670", "child": "10850012345677",
"quantity": 48,
"source": "gdsn-licensed",
"license": "gs1-licensed-display-only",
"confidence": 1.0 }
]
}
Read the two edges against each other; the contrast is the whole design. The inferred edge carries source: inference, names its basis, declines to invent a quantity, and states a confidence below one. The licensed edge — available only where GDSN standing exists for that brand relationship, because the network's terms make per-brand-owner consent the unit of redistribution — carries the authoritative quantity, the license class, and the enforcement consequences that class implies under the provenance envelope. Same graph shape, different epistemic status, and the difference rides in the payload instead of in a disclaimer nobody reads. Labeled inference is a design law here, not a hedge: the dishonest alternative is not "more data," it is fabricated certainty at exactly the join where receiving disputes get expensive.
The ASN case, where the grain bites
The place your team feels this weekly is the despatch advice. An ASN describes a shipment as nested levels — shipment, order, pack, item — and the packing structure it asserts has to reconcile with what the dock actually scans: an SSCC on the pallet, case marks underneath, eaches inside. When a client's ASN says cases of a GTIN and the dock scans eaches — or the WMS item file carries a package-level UPC the ASN never mentions — the discrepancy lands on whoever wired the integration. A typed packaging graph gives that reconciliation something to stand on: the receiving logic can distinguish "the licensed graph says 48 per pallet layer and the ASN agrees" from "an inferred edge suggests these GTINs are related; quantity unknown; escalate the mismatch instead of absorbing it." The SSCC side of that story — the logistic unit as the unit of custody, and the label-to-ASN contract — runs through transactions.dev, where the trace carries its paperwork.
For a 3PL specifically, the graph is client-shaped: every client's family structure arrives differently licensed and differently sloppy, which is precisely why the per-edge source field matters more here than anywhere. You cannot promise your client certainty you don't have; you can promise them a graph that never lies about which kind of edge it is standing on.
Run it against a real client file
The evaluation path that fits how your seat actually adopts tools: take one client's item file — the one with packageUnit.upc filled in by three different people over four years — and resolve its GTINs into families. Every edge comes back typed; every licensed edge names its class; every inferred edge names its basis and refuses to invent quantities. hierarchy is a network verb and runs behind keys — get an API key, say that mixed-client WMS feeds are what arrive at your door, and provisioning follows the list. The GDSN-licensed tier additionally requires standing that is negotiated, not assumed, and the API tells you per edge which side of that line an answer came from.
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.