# 940 and 945 — the warehouse speaks a different dialect of shipping

> transactions.dev · by visibility.cloud — 2026-07-31
> Written for 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](/blog/anatomy-of-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](/blog/biztransaction-is-a-core-field/).
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:

```json
{
  "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](/blog/grammars-are-data-grammar-pins/), 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](https://epcis.dev/conformance/). 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:

```json
{
  "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](/blog/reconcile-is-a-verdict/) compares the
945-derived record with downstream captures, and the executive view at
[visibility.cloud](https://visibility.cloud/asn-po-context-in-traces/)
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](/get-access/) — it asks whose documents
you run and for whom, because the mapping conversation starts differently
on each side of the triangle.

---
Access: https://transactions.dev/get-access/ · All posts: https://transactions.dev/blog/ · Machine face: https://transactions.dev/llms.txt
