Event and Lot Custom Data
Creates a Commission event with event-level CustomProperties and lot-level MasterData. Location.Details and Product.Details can be supplied to create the location, trade partner, and product on the go.
curl -X POST "https://connect.wholechain.com/Integration/Events" \
-H "Content-Type: application/json" \
-H "X-API-KEY: example_string" \
-d '{
"Events": [
{
"$type": "commission",
"Location": {
"Id": "processing_001",
"Details": {
"TradePartner": {
"Id": "processor_001",
"Name": "Processor Name",
"ConnectionType": "SELF",
"Duns": "123456789"
},
"Name": "Processing Facility",
"Gln": "9506000140445",
"Extension": "SomeExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Processing Contact",
"Phone": "+1234567890",
"Email": "processing@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "123 Processing Street",
"AddressLine2": "Building 2",
"PostalCode": "8001",
"GeoCoordinates": {
"Latitude": -33.9249,
"Longitude": 18.4241
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001_custom",
"Product": {
"Id": "rawgoods_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Raw Goods",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "product_category",
"namespace": "custom",
"value": "Raw Material"
}
]
}
},
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
],
"Id": "commission_001_custom",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2026-09-28T13:00:00",
"EventTimeZone": "+00:00",
"CustomProperties": [
{
"Name": "Gear Type",
"Namespace": "custom",
"Value": "Longline"
}
]
}
]
}'
import requests
import json
url = "https://connect.wholechain.com/Integration/Events"
headers = {
"Content-Type": "application/json",
"X-API-KEY": "example_string"
}
data = {
"Events": [
{
"$type": "commission",
"Location": {
"Id": "processing_001",
"Details": {
"TradePartner": {
"Id": "processor_001",
"Name": "Processor Name",
"ConnectionType": "SELF",
"Duns": "123456789"
},
"Name": "Processing Facility",
"Gln": "9506000140445",
"Extension": "SomeExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Processing Contact",
"Phone": "+1234567890",
"Email": "processing@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "123 Processing Street",
"AddressLine2": "Building 2",
"PostalCode": "8001",
"GeoCoordinates": {
"Latitude": -33.9249,
"Longitude": 18.4241
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001_custom",
"Product": {
"Id": "rawgoods_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Raw Goods",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "product_category",
"namespace": "custom",
"value": "Raw Material"
}
]
}
},
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
],
"Id": "commission_001_custom",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2026-09-28T13:00:00",
"EventTimeZone": "+00:00",
"CustomProperties": [
{
"Name": "Gear Type",
"Namespace": "custom",
"Value": "Longline"
}
]
}
]
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
const response = await fetch("https://connect.wholechain.com/Integration/Events", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": "example_string"
},
body: JSON.stringify({
"Events": [
{
"$type": "commission",
"Location": {
"Id": "processing_001",
"Details": {
"TradePartner": {
"Id": "processor_001",
"Name": "Processor Name",
"ConnectionType": "SELF",
"Duns": "123456789"
},
"Name": "Processing Facility",
"Gln": "9506000140445",
"Extension": "SomeExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Processing Contact",
"Phone": "+1234567890",
"Email": "processing@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "123 Processing Street",
"AddressLine2": "Building 2",
"PostalCode": "8001",
"GeoCoordinates": {
"Latitude": -33.9249,
"Longitude": 18.4241
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001_custom",
"Product": {
"Id": "rawgoods_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Raw Goods",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "product_category",
"namespace": "custom",
"value": "Raw Material"
}
]
}
},
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
],
"Id": "commission_001_custom",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2026-09-28T13:00:00",
"EventTimeZone": "+00:00",
"CustomProperties": [
{
"Name": "Gear Type",
"Namespace": "custom",
"Value": "Longline"
}
]
}
]
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"Events": [
{
"$type": "commission",
"Location": {
"Id": "processing_001",
"Details": {
"TradePartner": {
"Id": "processor_001",
"Name": "Processor Name",
"ConnectionType": "SELF",
"Duns": "123456789"
},
"Name": "Processing Facility",
"Gln": "9506000140445",
"Extension": "SomeExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Processing Contact",
"Phone": "+1234567890",
"Email": "processing@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "123 Processing Street",
"AddressLine2": "Building 2",
"PostalCode": "8001",
"GeoCoordinates": {
"Latitude": -33.9249,
"Longitude": 18.4241
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001_custom",
"Product": {
"Id": "rawgoods_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Raw Goods",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "product_category",
"namespace": "custom",
"value": "Raw Material"
}
]
}
},
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
],
"Id": "commission_001_custom",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2026-09-28T13:00:00",
"EventTimeZone": "+00:00",
"CustomProperties": [
{
"Name": "Gear Type",
"Namespace": "custom",
"Value": "Longline"
}
]
}
]
}`)
req, err := http.NewRequest("POST", "https://connect.wholechain.com/Integration/Events", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-KEY", "example_string")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://connect.wholechain.com/Integration/Events')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['X-API-KEY'] = 'example_string'
request.body = '{
"Events": [
{
"$type": "commission",
"Location": {
"Id": "processing_001",
"Details": {
"TradePartner": {
"Id": "processor_001",
"Name": "Processor Name",
"ConnectionType": "SELF",
"Duns": "123456789"
},
"Name": "Processing Facility",
"Gln": "9506000140445",
"Extension": "SomeExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Processing Contact",
"Phone": "+1234567890",
"Email": "processing@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "123 Processing Street",
"AddressLine2": "Building 2",
"PostalCode": "8001",
"GeoCoordinates": {
"Latitude": -33.9249,
"Longitude": 18.4241
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001_custom",
"Product": {
"Id": "rawgoods_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Raw Goods",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "product_category",
"namespace": "custom",
"value": "Raw Material"
}
]
}
},
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
],
"Id": "commission_001_custom",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2026-09-28T13:00:00",
"EventTimeZone": "+00:00",
"CustomProperties": [
{
"Name": "Gear Type",
"Namespace": "custom",
"Value": "Longline"
}
]
}
]
}'
response = http.request(request)
puts response.body
{
"message": "Events processed successfully",
"result": [
{
"id": "commission_001",
"status": "Created",
"products": [
{
"id": "rawgoods_001",
"status": "Created"
}
],
"locations": [
{
"id": "processing_001",
"status": "Created"
}
]
}
]
}
/Integration/Events
Target server for requests. Edit to use your own host.
The media type of the request body
Request Preview
Response
Response will appear here after sending the request
Responses
Introduction
Wholechain supports custom data at two different levels within an event:
- Event-level custom data uses
CustomPropertiesand describes the event as a whole. - Lot-level custom data uses
MasterDatainside a product instance and describes a specific lot or product instance.
Use the appropriate field depending on what the custom value applies to.
Example
In the example below:
Gear Typeis event-level custom data because it is stored inCustomProperties.customField1andcustomField2are lot-level custom data because they are stored inMasterDatainside theProductInstancesitem.
{
"Events": [
{
"$type": "commission",
"Id": "event_Commission1790672668636_commission",
"EventTime": "2025-01-27T14:47:25.148",
"EventTimeZone": "-05:00",
"InvoiceNumber": "INV_VALUE",
"PurchaseOrder": "PO_VALUE",
"CustomProperties": [
{
"Name": "Gear Type",
"Namespace": "custom",
"Value": "GEAR TYPE_VALUE"
}
],
"Location": {
"Id": "location_id"
},
"ProductInstances": [
{
"Quantity": 100,
"LotSerial": "lot_serial",
"Product": {
"Id": "product_id"
},
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
]
}
]
}
Event-level custom data
Use CustomProperties to attach business-specific metadata to a Wholechain event without changing the event's standard schema.
Event-level custom data applies to the event as a whole, rather than to a particular lot or product instance.
Typical uses include:
- GDST Data
- Internal workflow references
- Audit results
- Event-specific quality information
- Processing or production information
- Identifiers that relate to the complete event
- Other business-specific values that do not have a dedicated Wholechain field
Supported events
The current ERP event payloads support event-level custom data for:
- Commission
- Aggregation and Disaggregation
- Decommission
- Internal Ship and External Ship
- Receive
- Transform
- Observe
Add CustomProperties directly to the event object, at the same level as fields such as Id, EventTime, Location, and ProductInstances.
Do not place event-level CustomProperties inside ProductInstances, InputProducts, or OutputProducts.
Event custom property schema
CustomProperties is an array. Each entry has the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
Name | string | Yes | Stable name of the custom property. |
Value | string | Yes | Value assigned to the property. |
Namespace | string | Yes | Namespace used to distinguish properties with the same name. |
Example:
{
"CustomProperties": [
{
"Name": "production_line",
"Namespace": "com.example.production",
"Value": "LINE-04"
}
]
}
Complete event-level example
{
"Events": [
{
"$type": "observe",
"Location": {
"Id": "cold_storage_001"
},
"ProductInstances": [
{
"Quantity": 48,
"LotSerial": "LOT-2026-0915",
"Product": {
"Id": "fresh_product_001"
}
}
],
"Id": "observe-0008",
"EventTime": "2026-09-28T10:30:00",
"EventTimeZone": "+00:00",
"CustomProperties": [
{
"Name": "inspection_reference",
"Namespace": "com.example.quality",
"Value": "QA-2026-4401"
}
]
}
]
}
Lot-level custom data
Use MasterData to attach custom data to a specific lot or product instance within an event.
Unlike CustomProperties, which describes the entire event, MasterData belongs inside the relevant product instance.
This allows different lots within the same event to carry different custom values.
Typical uses include:
- Expiration dates
- Harvest information
- Quality grades
- Lot-specific identifiers
- Lot-specific certifications or attributes where no dedicated field exists
- Other metadata that applies specifically to the individual lot
Placement
For events that use ProductInstances, place MasterData inside the relevant product instance:
{
"ProductInstances": [
{
"Quantity": 100,
"LotSerial": "LOT-001",
"Product": {
"Id": "PRODUCT-001"
},
"MasterData": [
{
"name": "expiry_date",
"namespace": "gdst:lot",
"value": "2026-12-31"
}
]
}
]
}
Each product instance can have its own MasterData array.
For example:
{
"ProductInstances": [
{
"Quantity": 100,
"LotSerial": "LOT-001",
"Product": {
"Id": "PRODUCT-001"
},
"MasterData": [
{
"name": "quality_grade",
"namespace": "gdst:lot",
"value": "A"
}
]
},
{
"Quantity": 75,
"LotSerial": "LOT-002",
"Product": {
"Id": "PRODUCT-001"
},
"MasterData": [
{
"name": "quality_grade",
"namespace": "gdst:lot",
"value": "B"
}
]
}
]
}
In this example, the two lots belong to the same event but carry different lot-level custom data.
Lot master-data schema
MasterData is an array. Each entry contains:
| Field | Type | Description |
|---|---|---|
name | string | Name of the lot-level custom field. |
namespace | string | Namespace associated with the custom field. |
value | string | Value assigned to the field for this lot. |
Example:
{
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
Using both levels together
An event can contain both event-level and lot-level custom data.
{
"Events": [
{
"$type": "commission",
"Id": "commission-001",
"EventTime": "2026-09-28T10:30:00",
"EventTimeZone": "+00:00",
"Location": {
"Id": "processing_001"
},
"CustomProperties": [
{
"Name": "Gear Type",
"Namespace": "custom",
"Value": "Longline"
}
],
"ProductInstances": [
{
"Quantity": 100,
"LotSerial": "LOT-001",
"Product": {
"Id": "PRODUCT-001"
},
"MasterData": [
{
"name": "customField1",
"namespace": "gdst:lot",
"value": "customValue1"
},
{
"name": "customField2",
"namespace": "gdst:lot",
"value": "customValue2"
}
]
}
]
}
]
}
Here:
Gear Typeapplies to the entire Commission event.customField1applies specifically toLOT-001.customField2also applies specifically toLOT-001.
If another lot were added to the same event, it could have a different MasterData array.
Choosing the correct level
Use event-level CustomProperties when the value describes the entire business event.
Use lot-level MasterData when the value describes a particular lot or product instance.
For example:
| Data | Recommended level |
|---|---|
| Production line used for the entire transformation | Event-level |
| Internal event reference | Event-level |
| Audit result for the complete event | Event-level |
| Gear type associated with the event | Event-level |
| Expiration date for a specific lot | Lot-level |
| Quality grade for a specific lot | Lot-level |
| Lot-specific harvest information | Lot-level |
| Lot-specific external identifier | Lot-level |
Design a stable custom-data contract
For both event-level and lot-level custom data:
- Use consistent, machine-readable field names.
- Keep the meaning and format of a field stable after integrations depend on it.
- Use namespaces consistently to prevent similarly named values from being interpreted differently.
- Use a consistent representation for dates, numbers, and Boolean values.
- Prefer ISO 8601 for dates and timestamps, for example
2026-12-31or2026-09-28T10:30:00Z. - Include units in the field name or namespace when the value would otherwise be ambiguous.
- Use a dedicated Wholechain field whenever one exists rather than duplicating standard information as custom data.