EventsOverview of the Events API

Events API Overview

Introduction

The Wholechain Events API is used to record the movement, creation, transformation, adjustment, and removal of products throughout a supply chain.

Unlike APIs where each record can be created independently, Wholechain events form a chronological chain.

Each event affects the product's current state and determines what events can happen next.

A typical product journey may look like:

Receive
   ↓
Transform
   ↓
Ship
   ↓
Receive
   ↓
Ship

Or:

Commission
    ↓
Observe
    ↓
Transform
    ↓
Ship

This means that when submitting an event, Wholechain does not only validate the payload itself. It also validates whether the event makes sense based on the events and inventory that already exist before that point in time.


Events Are Connected

Events represent what happens to a specific:

  • Product
  • Lot or serial
  • Quantity
  • Location
  • Trade partner
  • Point in time

These values allow Wholechain to connect one event to another and build the product's traceability history.

For example:

Receive
Product: Salmon
Lot: LOT-001
Location: Warehouse A
Quantity: 100 kg
Time: 09:00

        ↓

Transform
Input Product: Salmon
Input Lot: LOT-001
Location: Warehouse A
Quantity: 100 kg
Time: 11:00

        ↓

Ship
Output Product: Salmon Fillet
Lot: LOT-002
Location: Warehouse A
Quantity: 80 kg
Time: 15:00

The Transform works because Wholechain can find LOT-001 at Warehouse A before 11:00.

The Ship works because the output of the Transform exists before 15:00.


Event Timing Matters

The event timestamp determines where an event sits within the supply chain history.

Events must therefore occur in the correct chronological order.

For example:

09:00  Receive 100 kg
          ↓
11:00  Transform 100 kg
          ↓
15:00  Ship 80 kg

This is valid because each event happens after the event that makes the required inventory available.

The following would not be valid:

11:00  Transform 100 kg
          ↓
12:00  Receive 100 kg

At 11:00, the Receive has not happened yet.

Therefore, as far as Wholechain is concerned, the inventory required for the Transform does not yet exist.

It does not matter if the Receive request was sent to the API first. The event timestamp determines the sequence of events, not simply the order in which the API requests are submitted.


Avoid Using the Same Time for Dependent Events

Events that depend on each other should have clearly ordered timestamps.

For example:

10:00:00  Ship from Supplier
10:05:00  Receive at Processor

is preferable to:

10:00:00  Ship from Supplier
10:00:00  Receive at Processor

If two dependent events occur at exactly the same time, Wholechain will not have a clear preceding event to connect against.

If the Receive depends on the Ship, the Ship should occur before the Receive.

Likewise:

Receive → Transform → Ship

should mean:

Receive Time < Transform Time < Ship Time

Correct timestamps are therefore essential for both inventory validation and traceability.


Inventory Must Exist Before It Can Be Used

Many Wholechain events operate on existing inventory.

You cannot simply create a Transform, Ship, Observe, or Decommission event for any product and lot combination.

Wholechain must first be able to find the relevant inventory.

For example:

Receive
100 kg of LOT-001
        ↓
Available Inventory
100 kg of LOT-001
        ↓
Transform
Consumes 60 kg
        ↓
Available Inventory
40 kg of LOT-001

The Transform succeeds because 100 kg was available before the event.

If you attempted to Transform 120 kg:

Available: 100 kg
Requested: 120 kg

the event cannot be completed because there is insufficient inventory.


Inventory Is Identified by More Than Just the Lot

When Wholechain searches for inventory, the lot number alone is not enough.

The relevant product instance generally needs to match the event's:

Product
+
Lot / Serial
+
Location
+
Event Time

Therefore, inventory may exist in Wholechain but still not be available for a particular event.

For example:

Product: Salmon
Lot: LOT-001
Location: Warehouse A
Quantity: 100 kg

A Ship requesting:

Product: Salmon
Lot: LOT-001
Location: Warehouse B

cannot use that inventory.

The inventory exists, but it exists at the wrong location.

The same applies when the Product ID, lot code, or event timing does not match.


Events Change Available Inventory

Every inventory-related event affects what can happen next.

For example:

Receive 100 kg
      ↓
Inventory = 100 kg

Ship 30 kg
      ↓
Inventory = 70 kg

Transform 50 kg
      ↓
Inventory = 20 kg

Decommission 10 kg
      ↓
Inventory = 10 kg

Future events can only operate on the remaining available inventory.

This is why events should be thought of as a continuous product history, rather than separate API transactions.


Creating Inventory

Before inventory can be consumed, it generally needs to enter Wholechain.

Two common events used to establish inventory are:

Receive

A Receive event records product arriving at a location.

For example:

Supplier
   ↓
Receive
   ↓
Warehouse A

LOT-001
100 kg

Once received, that inventory becomes available at the receiving location for subsequent events.

A Receive may also connect to an upstream Ship where the corresponding shipment exists.

Commission

A Commission event creates inventory directly at a location.

This is useful where inventory originates within the organization and there is no preceding external Receive that establishes the product.

For example:

Commission
     ↓
LOT-001
100 kg
Warehouse A

Once commissioned, the lot can be used by subsequent inventory events.


Transform

A Transform represents the conversion of one or more existing product lots into one or more output lots.

For example:

INPUT

Whole Salmon
LOT-001
100 kg

     ↓
  TRANSFORM
     ↓

OUTPUT

Salmon Fillet
LOT-002
60 kg

Salmon Trim
LOT-003
30 kg

The important point is that the input inventory must already exist before the Transform event occurs.

Wholechain needs to find:

Input Product
Input Lot
Input Location
Required Quantity
Inventory available before the Transform time

You therefore cannot create a valid Transform merely because the payload contains an input lot.

If that input inventory does not exist at that location and time, the Transform cannot correctly consume it.

Once the Transform is completed, the output lots become available inventory for later events.

Receive LOT-001
       ↓
Transform LOT-001 → LOT-002
       ↓
Ship LOT-002

Ship

A Ship event moves inventory out of a location.

For example:

Warehouse A

LOT-001
100 kg

   ↓ Ship 40 kg

Customer

Remaining at Warehouse A:
60 kg

Wholechain therefore needs to find the inventory at the shipping location before the Ship event occurs.

The following must match the available inventory:

  • Product
  • Lot
  • Shipping location
  • Quantity
  • Event time

A Ship event normally reduces the available quantity at the origin location.


Direct Ship

Ship events can support a DirectShip option.

This provides an exception to the normal inventory requirement.

DirectShip: false

Wholechain expects the inventory to exist.

If the requested inventory cannot be found, the shipment will not be completed normally.

DirectShip: true

If Wholechain cannot find the expected inventory, the shipment can still be recorded.

This is useful when there is an earlier data issue in the supply chain—for example, an upstream event was never successfully transmitted—but you still need to record the shipment to the customer.

Earlier inventory data missing
          ↓
DirectShip = true
          ↓
Shipment can still be recorded

Direct Ship should therefore be treated as a fallback mechanism. It does not mean that inventory validation is generally unnecessary.


Receive After a Ship

When representing movement between locations, the logical sequence is:

Location A
   ↓
Ship
   ↓
Receive
   ↓
Location B

For example:

09:00
Ship LOT-001
Warehouse A → Warehouse B

        ↓

12:00
Receive LOT-001
at Warehouse B

Once the Receive occurs, the inventory becomes available at Warehouse B.

Events after that Receive should reference Warehouse B.

For example:

Warehouse A
    ↓
  Ship
    ↓
Warehouse B
    ↓
 Receive
    ↓
Transform
    ↓
  Ship

You should not attempt to Transform the product at Warehouse B before the Receive establishes it there.


Observe

An Observe event records an adjustment or observation against existing inventory.

For example:

Current Inventory
100 kg

     ↓

Observe
5 kg

     ↓

New Inventory
5 kg

An Observe event therefore normally needs an existing product instance to act against.

The product, lot, location, and timing must correspond to inventory that exists before the Observe event.

An Observe does not move the product to another location and quantity must be greater than 0.


Decommission

A Decommission event removes some or all of a product from the active supply chain.

For example:

Inventory
100 kg

    ↓

Decommission
20 kg

    ↓

Available Inventory
80 kg

Common examples include:

  • Spoilage
  • Damage
  • Expiration
  • Rejection
  • Product loss
  • Product being taken permanently out of circulation

The quantity being decommissioned must be available before the Decommission occurs.

Once inventory has been decommissioned, that quantity cannot subsequently be shipped or transformed.


Aggregate and Disaggregate

Aggregate and Disaggregate events describe relationships between products and containers or grouped units.

Conceptually:

Individual Products
       ↓
    Aggregate
       ↓
Container / Parent Unit

and:

Container / Parent Unit
       ↓
   Disaggregate
       ↓
Individual Products

As with other events, the products or units referenced by these events need to exist at the appropriate location and point in the event chain.


Events Cannot Be Treated as Independent Records

Consider the following:

1. Receive 100 kg
2. Transform 60 kg
3. Ship 40 kg

These are not three unrelated records.

They represent changes to the same inventory over time.

Receive
Inventory +100
     ↓
Transform
Inventory -60
     ↓
Ship
Inventory -40

Wholechain therefore continuously evaluates what inventory should exist at each point in the chain.

This is why an event can have a structurally correct JSON payload but still fail business validation.


Inserting Events Into an Existing Chain

Extra care is required when adding or correcting historical events.

For example, assume Wholechain already contains:

September 1
Receive 100 kg

September 4
Ship 50 kg

You should not assume that you can later insert any inventory-consuming event between those two events without affecting the events that follow.

The chain is already dependent on the inventory history.

For example:

Sep 1
Receive 100 kg
     ↓
Sep 3
NEW Transform 80 kg
     ↓
Sep 4
Existing Ship 50 kg

The existing Ship may no longer be valid because the Transform has changed the inventory that should be available to it.

Historical corrections may therefore require later dependent events to be corrected, removed, or reposted in the correct sequence.

Think of the chain as:

Event 1
   ↓
determines state for
   ↓
Event 2
   ↓
determines state for
   ↓
Event 3

Changing Event 1 or Event 2 can affect everything downstream.


Updating Events

Where an existing event is being updated, use the same event identifier according to the relevant event endpoint's update behavior.

The event ID is important because it tells Wholechain that the request relates to an existing event rather than representing an entirely separate business event.

For example:

EVENT-001
Receive 50 kg

may later be updated as:

EVENT-001
Receive 100 kg

rather than creating:

EVENT-001
50 kg

EVENT-002
100 kg

when the business system is actually sending an updated version of the same transaction.

Updating an earlier event can also affect downstream inventory, so updates should always be considered in the context of the entire event chain.


Common Reasons an Event Cannot Find Inventory

If Wholechain reports that a product instance or inventory cannot be found, check the complete chain rather than only the failing event.

Common causes include:

  1. Incorrect Event Time

    The event occurs before the event that created or received the inventory.

  2. Incorrect Location

    The lot exists, but at another location.

  3. Incorrect Product ID

    The lot exists against a different product.

  4. Incorrect Lot or Serial

    The product exists, but the specified lot does not match.

  5. Insufficient Quantity

    Some inventory exists, but not enough remains for the requested event.

  6. Inventory Was Already Consumed

    A previous Transform, Ship, Observe adjustment, or Decommission has reduced or removed the inventory.

  7. An Earlier Event Is Missing

    The Receive, Commission, Transform, or other event that should have established the inventory was never successfully created.

  8. Events Are in the Wrong Chronological Order

    The required inventory only becomes available after the event that is trying to use it.

  9. Dependent Events Use the Same Timestamp

    Wholechain cannot establish the expected preceding inventory relationship correctly.

  10. A Historical Event Was Changed

    An earlier update may have changed the inventory available to later events.


Example of a Correct Event Chain

Consider a processor receiving fish, processing it, and shipping the finished product.

08:00
RECEIVE

Product: Whole Salmon
Lot: RAW-001
Location: Processing Plant
Quantity: 100 kg

        ↓

10:00
TRANSFORM

Input:
Whole Salmon
RAW-001
100 kg

Outputs:
Salmon Fillet
FILLET-001
70 kg

Salmon Trim
TRIM-001
20 kg

        ↓

14:00
SHIP

Product: Salmon Fillet
Lot: FILLET-001
Location: Processing Plant
Quantity: 50 kg

        ↓

Remaining Inventory:

FILLET-001 = 20 kg
TRIM-001 = 20 kg

At every stage, the event is possible because the required inventory exists immediately before the event occurs.


Example of an Incorrect Event Chain

08:00
Transform RAW-001

        ↓

10:00
Receive RAW-001

The Transform cannot correctly use the lot because the inventory does not exist until 10:00.

Another example:

08:00
Receive
LOT-001
Warehouse A
100 kg

        ↓

10:00
Ship
LOT-001
Warehouse B
50 kg

This also fails normal inventory logic because the inventory exists at Warehouse A, not Warehouse B.


The Key Rule

When working with the Events API, always ask:

What inventory should exist at this exact location immediately before this event occurs?

If the answer does not match the event you are sending, the event will not form the expected Wholechain traceability chain.

Before submitting an event, confirm:

  • Is the Product ID correct?
  • Is the Lot or Serial correct?
  • Is the Location correct?
  • Does sufficient inventory exist?
  • Did the previous event happen first?
  • Is the event timestamp correct?
  • Has any previous event already consumed this inventory?
  • Does the quantity make sense?
  • Does the event logically follow the preceding supply chain event?

Wholechain events should therefore always be designed and tested as an end-to-end event flow, not as individual API calls.