Atoms API
v1Manage and visualize hierarchical product relationships. Atoms represent the actual physical items in orders and their parent-child relationships.
Interactive API Explorer
Loading API Documentation...
Authentication
Authorization: apikey YOUR_API_KEY_HEREBase URLs
- Production:
https://app.zenderatms.com/api/ - Staging:
https://staging.zenderatms.com/api/
Endpoints
Get Atom Tree
Retrieve the complete hierarchical structure of products for an order.
GET /v1/atoms/{orderId}/treeParameters:
orderId(path): Zendera order ID
Example Request:
curl "https://app.zenderatms.com/api/v1/atoms/12345/tree" \
-H "Authorization: apikey YOUR_API_KEY"Response:
{
"atoms": [
{
"id": 1001,
"type": "colli",
"name": "Pallet",
"description": "Standard pallet",
"quantity": 1,
"length": 120.0,
"width": 80.0,
"height": 180.0,
"weight": 50.0,
"internalProductNumber": "PALLET_001",
"internalOrderProductNumber": "OP_001",
"barcodeId": "PALLET_BARCODE_001",
"barcodeType": "CODE128",
"parentId": null,
"children": [
{
"id": 1002,
"type": "trade item",
"name": "Product A",
"quantity": 10,
"weight": 20.0,
"internalProductNumber": "PROD_A_001",
"parentId": 1001,
"children": [],
"statuses": [
{
"status": "PENDING_ORDER_PRODUCT_ORDER_LOCATION_STATUS",
"type": "PICKUP",
"isScanned": false
},
{
"status": "PENDING_ORDER_PRODUCT_ORDER_LOCATION_STATUS",
"type": "DELIVERY",
"isScanned": false
}
]
}
],
"statuses": [
{
"status": "PENDING_ORDER_PRODUCT_ORDER_LOCATION_STATUS",
"type": "PICKUP",
"isScanned": false
}
],
"skills": [
{
"id": 123,
"type": "REQUIRED",
"name": "Forklift",
"description": "Requires forklift handling"
}
],
"groups": [
{
"id": 456,
"name": "Fragile Items",
"description": "Handle with care"
}
],
"units": [
{
"id": 789,
"quantity": 1,
"unitId": 1,
"name": "Pallet",
"description": "Standard EUR pallet"
}
]
}
]
}Update Atom Hierarchy
Modify the parent-child relationships between atoms.
PATCH /v1/atoms/{orderId}/treeParameters:
orderId(path): Zendera order ID
Request Body:
{
"id": 1002,
"parentId": 1001
}This moves atom with ID 1002 to become a child of atom 1001.
Example Request:
curl -X PATCH "https://app.zenderatms.com/api/v1/atoms/12345/tree" \
-H "Authorization: apikey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": 1002,
"parentId": 1001
}'Response:
{
"atoms": [
// Updated atom tree structure
]
}Atom Fields Explained
Core Atom Properties
id: Zendera internal atom IDtype: Atom type ("colli"or"trade item")name: Product namedescription: Product descriptionquantity: Number of itemsparentId: Parent atom ID (null for root items)
Physical Properties
length,width,height: Dimensions in cmweight: Weight in kg
Identification
internalProductNumber: Your product identifierinternalOrderProductNumber: Unique order product identifierbarcodeId: Barcode for scanningbarcodeType: Type of barcode (CODE128, EAN13, etc.)
Warehouse Management
pickupWarehouseLocation: Pickup warehouse identifierdeliveryWarehouseLocation: Delivery warehouse identifier
Status Tracking
statuses: Array of status per location type (PICKUP/DELIVERY)isScanned: Whether the item has been scanned
Skills & Requirements
skills: Array of required/prohibited skills for handlinggroups: Classification groupsunits: Custom measurement units
Atom Hierarchy Patterns
Simple Container
Pallet (colli)
├── Product A (trade item) × 10
└── Product B (trade item) × 5Nested Containers
Pallet (colli)
├── Box 1 (colli)
│ ├── Product A (trade item) × 5
│ └── Product B (trade item) × 3
└── Box 2 (colli)
├── Product C (trade item) × 2
└── Product D (trade item) × 8Mixed Structure
Order
├── Loose Item (trade item) × 1
├── Pallet 1 (colli)
│ └── Products (trade item) × 20
└── Pallet 2 (colli)
├── Box A (colli)
│ └── Small Items (trade item) × 50
└── Large Item (trade item) × 3Status Values
Location Status Options
NOT_READY_ORDER_PRODUCT_LOCATION_STATUS: Product not ready for this locationPENDING_ORDER_PRODUCT_ORDER_LOCATION_STATUS: Awaiting processing at locationCOMPLETE_ORDER_PRODUCT_ORDER_LOCATION_STATUS: Processing complete at locationREMOVED_ORDER_PRODUCT_ORDER_LOCATION_STATUS: Product removed/cancelled
Location Types
PICKUP: Status at pickup locationDELIVERY: Status at delivery location
Use Cases
Hierarchy Visualization
Use the atom tree to build visual representations of product hierarchies:
async function visualizeOrderHierarchy(orderId) {
const response = await fetch(`${API_BASE}/v1/atoms/${orderId}/tree`, {
headers: { Authorization: `apikey ${API_KEY}` },
});
const data = await response.json();
function renderAtom(atom, level = 0) {
const indent = ' '.repeat(level);
console.log(`${indent}${atom.name} (${atom.type}) - Qty: ${atom.quantity}`);
if (atom.children) {
atom.children.forEach(child => renderAtom(child, level + 1));
}
}
data.atoms.forEach(atom => renderAtom(atom));
}Container Management
Move products between containers:
async function moveProductToContainer(orderId, productAtomId, containerAtomId) {
const response = await fetch(`${API_BASE}/v1/atoms/${orderId}/tree`, {
method: 'PATCH',
headers: {
Authorization: `apikey ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: productAtomId,
parentId: containerAtomId,
}),
});
const updatedTree = await response.json();
console.log('Hierarchy updated:', updatedTree);
return updatedTree;
}Status Tracking
Monitor scanning and completion status:
async function getProductStatus(orderId, productExternalId) {
const response = await fetch(`${API_BASE}/v1/atoms/${orderId}/tree`, {
headers: { Authorization: `apikey ${API_KEY}` },
});
const data = await response.json();
function findProduct(atoms, externalId) {
for (const atom of atoms) {
if (atom.internalProductNumber === externalId) {
return atom;
}
if (atom.children) {
const found = findProduct(atom.children, externalId);
if (found) return found;
}
}
return null;
}
const product = findProduct(data.atoms, productExternalId);
if (product && product.statuses) {
const statusReport = {};
product.statuses.forEach(status => {
statusReport[status.type] = {
status: status.status,
isScanned: status.isScanned,
};
});
return statusReport;
}
return null;
}Warehouse Location Tracking
Track products across warehouse locations:
async function getWarehouseLocations(orderId) {
const response = await fetch(`${API_BASE}/v1/atoms/${orderId}/tree`, {
headers: { Authorization: `apikey ${API_KEY}` },
});
const data = await response.json();
function collectLocations(atoms, locations = {}) {
atoms.forEach(atom => {
if (atom.pickupWarehouseLocation) {
locations.pickup = locations.pickup || [];
locations.pickup.push({
atomId: atom.id,
productName: atom.name,
location: atom.pickupWarehouseLocation,
});
}
if (atom.deliveryWarehouseLocation) {
locations.delivery = locations.delivery || [];
locations.delivery.push({
atomId: atom.id,
productName: atom.name,
location: atom.deliveryWarehouseLocation,
});
}
if (atom.children) {
collectLocations(atom.children, locations);
}
});
return locations;
}
return collectLocations(data.atoms);
}Best Practices
1. Use for Visualization Only
The Atoms API is primarily for viewing and understanding product hierarchies. Use the Product Upsert API for modifying products.
2. Cache Atom Trees
Atom trees can be large. Cache the response when possible and only refresh when needed:
class AtomTreeCache {
constructor() {
this.cache = new Map();
this.cacheTimeout = 5 * 60 * 1000; // 5 minutes
}
async getAtomTree(orderId) {
const cached = this.cache.get(orderId);
if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.data;
}
const data = await this.fetchAtomTree(orderId);
this.cache.set(orderId, {
data,
timestamp: Date.now(),
});
return data;
}
}3. Handle Large Hierarchies
For orders with many products, consider pagination or filtering:
async function getAtomSummary(orderId) {
const data = await getAtomTree(orderId);
const summary = {
totalAtoms: 0,
colliCount: 0,
tradeItemCount: 0,
maxDepth: 0,
};
function analyzeAtom(atom, depth = 0) {
summary.totalAtoms++;
summary.maxDepth = Math.max(summary.maxDepth, depth);
if (atom.type === 'colli') {
summary.colliCount++;
} else {
summary.tradeItemCount++;
}
if (atom.children) {
atom.children.forEach(child => analyzeAtom(child, depth + 1));
}
}
data.atoms.forEach(atom => analyzeAtom(atom));
return summary;
}4. Integration with Other APIs
Combine with Order Summary and Product Upsert APIs for complete workflows:
async function completeOrderManagement(orderExternalId) {
// 1. Get order details
const orderSummary = await getOrderSummary(orderExternalId);
const orderId = orderSummary.order.orderId;
// 2. View product hierarchy
const atomTree = await getAtomTree(orderId);
// 3. Update products if needed
await upsertProducts({
update: [
/* updates */
],
updateConfig: { hierarchicalMode: true },
});
// 4. View updated hierarchy
const updatedTree = await getAtomTree(orderId);
return {
orderSummary,
originalTree: atomTree,
updatedTree,
};
}Error Handling
Common error scenarios:
ORDER_NOT_FOUND: Order ID doesn’t existINVALID_ATOM_ID: Atom ID in PATCH request doesn’t existCIRCULAR_REFERENCE: Attempting to create circular parent-child relationshipsINVALID_HIERARCHY: Invalid parent-child relationship (e.g., trade item as parent of colli)