Skip to content

Packing Optimization API

The Packing Optimization API calculates optimal 3D packing solutions for SKUs into pallets and containers using a hybrid 3-layer architecture combining rule-based systems, AI prediction, and mathematical optimization.

Overview

The Packing API solves the 3D bin packing problem with support for:

  • Multiple pallet types: Mixed pallet sizes and specifications
  • Weight constraints: Per-pallet and per-SKU weight limits
  • Dangerous goods: Isolation and special handling
  • Stacking constraints: Non-stackable item support
  • Pre-assigned pallets: Items already packed in specific pallets
  • Unavailable pallet filtering: Exclude specific pallet types
  • Vehicle loading: Container/truck loading optimization

Architecture

The packing service uses a unique three-layer hybrid architecture:

┌─────────────────────────────────────────────────────────┐
│              Layer 3: OR-Tools Mathematical Solver      │
│       - 100% correctness guarantee                      │
│       - Constraint Programming (CP-SAT                       │
│       - Optimal or near-optimal solutions                │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│              Layer 2: AI Prediction Model               │
│       - SKU-pallet compatibility scoring                 │
│       - Placement sequence optimization                  │
│       - Pattern recognition from historical data         │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│              Layer 1: Rule Engine                    │
│       - Pre-assigned pallet handling                     │
│       - Unavailable pallet filtering                     │
│       - Dangerous goods isolation                       │
│       - Stacking constraints                          │
└─────────────────────────────────────────────────────────┘

Performance Characteristics:

LayerSpeedOptimalityUse Case
Rule Engine< 50msBasicFast validation
AI Model100-500msGoodQuick solutions
OR-Tools1-30sOptimalHigh-quality results

Endpoints

Calculate Packing

POST /api/packing/calculate

Calculate the optimal packing plan for a set of SKUs.

Request Body:

json
{
    "skus": [
        {
            "id": "SKU-001",
            "weight": 2.5,
            "weight_unit": "kg",
            "length": 20.0,
            "width": 15.0,
            "height": 10.0,
            "quantity": 50,
            "is_dangerous": false,
            "is_stackable": true
        }
    ],
    "pallets": [
        {
            "id": "EUR-PALLET",
            "length": 120.0,
            "width": 80.0,
            "height": 150.0,
            "weight": 25.0,
            "max_weight": 1500.0,
            "cost": 8.50,
            "flexible_height_ratio": 0.05
        }
    ],
    "vehicle": {
        "length": 1200.0,
        "width": 240.0,
        "height": 260.0,
        "max_weight": 24000.0,
        "unit": "cm"
    },
    "entropy_factor": 1.0,
    "pre_assigned_pallets": null,
    "unavailable_pallet_types": null,
    "use_ai": true,
    "time_limit_ms": 30000
}

SKU Fields:

FieldTypeDefaultDescription
idstringUnique SKU identifier
weightfloatWeight of one unit
weight_unitstring"kg"Weight unit (kg, g, lb, oz)
lengthfloatLength dimension
widthfloatWidth dimension
heightfloatHeight dimension
quantityinteger1Number of units
is_dangerousbooleanfalseDangerous goods flag
is_stackablebooleantrueCan be stacked

Dimension Units

All SKU dimensions default to cm unless specified otherwise. The API automatically converts units based on unit specifications.

Pallet Fields:

FieldTypeDefaultDescription
idstringPallet type identifier
lengthfloatPallet length
widthfloatPallet width
heightfloatPallet height
weightfloat0.0Pallet tare weight
max_weightfloatMaximum loaded weight
length_unitstring"cm"Dimension unit
weight_unitstring"kg"Weight unit
costfloat0.0Cost per pallet use
max_heightfloatnullOptional max stack height
flexible_height_ratiofloat0.05Height tolerance ratio

Flexible Height

The flexible_height_ratio allows small height overruns. Default 5% means a ratio means items can exceed pallet height by 5% if otherwise impossible to pack.

Vehicle Fields (Optional):

FieldTypeDescription
lengthfloatVehicle interior length
widthfloatVehicle interior width
heightfloatVehicle interior height
max_weightfloatMaximum vehicle payload
unitstringDimension unit

Optimization Parameters:

ParameterTypeDefaultDescription
entropy_factorfloat1.0Solution diversity (0.8-2.0)
pre_assigned_palletsarraynullAlready packed pallets
unavailable_pallet_typesarraynullPallet types to exclude
use_aibooleantrueEnable AI enhancement
time_limit_msinteger30000Max solve time in ms

Response:

json
{
    "pallets": [
        {
            "id": "pallet_1",
            "pallet_type": "EUR-PALLET",
            "items": [
                {
                    "sku_id": "SKU-001",
                    "quantity": 45
                }
            ],
            "length": 120.0,
            "width": 80.0,
            "height": 140.0,
            "total_weight": 112.5,
            "total_volume": 135000.0,
            "pallet_volume": 1440000.0,
            "sku_volume": 135000.0,
            "pallet_cost": 8.50,
            "utilization": 0.78
        }
    ],
    "total_pallets": 2,
    "total_weight": 225.0,
    "total_volume": 270000.0,
    "gross_weight": 275.0,
    "net_weight": 225.0,
    "total_items": 100,
    "loaded_items": 90,
    "unloaded_items": 10,
    "total_sku_base_volume": 300000.0,
    "volume_reduction": 0.1,
    "pallet_volume": 2880000.0,
    "total_cost": 17.0,
    "vehicle_utilization": 0.15,
    "algorithm_used": "IntelligentPacking 3-Layer Architecture",
    "pallet_type_usage": {
        "EUR-PALLET": 2
    },
    "solve_time_ms": 1523.45,
    "errors": [],
    "unloaded_items_detail": [
        {
            "sku_id": "SKU-001",
            "quantity": 10,
            "reason": "weight_limit_exceeded"
        }
    ],
    "success": false,
    "message": "Packing complete with 10 items unloaded due to weight constraints",
    "statistics": {
        "weight_utilization": 0.75,
        "volume_utilization": 0.78,
        "pallet_efficiency": 0.92
    },
    "layers_used": ["rule_engine", "ai_model", "or_tools"],
    "processing_time_ms": 1650.23
}

Pre-Assigned Pallets

Specify items already packed in specific pallets:

json
{
    "skus": [...],
    "pallets": [...],
    "pre_assigned_pallets": [
        {
            "pallet_type_id": "EUR-PALLET",
            "pallet_id": "PRE-PAL-001",
            "items": [
                {
                    "sku_id": "SKU-001",
                    "quantity": 10
                }
            ],
            "used_volume": 30000.0,
            "used_weight": 25.0
        }
    ]
}

The optimizer will respect these assignments and optimize around them.

Unavailable Pallet Types

Exclude specific pallet types from consideration:

json
{
    "skus": [...],
    "pallets": [...],
    "unavailable_pallet_types": ["CHEP-PALLET", "ONE-WAY"]
}

Legacy Endpoint

POST /api/packing/calculate/legacy

Legacy endpoint with same interface as /calculate for backward compatibility with older clients.

Health Check

GET /api/packing/health

Check packing service health status.

Response:

json
{
    "status": "healthy",
    "service": "packing",
    "version": "7.0.0",
    "architecture": "3-Layer Hybrid (Rule Engine + AI + OR-Tools)"
}

Error Handling

The API returns structured errors in the errors array:

json
"errors": [
    {
        "sku_id": "SKU-001",
        "error_type": "dimension_too_large",
        "message": "SKU dimensions exceed all available pallets",
        "details": {
            "sku_dimensions": [200, 150, 100],
            "largest_pallet": [120, 80, 150]
        },
        "severity": "error"
    }
]

Error Types:

TypeSeverityDescription
dimension_too_largeerrorSKU larger than any pallet
weight_limit_exceededwarningCannot fit due to weight
dangerous_isolationwarningDangerous goods isolation constraint
stacking_violationwarningNon-stackable stacking violation
unloading_unsolvableerrorPacking problem infeasible

Performance Tips

1. Start Simple

  • Order SKUs by volume descending:
python
# Best packing efficiency
skus.sort(key=lambda x: x.length * x.width * x.height, reverse=True)

2. Weight Distribution

Distribute weight evenly across pallets:

json
{
    "pallets": [
        {"id": "heavy", "max_weight": 2000 /* heavy items */ },
        {"id": "light", "max_weight": 500 /* light items */ }
    ]
}

3. Dangerous Goods Isolation

Separate dangerous goods from regular items:

python
for sku in skus:
    if sku.is_dangerous:
        # These items get their own pallets
        pass

4. Time Limit Tuning

Adjust based on problem size:

SKU CountRecommended Time Limit
< 105000ms
10-5015000ms
50-20030000ms
> 20060000ms

Examples

Example 1: Simple E-Commerce Order

python
payload = {
    "skus": [
        {"id": "BOX-SMALL", "weight": 0.5, "length": 15, "width": 10, "height": 8, "quantity": 200},
        {"id": "BOX-MEDIUM", "weight": 2.0, "length": 30, "width": 20, "height": 15, "quantity": 50},
        {"id": "BOX-LARGE", "weight": 5.0, "length": 50, "width": 40, "height": 30, "quantity": 10}
    ],
    "pallets": [
        {
            "id": "STD", "length": 120, "width": 100, "height": 150, "max_weight": 1000, "cost": 5.0
        }
    ],
    "use_ai": True,
    "time_limit_ms": 15000
}

response = requests.post("/api/packing/calculate", json=payload)

Example 2: Mixed Pallet Types

python
payload = {
    "skus": [...],
    "pallets": [
        {"id": "EUR", "length": 120, "width": 80, "height": 200, "max_weight": 1500, "cost": 8.0},
        {"id": "HALF", "length": 80, "width": 60, "height": 150, "max_weight": 500, "cost": 4.0},
        {"id": "INDUSTRIAL", "length": 120, "width": 100, "height": 180, "max_weight": 2000, "cost": 12.0}
    ]
}

Example 3: With Vehicle Loading

python
payload = {
    "skus": [...],
    "pallets": [...],
    "vehicle": {
        "length": 1360, "width": 244, "height": 260, "max_weight": 20000, "unit": "cm"
    }
}

Cost Optimization

Minimize total cost when multiple pallet types:

python
# API automatically selects optimal pallet mix to minimize:
# total_cost = sum(pallet_type.cost * count)

Set appropriate costs on pallets to get cost-optimized solutions.