Bin Packing API

3D bin packing service. Given a set of containers and items, computes optimal packing — which items fit into which containers and where.

All values are integers. The service is unit-agnostic — use any consistent unit system (mm, cm, inches, etc.).

Endpoint

POST https://php-testing-day.shipmonk.com/api/v1/pack

Pack items into available containers.

Request Body

Content-Type: application/json

Unknown keys are rejected.

FieldTypeDescription
containersarrayAvailable containers required, 1–50
itemsarrayItems to pack required, 1–200

Container Object

Inner (usable) dimensions are assumed equal to outer dimensions. If your containers have wall thickness, subtract it from the dimensions you provide.

FieldTypeDescription
idstringUnique identifier required, non-empty
widthintWidth required, > 0
lengthintLength required, > 0
depthintDepth required, > 0
max_weightintMax total weight required, > 0
empty_weightintContainer weight when empty optional, default 0

Item Object

FieldTypeDescription
idstringUnique identifier required, non-empty
widthintWidth required, > 0
lengthintLength required, > 0
depthintDepth required, > 0
weightintWeight required, > 0
keep_flatboolPrevent vertical rotation optional, default false

Example Request

curl -X POST https://php-testing-day.shipmonk.com/api/v1/pack \
  -H 'Content-Type: application/json' \
  -d '{
  "containers": [
    {
      "id": "box-small",
      "width": 300,
      "length": 200,
      "depth": 150,
      "max_weight": 5000,
      "empty_weight": 100
    }
  ],
  "items": [
    { "id": "item-1", "width": 100, "length": 50, "depth": 50, "weight": 200 },
    { "id": "item-2", "width": 80, "length": 60, "depth": 40, "weight": 150, "keep_flat": true }
  ]
}'

Responses

200 Packing Result

FieldTypeDescription
packed_containersarrayList of containers with their packed items
packed_containers[].container_idstringContainer ID
packed_containers[].itemsarrayItems placed in this container
packed_containers[].items[].item_idstringItem ID
packed_containers[].items[].xintX position within container
packed_containers[].items[].yintY position within container
packed_containers[].items[].zintZ position within container
packed_containers[].items[].widthintPacked width (may differ from input due to rotation)
packed_containers[].items[].lengthintPacked length
packed_containers[].items[].depthintPacked depth
packed_containers[].volume_utilizationfloatVolume usage 0–100 (%)
unpacked_itemsarrayIDs of items that could not fit into any container

Example Response

{
  "packed_containers": [
    {
      "container_id": "box-small",
      "items": [
        { "item_id": "item-1", "x": 0, "y": 0, "z": 0, "width": 100, "length": 50, "depth": 50 },
        { "item_id": "item-2", "x": 100, "y": 0, "z": 0, "width": 80, "length": 60, "depth": 40 }
      ],
      "volume_utilization": 7.78
    }
  ],
  "unpacked_items": []
}

Errors

Every error response has the same shape.

{
  "code": 400,
  "message": "Failed to map data at path /containers/0/width: Expected value greater than 0, got -5",
  "event_id": "10175da7-80f3-406c-af3d-4f4b0cae0c27"
}
FieldTypeDescription
codeintThe HTTP status code
messagestringHuman-readable description. For a validation failure, it starts with the path of the invalid field.
event_idstringIdentifier of the error occurrence
StatusWhen
400The body is not valid JSON, or it fails validation (missing key, unknown key, wrong type, value out of range, duplicate id)
404The path does not exist
405Wrong HTTP method (e.g. GET instead of POST)
415The Content-Type is not application/json
429More than 60 requests per minute from one IP address. The Retry-After header gives the number of seconds to wait.
500Unexpected server error