Say `shipping`, not "shipped."
31 July 2026 · the launch journal
Every warehouse system speaks a private dialect. SHP-OUT-04. RCVD. QC-HOLD. Inside one building, the dialect works — everyone knows what stage 04 means, and the meaning lives in a wiki, a code table, or the head of whoever configured the WMS in 2019. The moment an event crosses a company boundary, the dialect becomes a translation project: your partner's analyst emails to ask what SHP-OUT-04 means, your analyst asks what their STG-COMPLETE means, and a reconciliation meeting is born that will recur, quarterly, forever.
EPCIS solved this in the standard itself. The Core Business Vocabulary — CBV 2.0 — is the why dimension's dictionary: a closed, standardized set of bizStep identifiers (what business process was underway) and disposition identifiers (what state the objects were left in). shipping, receiving, picking, in_transit, sellable_accessible — forty-one business steps, thirty-three dispositions, each with one published meaning. Use them and two parties who have never exchanged a code table can query each other's events and agree on what they say. The vocabulary is the join key.
This is not a style guideline. The schema enforces it.
Here is the part that surprises teams who assumed bizStep was a free-text field. The pinned official EPCIS 2.0.1 JSON schema enumerates the CBV values — a bare word must be one of the standardized identifiers, and anything else must be a full URI in a non-CBV namespace (the sanctioned escape hatch, of which more below). Feed the validator an event whose bizStep is a WMS status code and watch the standard defend itself:
$ npx epcis.dev validate freetext-bizstep.json
schema-error /epcisBody/eventList/0/bizStep must match format "uri"
schema-error /epcisBody/eventList/0/bizStep must be equal to one of the allowed values
schema-error /epcisBody/eventList/0/bizStep must match a schema in anyOf
schema-error /epcisBody/eventList/0 must match "then" schema
schema-error / must match "then" schema
invalid errors=5
$ echo $?
1
SHP-OUT-04 is not merely unfashionable — it is schema-invalid, rejected by GS1's own published artefact with exit 1. Change it to shipping and the same document returns valid. The RFP checkbox that says "CBV-conformant vocabulary" is checkable by a machine in twelve microseconds, which is precisely the kind of claim worth putting in an RFP.
Ten real status strings, mapped
The translation your integration actually needs, for the ten strings every WMS seems to grow — every CBV value below verified against the pinned context's enumerations:
| WMS status string | bizStep | disposition |
|---|---|---|
| SHP-OUT-04 / "Shipped to customer" | shipping | in_transit |
| RCVD | receiving | in_progress |
| PICKED | picking | in_progress |
| STAGED | staging_outbound | in_progress |
| LOADED | loading | in_progress (then container_closed at seal) |
| PUTAWAY | storing | sellable_accessible |
| QC-HOLD | inspecting | non_sellable_other |
| RET-IN (customer return received) | receiving | returned |
| DMG-WRITEOFF | inspecting | damaged |
| SHIP-CANCEL | void_shipping | — |
Note the shape of the mapping: a WMS string usually collapses process and state into one code, and CBV splits them back apart. "Shipped" is a past-tense state in the dialect; in the vocabulary it is a process (shipping) that left the goods in a state (in_transit). That split is why the title of this entry is a rule worth enforcing in code review — the event records a step underway and a disposition resulting, not a verdict remembered.
Also note the pairs are not arbitrary. CBV constrains which dispositions sensibly follow which steps — in_transit follows shipping, not storing; sellable_accessible follows stocking or storing, not destroying. A validator checks the values; a reviewer checks the pairs; a partner's verifier agent, branching on typed results, consumes both without a phone call.
The two strings with no CBV home
Every real code table has entries the vocabulary deliberately does not cover — in our ten-system sample, things like AWAITING-BILLING (a finance workflow state, not an observation about goods) and INV-SYNC-OK (a system-integration heartbeat). Do not shoehorn them into other, and do not stop recording them. The standard's own extension path is the answer: a full URI under your namespace (https://example.com/voc/awaiting-billing) is exactly what the schema's non-CBV URI branch admits, and it validates. The discipline is the boundary: standardized meanings ride the standardized identifiers, private meanings ride namespaced URIs that announce they are private — never a bare string that looks like vocabulary but resolves to a wiki page. (The same discipline, one dimension over, is how a performer rides an event conformantly.)
The compounding payoff is that vocabulary discipline is what makes the joins mechanical. The despatch-advice reconciliation works because both sides' receiving events say receiving; a trace across a co-manufacturer works because commissioning says commissioning in both buildings; the exec dashboard upstairs at visibility.cloud rolls up dispositions it did not have to translate. Every home-grown status string you retire is one future meeting cancelled — and the validator will tell you, today, exactly how many you have left: npx epcis.dev validate, exit codes honest, fixtures in the tarball.
Sources: CBV 2.0 bizStep/disposition vocabularies as enumerated in the pinned epcis-context.jsonld and enforced by the pinned epcis-json-schema.json (digests at /conformance/); rejection transcript run 2026-07-31 with the packaged CLI, exit 1.
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.