# Lot, expiry, and the header — where ASN master data lands in an EPCIS document

> transactions.dev · by visibility.cloud — 2026-07-31
> Written for the in-house supply-chain platform team — the platform engineer deciding where trade-item and party attributes live.

One thesis: **the master data an ASN carries — lot numbers, expiry dates,
trade-item attributes, party names — has two spec-sanctioned homes inside an
EPCIS 2.0 document, and neither of them is a side database.** ILMD rides on
events at object creation; everything else rides in the document header.
Pick the right home for each attribute and the paperwork's context ships
beside the events, in one file, validated by one schema.

## The two homes, in the pinned schema's own structure

Do not take the claim from prose; take it from the schema. The official
EPCIS 2.0 JSON schema — vendored and sha256-pinned in the open epcis.dev
artifact set (`epcis-json-schema.json`, sha256
`0f46ff694efffd8d8ce840a33dfde84228add11b516b8b258f3200740ae210af`,
retrieved 2026-07-19, digests published on
[the conformance page](https://epcis.dev/conformance/)) — defines both homes
as first-class structures:

- **`ilmd`** (schema definition at line 954): instance/lot master data,
  attached to events that create or transform objects — EPCIS 2.0 §7.3.7.
  This is where a lot's own facts live: the lot number's attributes, the
  expiry, the production date. ILMD is written once, at the event where the
  instance or lot comes into being, and travels with the event record from
  then on.
- **`epcisHeader → epcisMasterData → vocabularyList`** (definitions at
  lines 256 and 347): document-level master data. A `vocabularyList` is a
  list of vocabularies — trade items, locations, parties — each carrying
  vocabulary elements with attributes. This is where the reusable facts
  live: what GTIN 00614141000012 *is*, what GLN 0614141000012 *names*, who
  the parties in the N1 loops are.

The split is not stylistic. ILMD answers "what is true of this particular
lot or instance"; the header answers "what is true of this class, place, or
party, regardless of event." An expiry date belongs to the lot. A product
description belongs to the class. Put each where the schema put it and every
conformant consumer downstream finds both without being told where to look.

## You do not have to invent attribute names

CBV 2.0 §9.2 defines trade-item master data attributes and §9.3 defines
location and party master data attributes — the `cbvmda:` vocabulary,
aligned with GDSN attribute names. Lot number, best-before date, ship-to
party name, trade-item description: the attribute identifiers are already
standardized. The compile emits `cbvmda:`-named attributes, which means the
document's master data is legible to any consumer that reads CBV — the same
reason [the transaction references themselves use core
fields](/blog/biztransaction-is-a-core-field/) instead of a custom
namespace.

## One document, three layers

Here is the shape the `join` verb emits when an ASN carries lot-level lines:
events in the body, transaction references on the events, master data in
the header. Abbreviated but structurally complete:

```json
{
  "@context": "https://ref.gs1.org/standards/epcis/epcis-context.jsonld",
  "type": "EPCISDocument",
  "schemaVersion": "2.0",
  "creationDate": "2026-07-31T09:15:00.000Z",
  "epcisHeader": {
    "epcisMasterData": {
      "vocabularyList": [
        {
          "type": "urn:epcglobal:epcis:vtype:EPCClass",
          "vocabularyElementList": [
            {
              "id": "urn:epc:class:lgtin:0614141.100001.LOT-2607A",
              "attributes": [
                { "id": "cbvmda:lotNumber", "attribute": "LOT-2607A" },
                { "id": "cbvmda:bestBeforeDate", "attribute": "2026-11-15" }
              ]
            }
          ]
        }
      ]
    }
  },
  "epcisBody": {
    "eventList": [
      {
        "type": "ObjectEvent",
        "action": "OBSERVE",
        "bizStep": "shipping",
        "disposition": "in_transit",
        "eventTime": "2026-07-31T09:15:00.000Z",
        "eventTimeZoneOffset": "+00:00",
        "quantityList": [
          {
            "epcClass": "urn:epc:class:lgtin:0614141.100001.LOT-2607A",
            "quantity": 48,
            "uom": "CA"
          }
        ],
        "bizTransactionList": [
          { "type": "desadv", "bizTransaction": "urn:epc:id:gdti:0614141.06012.1234" },
          { "type": "po", "bizTransaction": "urn:epc:id:gdti:0614141.06011.7007" }
        ]
      }
    ]
  }
}
```

The header names the lot and its expiry once. The event cites the lot class
in `quantityList` — the same GTIN-keyed class grain
[the enrichment join works on](/blog/the-gtin-is-the-join-key/) — and
carries its paperwork in `bizTransactionList`. Nothing
is duplicated, nothing is invented, and the whole document validates against
the pinned official schema — that is the gate every emitted document passes
before it leaves the tool. Where an ASN carries more than the standard
models, the extra context rides along as a superset, and the output stays
conformant — always both, never one without the other.

## The anti-pattern this replaces

The common design keeps a product master in one database, a partner master
in another, and events in a third, with the join deferred to query time in
somebody's BI layer. Every consumer then needs credentials to three systems
and a private understanding of the join keys. The EPCIS document model
exists precisely so the record can be handed over whole: a regulator, a
trading partner, or an auditor receives one file and holds the events, the
transaction context, and the master data that makes both legible — no
access to your ERP required, no joining anything. The aggregation structure
the same ASN contributes is
[the HL-tree compile](/blog/the-856-is-already-an-aggregation-tree/); this
post is the third layer of that same document.

## The FSMA-shaped payoff

Food-safety mandates are lot-grain mandates. FSMA 204's traceability
records turn on lot codes and dates, and the difference between "the lot
and expiry are queryable fields on the record" and "the lot is a string
somewhere in a PDF attachment" is the difference between answering a
records request in minutes and staffing it for a week. ILMD at creation
plus `cbvmda:` attributes in the header is exactly the queryable shape —
and it is the shape [the executive layer](https://visibility.cloud/asn-po-context-in-traces/)
stands on when the question is asked by someone with enforcement authority.
The identifier layer those lot classes resolve through — GTIN plus lot,
straight off the case label — is [barcoding.dev](https://barcoding.dev)'s
side of the family.

If your ASNs already carry lot and date segments, the master data is
already in your possession — it has just been landing in an archive
instead of on the record. Bring a sample document to
[the access flow](/get-access/) and say which attributes your partners
actually send — the survey asks exactly that, and the ILMD lane is
sequenced from the answers.

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