The blog · 2026-07-31
940 and 945 — the warehouse speaks a different dialect of shipping
Written for ED-2 — the RFID systems-integrator / VAR practice — the practice lead deciding which mapping risk the practice owns.
One thesis: the 940/945 cycle compiles cleanly onto warehouse ObjectEvents, but the compile contains genuine choices — which date becomes eventTime, which business step a 945 asserts — and a pipeline is only trustworthy if those choices live in pinned data changed by journaled ruling, never in code changed by refactor. For a practice that deploys against other people's warehouses, that governance question is the difference between attaching margin and inheriting liability.
The 3PL triangle
The 940/945 pair exists because a third party runs the building. The brand sends its 3PL a warehouse shipping order — the 940: ship this, to there, by then. The warehouse fulfills and answers with the 945 — the shipping advice: here is what actually left, when, in what cartons. The brand then tells its retail customer with an 856 built largely from the 945's facts. Three parties, and the systems view is asymmetric in a way that matters: the 945 is very often the only machine record the brand ever receives of what physically departed a building it does not operate. That makes the 945-to-event compile disproportionately valuable — it is the brand's event stream for facilities where it owns no scanners.
The compile, and the three places it is a choice
Structurally the compile is unexciting, which is a compliment: order identity and parties from the 940 land as context; the 945's cartons, GTINs, and quantities land as the observed objects; out come warehouse ObjectEvents — picked, then shipped — carrying the order references on bizTransactionList the same way every other document in the family lands. But three points in that sentence are rulings, not derivations:
- Which date is eventTime. A 945 carries several dates (its own creation, the shipped date, sometimes appointment or loading dates). An event asserts one eventTime. Choosing "the shipped-date segment, and the document date only in its absence" is defensible — and still a choice.
- What a 945 asserts. CBV offers shipping and departing as distinct business steps. A shipping advice generated at manifest close is arguably the former; one generated at trailer departure arguably the latter. The ruling: shipping, uniformly — corroborated departure is transport evidence, a different claim from a different source.
- What grain the objects are. Carton-level SSCCs when the 945 carries them; otherwise class-level quantities per GTIN — never serials invented to make the event prettier. Identity is computed from what the document actually says, or it is absent.
None of these is discoverable by testing, because there is no ground truth to test against — the document did not say. They are semantics, and semantics get governed, not guessed.
The mapping is pinned data
So the 940/945 compile ships as data — an excerpt from the mapping file, with its provenance block:
{
"set": "945",
"version": "004010",
"eventTime": { "use": "shipped-date", "fallback": "document-date" },
"bizStep": "shipping",
"objectGrain": ["sscc", "lgtin-quantity"],
"bizTransactionList": [
{ "type": "po", "from": "warehouse-order-reference" }
],
"provenance": {
"authored": "self",
"sources": ["public implementation conventions", "corpus observation",
"differential parser behavior"],
"rulings": ["2026-07-31 945 asserts bizStep shipping, never departing;
departure is transport evidence, not a warehouse claim"]
}
}
The file is sha256-pinned beside the grammars, and the pipeline's verify gate refuses to run against a mapping whose digest does not match its pin — the same anti-tamper discipline the family applies to its vendored GS1 artifacts. The consequence is the governance property the thesis claims: the implementation hill-climbs conformance to the map, and the map itself changes only when a human writes a dated ruling into the journal. No silent semantic drift, ever — a partner asking "why did these events say shipping" gets a journal line with a date on it, not an archaeology project through git blame.
One 945, one event
The compiled shape, abbreviated — and validated against the pinned official EPCIS 2.0 schema before it leaves the tool, conformant always, superset only where the document carries more:
{
"type": "ObjectEvent",
"action": "OBSERVE",
"bizStep": "shipping",
"disposition": "in_transit",
"eventTime": "2026-07-31T16:40:00.000Z",
"eventTimeZoneOffset": "-06:00",
"epcList": ["urn:epc:id:sscc:0614142.0000004471"],
"bizTransactionList": [
{ "type": "po", "bizTransaction": "urn:epc:id:gdti:0614141.06011.7007" }
],
"sourceList": [
{ "type": "location", "source": "urn:epc:id:sgln:0614142.00001.0" }
]
}
What this unlocks at reconcile time — and for the practice
Once 945s compile to events, the brand's shipped-versus-seen question runs against 3PL facilities exactly as it does against its own docks: the reconcile verdict compares the 945-derived record with downstream captures, and the executive view at visibility.cloud carries paperwork context for buildings that were previously a blind spot between "we told the 3PL" and "the customer complained."
For the practice lead, the governance shape is the business shape. Deployments differ per client — which date their 3PLs populate, whether SSCCs appear — and each difference is an overlay on pinned data your practice authors, versions, and bills for. What the practice does not inherit is the platform risk underneath: the parse, the grammars, the schema validation gate, and the ruling journal are the pipeline's to maintain, with every mapping decision inspectable before your name goes on a deployment. Margin attaches to the judgment layer; maintenance stays where the pins are.
The 940/945 lane, the mapping files, and the journal governance are one pipeline behind the access flow — it asks whose documents you run and for whom, because the mapping conversation starts differently on each side of the triangle.
895 words. The access flow is at /get-access/; the family's event door is epcis.dev.