Create an Observe Event
Create an Observe Event. The request example includes all fields documented for this event, including optional fields.
curl -X POST "https://connect.wholechain.com/Integration/Events" \
-H "Content-Type: application/json" \
-H "X-API-KEY: example_string" \
-d '{
"Events": [
{
"$type": "observe",
"Location": {
"Id": "warehouse_001",
"Details": {
"TradePartner": {
"Id": "my_company",
"Name": "My Company",
"ConnectionType": "SELF",
"Duns": "987654321"
},
"Name": "Main Warehouse",
"Gln": "9506000140446",
"Extension": "WarehouseExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Warehouse Contact",
"Phone": "+1234567891",
"Email": "warehouse@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "456 Warehouse Road",
"AddressLine2": "Building 2",
"PostalCode": "8002",
"GeoCoordinates": {
"Latitude": -33.925,
"Longitude": 18.425
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001",
"Product": {
"Id": "product_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Sample Product",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "Gear Type",
"namespace": "custom",
"value": "GEAR TYPE_VALUE"
}
]
}
}
}
],
"Id": "observe_001",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2024-03-30T19:30:00",
"EventTimeZone": "-05:00",
"CustomProperties": [
{
"Name": "quality_grade",
"Namespace": "custom",
"Value": "A"
}
],
"CertificationList": [
{
"Type": "urn:gdst:certType:harvestCoC",
"Standard": "MSC Chain of Custody",
"Agency": "MSC",
"Value": "YES",
"Identification": "MSC-C-12345"
}
]
}
]
}'
import requests
import json
url = "https://connect.wholechain.com/Integration/Events"
headers = {
"Content-Type": "application/json",
"X-API-KEY": "example_string"
}
data = {
"Events": [
{
"$type": "observe",
"Location": {
"Id": "warehouse_001",
"Details": {
"TradePartner": {
"Id": "my_company",
"Name": "My Company",
"ConnectionType": "SELF",
"Duns": "987654321"
},
"Name": "Main Warehouse",
"Gln": "9506000140446",
"Extension": "WarehouseExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Warehouse Contact",
"Phone": "+1234567891",
"Email": "warehouse@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "456 Warehouse Road",
"AddressLine2": "Building 2",
"PostalCode": "8002",
"GeoCoordinates": {
"Latitude": -33.925,
"Longitude": 18.425
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001",
"Product": {
"Id": "product_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Sample Product",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "Gear Type",
"namespace": "custom",
"value": "GEAR TYPE_VALUE"
}
]
}
}
}
],
"Id": "observe_001",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2024-03-30T19:30:00",
"EventTimeZone": "-05:00",
"CustomProperties": [
{
"Name": "quality_grade",
"Namespace": "custom",
"Value": "A"
}
],
"CertificationList": [
{
"Type": "urn:gdst:certType:harvestCoC",
"Standard": "MSC Chain of Custody",
"Agency": "MSC",
"Value": "YES",
"Identification": "MSC-C-12345"
}
]
}
]
}
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": "observe",
"Location": {
"Id": "warehouse_001",
"Details": {
"TradePartner": {
"Id": "my_company",
"Name": "My Company",
"ConnectionType": "SELF",
"Duns": "987654321"
},
"Name": "Main Warehouse",
"Gln": "9506000140446",
"Extension": "WarehouseExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Warehouse Contact",
"Phone": "+1234567891",
"Email": "warehouse@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "456 Warehouse Road",
"AddressLine2": "Building 2",
"PostalCode": "8002",
"GeoCoordinates": {
"Latitude": -33.925,
"Longitude": 18.425
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001",
"Product": {
"Id": "product_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Sample Product",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "Gear Type",
"namespace": "custom",
"value": "GEAR TYPE_VALUE"
}
]
}
}
}
],
"Id": "observe_001",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2024-03-30T19:30:00",
"EventTimeZone": "-05:00",
"CustomProperties": [
{
"Name": "quality_grade",
"Namespace": "custom",
"Value": "A"
}
],
"CertificationList": [
{
"Type": "urn:gdst:certType:harvestCoC",
"Standard": "MSC Chain of Custody",
"Agency": "MSC",
"Value": "YES",
"Identification": "MSC-C-12345"
}
]
}
]
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"Events": [
{
"$type": "observe",
"Location": {
"Id": "warehouse_001",
"Details": {
"TradePartner": {
"Id": "my_company",
"Name": "My Company",
"ConnectionType": "SELF",
"Duns": "987654321"
},
"Name": "Main Warehouse",
"Gln": "9506000140446",
"Extension": "WarehouseExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Warehouse Contact",
"Phone": "+1234567891",
"Email": "warehouse@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "456 Warehouse Road",
"AddressLine2": "Building 2",
"PostalCode": "8002",
"GeoCoordinates": {
"Latitude": -33.925,
"Longitude": 18.425
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001",
"Product": {
"Id": "product_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Sample Product",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "Gear Type",
"namespace": "custom",
"value": "GEAR TYPE_VALUE"
}
]
}
}
}
],
"Id": "observe_001",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2024-03-30T19:30:00",
"EventTimeZone": "-05:00",
"CustomProperties": [
{
"Name": "quality_grade",
"Namespace": "custom",
"Value": "A"
}
],
"CertificationList": [
{
"Type": "urn:gdst:certType:harvestCoC",
"Standard": "MSC Chain of Custody",
"Agency": "MSC",
"Value": "YES",
"Identification": "MSC-C-12345"
}
]
}
]
}`)
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": "observe",
"Location": {
"Id": "warehouse_001",
"Details": {
"TradePartner": {
"Id": "my_company",
"Name": "My Company",
"ConnectionType": "SELF",
"Duns": "987654321"
},
"Name": "Main Warehouse",
"Gln": "9506000140446",
"Extension": "WarehouseExtension",
"DunsPlus4": "1234",
"ContactInformation": {
"Name": "Warehouse Contact",
"Phone": "+1234567891",
"Email": "warehouse@example.com"
},
"Address": {
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"AddressLine1": "456 Warehouse Road",
"AddressLine2": "Building 2",
"PostalCode": "8002",
"GeoCoordinates": {
"Latitude": -33.925,
"Longitude": 18.425
}
}
}
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "lot_001",
"Product": {
"Id": "product_001",
"Details": {
"ProductIdentifierType": "Lot",
"Name": "Sample Product",
"SimpleUnitOfMeasurement": "Kgm",
"SharingPolicy": "Open",
"UnitDescriptor": "Cases",
"UnitQuantity": 10.5,
"Gtin": "12345678912343",
"Plu": "4001",
"MasterData": [
{
"name": "Gear Type",
"namespace": "custom",
"value": "GEAR TYPE_VALUE"
}
]
}
}
}
],
"Id": "observe_001",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2024-03-30T19:30:00",
"EventTimeZone": "-05:00",
"CustomProperties": [
{
"Name": "quality_grade",
"Namespace": "custom",
"Value": "A"
}
],
"CertificationList": [
{
"Type": "urn:gdst:certType:harvestCoC",
"Standard": "MSC Chain of Custody",
"Agency": "MSC",
"Value": "YES",
"Identification": "MSC-C-12345"
}
]
}
]
}'
response = http.request(request)
puts response.body
{
"message": "Events processed successfully",
"result": [
{
"id": "01a0d877-7871-79a5-a8c8-a2f45673633d",
"externalEventId": "observe_001",
"type": "Observe",
"status": "Created",
"eventDate": "2024-03-30T19:30:00+00:00",
"productInstances": [
{
"quantity": 190.75,
"lotSerial": "lot_001",
"status": "Created",
"id": "01a0d877-7871-7426-b365-3a587ad4f893",
"name": "Raw Goods",
"urn": "urn:gdst:wholechain.com:product:lot:class:raindropsolutions.rawgoods-1.lot_001"
}
],
"containers": [],
"directShipFallback": null,
"externalShipmentFailure": null
}
],
"locations": [
{
"id": "01a0d877-76de-7e96-ac8c-962a914952bf",
"status": "Created"
}
],
"products": [
{
"id": "01a0d877-7719-720e-8fd8-224e3fec0602",
"status": "Created"
}
],
"errors": [],
"validations": []
}
/Integration/Events
Target server for requests. Edit to use your own host.
The media type of the request body
API key used to authenticate the request.
Required. events.
Request Preview
Response
Response will appear here after sending the request
Responses
Optional. message.
Optional. result.
Optional. locations.
Optional. products.
Optional. errors.
Optional. validations.
Introduction
An Observe event records information about an existing product lot at a specific point in time and sets the lot's quantity at that location to the observed quantity.
Observe events can be used for activities such as:
- quality inspections
- temperature readings
- condition checks
- audit results
- quantity observations
- other product or process observations
The observation becomes part of the traceability history for the existing lot.
An Observe event identifies:
- where the observation occurred using
Location - which lot was observed using
ProductInstances - the quantity associated with the observation using
Quantity - when the observation occurred using
EventTime - the unique identifier of the Observe event using
Id
Request Headers
| Header | Description | Example Value |
|---|---|---|
X-API-KEY | Your API key. | YOUR_API_KEY_HERE |
Content-Type | Content type of the request. | application/json |
accept | Response content type. | */* |
Request Body
Event Object
| Field | Type | Description | Required |
|---|---|---|---|
$type | STRING | Defines the event type. For an Observe event, use observe. | Yes |
Location | OBJECT | Location where the observation occurred. | Yes |
ProductInstances | ARRAY | Product lots being observed. | Yes |
Id | STRING | Unique identifier for the Observe event. | Yes |
PurchaseOrder | STRING | Purchase order associated with the event. | No |
InvoiceNumber | STRING | Invoice number associated with the event. | No |
EventTime | DATETIME | Local date and time when the event occurred, without a UTC offset, for example 2024-03-30T13:00:00. The time zone is taken from EventTimeZone. Any offset included in this value is ignored. | Yes |
EventTimeZone | STRING | Optional. Time zone of the event as a UTC offset in ±HH:MM format, for example -05:00. If omitted, the account's default time zone (selected when the account was created) is used. | No |
The Observe API requires Id and EventTime. EventTimeZone, PurchaseOrder and InvoiceNumber are optional.
Location
Location identifies where the observation took place.
Reference the location using its existing Wholechain location ID.
"Location": {
"Id": "warehouse_001"
}
Location Fields
| Field | Type | Description | Required |
|---|---|---|---|
Id | STRING | Unique identifier for the location where the observation occurred. | Yes |
Product Instances
ProductInstances identifies the existing product lot being observed.
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "LOT-001",
"Product": {
"Id": "product_001"
}
}
]
The Observe API requires a quantity, lot or serial number, and product ID for each observed product instance. Duplicate lot numbers should not be submitted separately within the same event.
Product Instance Fields
| Field | Type | Description | Required |
|---|---|---|---|
Quantity | DECIMAL | Quantity associated with the observed lot. | Yes |
LotSerial | STRING | Lot or serial number being observed. | Yes |
Product | OBJECT | Product associated with the lot. | Yes |
Product.Id | STRING | Unique identifier for the existing product. | Yes |
Example Observe a Lot Payload — All Fields
The example below shows the standard Observe payload with all event fields covered in this documentation.
Fields that do not apply should be omitted rather than submitted with empty values.
{
"Events": [
{
"$type": "observe",
"Location": {
"Id": "warehouse_001"
},
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "LOT-001",
"Product": {
"Id": "product_001"
}
}
],
"Id": "observe_0001",
"PurchaseOrder": "PO-12345",
"InvoiceNumber": "INV-12345",
"EventTime": "2026-09-24T10:00:00",
"EventTimeZone": "+00:00"
}
]
}
Observing Multiple Lots
Multiple existing lots can be observed within the same event.
"ProductInstances": [
{
"Quantity": 190.75,
"LotSerial": "LOT-001",
"Product": {
"Id": "product_001"
}
},
{
"Quantity": 75,
"LotSerial": "LOT-002",
"Product": {
"Id": "product_002"
}
}
]
Quantity Observations
An Observe event can also record the quantity observed for an existing lot.
For example, if a warehouse audit determines that the actual quantity differs from what was expected, an Observe event can record the observed quantity without creating a new product or changing the lot identity.
How Quantity works
An Observe event replaces the lot's on-hand quantity at that location with the observed quantity — it does not add or subtract.
| Current on-hand | Observe Quantity | Resulting on-hand |
|---|---|---|
| 100 kg | 5 | 5 kg |
| 100 kg | 150 | 150 kg |
Quantity must be greater than 0. Send the total quantity you observed, not the difference.
Certifications and Custom Event Data
Certifications and custom event-level information can also be added to an Observe event but are documented separately.
→ See: ****Certifications
For information on attaching certification records to an Observe event, see the dedicated Certifications documentation.
→ See: ****Custom Event Data
For information on adding observations such as temperature, quality results, measurements, or other custom information using CustomProperties, see the dedicated Custom Event Data documentation.
Important Notes
- Use
$type: "observe"for an Observe event. Locationidentifies where the observation occurred.ProductInstancesidentifies the existing lot or lots being observed.- Observe does not create a new lot or transform the product into a different product.
- The existing
LotSerialcontinues to identify the same product instance. - Multiple lots can be included in the same Observe event.
- Duplicate lot numbers should not be submitted separately within the same event.
PurchaseOrderandInvoiceNumberare optional and should be omitted when they do not apply.- Certifications and custom event data are documented separately.