# bizTransaction is a core field, not a custom extension

> transactions.dev · by visibility.cloud — 2026-07-31
> Written for the supply-chain ISV / traceability-vendor engineering org — the staff engineer answering "can your product carry our PO numbers?".

One thesis: **when a customer asks whether your product can attach their
purchase orders, ASNs, and invoices to traceability events, the correct
answer is that the standard already reserved the field — and any design that
invents a custom extension for it is wrong on the spec's own terms.**

## The citation, before the argument

CBV 2.0 §7.3 defines the `BusinessTransactionTypeID` vocabulary. It is a
closed, standardized list, and it reads like an EDI catalog because it was
written as one: `po` (purchase order), `inv` (invoice), `bol` (bill of
lading), `prodorder`, `recadv` (receiving advice), and `desadv` — the
despatch advice, with the definition that settles the naming argument in
your next architecture review: *"Also called an 'Advanced Shipment Notice,'
but the value desadv is always used regardless of local nomenclature."*

CBV 2.0 §8.5 then places `bizTransactionList` on **all** EPCIS event
types — ObjectEvent, AggregationEvent, TransactionEvent,
TransformationEvent, AssociationEvent. Not a corner of the model. The spine
of it.

That is the entire legal basis the transaction layer needs, and it is why
transactions.dev exists as a compiler rather than a schema: X12, EDIFACT,
and API-native documents in, `bizTransaction` references and party context
out, on core fields every conformant consumer already parses.

## The proof artifact is pinned, not quoted

Your review board should not take a blog post's word for a spec claim, so
here is where the claim is checkable against pinned artifacts rather than
prose. The official EPCIS 2.0 JSON-LD context — vendored and sha256-pinned
in the open epcis.dev artifact set, digests published on
[the conformance page](https://epcis.dev/conformance/) — maps the CBV types
directly:

```json
"po":     "cbv:BTT-po",
"desadv": "cbv:BTT-desadv",
"inv":    "cbv:BTT-inv",
"recadv": "cbv:BTT-recadv"
```

And the golden corpus carries a ratified-shape fixture,
`transaction-event-po.json`, whose relevant lines are exactly what your
product would emit:

```json
"bizTransactionList": [
  {
    "type": "po",
    "bizTransaction": "urn:epc:id:gdti:0614141.06012.1234"
  }
],
"sourceList": [
  { "type": "owning_party", "source": "urn:epc:id:pgln:0614141.00001" }
]
```

Validate that event against the pinned official EPCIS 2.0 JSON schema and it
passes. That is the acceptance bar the `join` verb enforces on everything it
emits: superset where a document carries more than the standard models, and
conformant always — the two words travel together, because a superset that
stops validating is just a fork with better marketing.

## The §7.3 table, worked against one real document

Abstract vocabulary tables convince nobody, so here is the closed list doing
its job against the golden join corpus's 856,
`856-ship-notice-01.edi` — the fixture pair reproduced byte-for-byte in
[the compile post](/blog/from-856-to-epcis-document/). One ASN carries three
of the §7.3 types at once, each from a different segment of the source:

```text
CBV type   source in the 856              emitted bizTransaction
desadv     BSN*00*SHIP20260730001         urn:epcglobal:cbv:bt:0614141000012:SHIP20260730001
po         PRF*PO-8812 (order HL)         urn:epcglobal:cbv:bt:0724142000017:PO-8812
bol        REF*BM*BOL-991                 urn:epcglobal:cbv:bt:0614141000012:BOL-991
```

Every row is core vocabulary. The identifier scheme is CBV §8.5's own —
assigning-party GLN, then the party's reference — so the `desadv` and `bol`
are scoped by the ship-from GLN and the `po` by the buyer GLN that issued
it, straight from the document's N1 loop. Three business documents, three
types, one `bizTransactionList`, zero extension fields: the vocabulary was
sized for exactly this paperwork because it was written from it.

## What this means for your product

You ship software to supply-chain customers. Somewhere in your backlog is a
ticket shaped like "attach ERP document references to trace records," and
two bad designs are competing for it:

1. **The custom-field design.** `customerPoNumber` in your own namespace.
   It works until the first conformant consumer downstream — a retailer's
   system, a regulator's tooling, another vendor — reads your events and
   sees nothing where the standard told it to look.
2. **The full-EDI-stack design.** Embed a translator, take on trading-partner
   onboarding, become an EDI vendor with a traceability feature. Your
   roadmap did not ask for that company.

The compile target is the third design. `transactions.dev` is a dependency
with one contract: documents in, core-field context out. `parse` gives you
lossless canonical JSON; `join` gives you conformant events with
`bizTransactionList`, `sourceList`/`destinationList`, and master-data
joins already placed; `npx transactions.dev` runs the whole thing on your
bench, and the MCP server exposes the same verbs to your customers' agents
with no second code path. Your product keeps its own event pipeline and its
own opinions — it gains the standard's join fields without staffing them.

The worked end-to-end of one document class is in
[the 856 post](/blog/the-856-is-already-an-aggregation-tree/); the
receiving-side counterpart — `recadv`, and what happens when the documents
and the events disagree — is [the reconcile post](/blog/reconcile-is-a-verdict/).

## The line for the RFP response

When the question lands in a bid — "can you carry our transaction context
on EPCIS events?" — the answer that wins is one sentence long and cites no
vendor: *purchase orders, despatch advices, invoices, and receiving advices
are attached as CBV 2.0 §7.3 business-transaction references on the
`bizTransactionList` field that EPCIS 2.0 defines on every event type, and
every emitted event validates against the pinned official schema.*

No extension namespace. No proprietary join table. No "our platform's
flexible metadata model." The standard already has a field for your
purchase order; the only thing missing was the compiler that fills it —
and the place that receives what it emits is already open at
[epcis.dev](https://epcis.dev/business-transactions-in-epcis/).

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