The launch journal

Four event types. One decision tree.

31 July 2026 · the launch journal

EPCIS 2.0 gives you five event types, four of which do nearly all the work: ObjectEvent, AggregationEvent, TransactionEvent, TransformationEvent. Teams mis-pick constantly, and the root cause is always the same framing error: they ask "what happened to the thing?" — a question whose answer is a warehouse anecdote — instead of "what claim will a reader need to verify later?" — a question whose answer is a field list. An event is not a diary entry. It is evidence, written for a verifier you will never meet: a trading partner's reconciler, a regulator's query, your own trace three owners later.

Frame it as the claim, and four questions pick the type in under a minute.

The tree

Q1 — Does the claim change what exists? Objects created or destroyed (commissioning serials, decommissioning, destruction) → ObjectEvent with action: ADD or DELETE. Merely seen — shipped, received, inspected, counted → ObjectEvent with action: OBSERVE. ObjectEvent is the default; if no later question fires, you were right the first time.

Q2 — Does the claim change what contains what? Packing, palletizing, loading a trailer, unpacking → AggregationEvent, parent ID plus children, ADD/DELETE for the change, OBSERVE for a checkpoint. If your instinct was "ObjectEvent on the pallet," ask what the verifier needs: the relationship, which only AggregationEvent carries.

Q3 — Is the claim itself about a business transaction? Not "this shipment relates to a PO" — every event type carries bizTransactionList for context. TransactionEvent is for when the association is the news: these EPCs are hereby assigned to (or released from) this PO, this invoice, this bill of lading. It asserts a legal linkage, not a physical occurrence.

Q4 — Do inputs differ from outputs? Materials consumed, different objects produced — batch mixing, assembly that changes identity, repacking bulk into retail units → TransformationEvent, input and output lists linked by a shared transformationID. The genealogy question — "which finished lots contain that input?" — is only answerable if this type was used at the moment identity changed.

(The fifth type, AssociationEvent, is the deliberate fifth wheel: physical pairing rather than containment — a sensor bolted to a reusable tote, an engine into an asset registry. Reach for it when the relationship is "attached to," not "contained in.")

One validating fixture per answer

Every shape below is a fixture in the packaged corpus (node_modules/epcis.dev/golden-corpus/valid-standard/), and each validates against the pinned official EPCIS 2.0.1 schema — seven fixtures, seven valid lines, exit 0 each, re-run today:

$ npx epcis.dev validate golden-corpus/valid-standard/object-event-shipping.json
valid	schema=epcis-json-schema.json	version=2.0.1

ObjectEvent (object-event-shipping.json) — one SGTIN observed shipping, with the PO riding as context, not as the claim:

{ "type": "ObjectEvent", "action": "OBSERVE",
  "epcList": ["urn:epc:id:sgtin:0614141.107346.2018"],
  "bizStep": "shipping", "disposition": "in_transit",
  "readPoint": { "id": "urn:epc:id:sgln:0614141.07346.1234" },
  "bizTransactionList": [{ "type": "po",
      "bizTransaction": "urn:epc:id:gdti:0614141.06012.1234" }] }

AggregationEvent (aggregation-event-packing.json) — the claim is containment: two SGTINs onto an SSCC, action: ADD, bizStep: packing.

TransactionEvent (transaction-event-po.json) — the claim is assignment: two EPCs ADDed to a purchase order, with sourceList/destinationList naming the owning parties by PGLN — the organisation-grain who.

TransformationEvent (transformation-event-production.json) — inputs (two SGTINs plus 10 kg of an input lot, urn:epc:class:lgtin:…) differ from outputs (two new SGTINs), joined by transformationID so multi-session runs chain.

The two classic mis-picks, and their downstream bill

TransactionEvent as "the shipping event." The name misleads; people reach for it because shipping feels transactional. But shipping is a thing that happened to objects — ObjectEvent, OBSERVE, bizStep: shipping, PO in bizTransactionList. Mis-pick and your partner's reconciler, which diffs the despatch advice against observations, finds no observation — the shipped-versus-seen join breaks at its first input.

ObjectEvent for repacking. Bulk case in, twelve retail units out, modeled as an OBSERVE on the case: the twelve output identities now appear from nowhere — commissioned by no event, descended from nothing. Recall scope for the input lot silently excludes every downstream unit. TransformationEvent existed precisely so identity changes leave a verifiable seam.

Both mistakes validate schematically, which is the trap: the schema checks shape, not modeling. The decision tree is the check the schema cannot run — it forces the claim into words before the field list, and the type falls out of the claim. Sixty seconds, four questions, and the reader you'll never meet gets evidence instead of anecdote.

The fixtures are in the tarball and the validator answers in microseconds — npx epcis.dev validate, or run the whole corpus. When the claim needs a performer as well as a type, that's the dimension the standard doesn't carry — and the door up a level is visibility.cloud.

Sources: EPCIS 2.0.1 event types (pinned schema, digests at /conformance/); all seven golden-corpus/valid-standard/ fixtures validated 2026-07-31, exit 0 each; fixture excerpts quoted from the packaged corpus.

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.