V4

Version 4 covers everything Version 3 does, over 16 endpoints, and organizes them by the answer you want rather than by the shape of the request.

This API version is experimental and can change at any time. It stays experimental for the whole 3.0.x line. Use Version 3 for anything you keep.

πŸ” Learn more:


πŸ“‘ Contents


πŸ—ΊοΈ Choosing an Endpoint

Every fit and pack route ends in bin or bins, and the plural says what comes back.

You want Route Returns
One bin, one answer fit/bin, pack/bin one result
The smallest bin that works fit/smallest-bin, pack/smallest-bin one result
The bin the items fill most pack/best-bin one result
An answer for every bin fit/compare-bins, pack/compare-bins one result per bin, in the order the bins were sent

Each route comes in two forms: custom, where you send the bins in the body, and preset, where the bins come from your configured presets and the preset name is in the path.

smallest-bin takes the least roomy bin the items fit in; best-bin takes the bin they fill the most. The two agree whenever some bin packs fully, and differ only when nothing does.

There is no fit/best-bin. A fit check stops as soon as it can, so on a bin that fails, the fill percentage records how far the run got and not how well the items fill the bin - ranking on it would be misleading. When a fit succeeds, fit/smallest-bin already gives the same answer.

The full list

Method Route What it does
GET /api/v4/presets List every preset with its bins
GET /api/v4/presets/{preset} Get one preset
POST /api/v4/fit/bin Fit-check a custom bin
POST /api/v4/fit/bin/{preset}/{bin} Fit-check one bin from a preset
POST /api/v4/fit/smallest-bin Smallest custom bin the items fit in
POST /api/v4/fit/smallest-bin/{preset} Smallest bin in a preset the items fit in
POST /api/v4/fit/compare-bins Fit-check every custom bin
POST /api/v4/fit/compare-bins/{preset} Fit-check every bin in a preset
POST /api/v4/pack/bin Pack a custom bin
POST /api/v4/pack/bin/{preset}/{bin} Pack one bin from a preset
POST /api/v4/pack/smallest-bin Pack the smallest custom bin that works
POST /api/v4/pack/smallest-bin/{preset} Pack the smallest bin in a preset that works
POST /api/v4/pack/best-bin Pack the custom bin the items fill most
POST /api/v4/pack/best-bin/{preset} Pack the bin in a preset the items fill most
POST /api/v4/pack/compare-bins Pack every custom bin
POST /api/v4/pack/compare-bins/{preset} Pack every bin in a preset

πŸ“œ Presets

GET /api/v4/presets
Returns every configured preset with its bins.

Response Example

{
  "presets": {
    "preset1": [
      { "id": "preset1_bin1", "length": 10, "width": 10, "height": 10 },
      { "id": "preset1_bin2", "length": 20, "width": 20, "height": 20 },
      { "id": "preset1_bin3", "length": 30, "width": 30, "height": 30 }
    ],
    "preset2": [
      { "id": "preset2_bin1", "length": 10, "width": 20, "height": 30 },
      { "id": "preset2_bin2", "length": 30, "width": 60, "height": 60 }
    ]
  }
}

GET /api/v4/presets/{preset}
Returns one preset. Responds 404 when the preset does not exist.

Response Example

{
  "name": "preset1",
  "bins": [
    { "id": "preset1_bin1", "length": 10, "width": 10, "height": 10 },
    { "id": "preset1_bin2", "length": 20, "width": 20, "height": 20 },
    { "id": "preset1_bin3", "length": 30, "width": 30, "height": 30 }
  ]
}

🧩 Fit

Fitting answers whether the items go in. V4 fit results also carry the placement of every item that was packed before the check finished.

POST /api/v4/fit/bin takes one bin in bin. fit/smallest-bin and fit/compare-bins take a list in bins instead. The preset forms take no bins at all - the path supplies them.

Request Example (POST /api/v4/fit/bin)

{
  "parameters": {
    "algorithm": "Best",
    "includeViPaqData": true
  },
  "bin": { "id": "custom_bin", "length": 10, "width": 40, "height": 60 },
  "items": [
    { "id": "box_1", "quantity": 2, "length": 2, "width": 5, "height": 10 },
    { "id": "box_2", "quantity": 1, "length": 12, "width": 15, "height": 10 },
    { "id": "box_3", "quantity": 1, "length": 12, "width": 10, "height": 15 }
  ]
}

Response Example

{
  "status": "Fits",
  "bin": { "id": "custom_bin", "length": 10, "width": 40, "height": 60 },
  "algorithmUsed": "FFD",
  "packedItems": [
    { "id": "box_2", "length": 10, "width": 12, "height": 15, "x": 0, "y": 0, "z": 0 },
    { "id": "box_3", "length": 10, "width": 12, "height": 15, "x": 0, "y": 12, "z": 0 },
    { "id": "box_1", "length": 2, "width": 5, "height": 10, "x": 0, "y": 0, "z": 15 },
    { "id": "box_1", "length": 2, "width": 5, "height": 10, "x": 0, "y": 24, "z": 0 }
  ],
  "unpackedItems": [],
  "packedItemsVolumePercentage": 100,
  "packedBinVolumePercentage": 15.83,
  "viPaqData": "AAAEAAooPAoMDwAAAAoMDwAMAAIFCgAADwIFCgAYAA==",
  "earlyExitReason": "None"
}

A check that stopped before placing anything reports why:

{
  "status": "EarlyExit",
  "bin": { "id": "custom_bin", "length": 10, "width": 40, "height": 60 },
  "algorithmUsed": "FFD",
  "packedItems": [],
  "unpackedItems": [ { "id": "large_box", "quantity": 1 } ],
  "packedItemsVolumePercentage": 0,
  "packedBinVolumePercentage": 0,
  "earlyExitReason": "ContainerDimensionExceeded"
}

fit/compare-bins returns one such result per bin, wrapped in a results array, in the order the bins were sent.


πŸ“¦ Pack

Packing places the items and returns where each one went.

Request Example (POST /api/v4/pack/smallest-bin)

{
  "parameters": {
    "algorithm": "Best",
    "includeViPaqData": true
  },
  "bins": [
    { "id": "custom_bin_1", "length": 10, "width": 40, "height": 60 },
    { "id": "custom_bin_2", "length": 20, "width": 40, "height": 60 },
    { "id": "custom_bin_3", "length": 30, "width": 40, "height": 60 }
  ],
  "items": [
    { "id": "box_1", "quantity": 2, "length": 2, "width": 5, "height": 10 },
    { "id": "box_2", "quantity": 1, "length": 12, "width": 15, "height": 10 },
    { "id": "box_3", "quantity": 1, "length": 12, "width": 10, "height": 15 }
  ]
}

Response Example

{
  "status": "FullyPacked",
  "bin": { "id": "custom_bin_1", "length": 10, "width": 40, "height": 60 },
  "algorithmUsed": "FFD",
  "packedItems": [
    { "id": "box_2", "length": 10, "width": 12, "height": 15, "x": 0, "y": 0, "z": 0 },
    { "id": "box_3", "length": 10, "width": 12, "height": 15, "x": 0, "y": 12, "z": 0 },
    { "id": "box_1", "length": 2, "width": 5, "height": 10, "x": 0, "y": 0, "z": 15 },
    { "id": "box_1", "length": 2, "width": 5, "height": 10, "x": 0, "y": 24, "z": 0 }
  ],
  "unpackedItems": [],
  "packedItemsVolumePercentage": 100,
  "packedBinVolumePercentage": 15.83,
  "viPaqData": "AAAEAAooPAoMDwAAAAoMDwAMAAIFCgAADwIFCgAYAA=="
}

When some items are left over, status is PartiallyPacked and they are listed with their quantity:

{
  "status": "PartiallyPacked",
  "bin": { "id": "custom_bin", "length": 10, "width": 40, "height": 60 },
  "algorithmUsed": "FFD",
  "packedItems": [
    { "id": "box_2", "length": 10, "width": 12, "height": 15, "x": 0, "y": 0, "z": 0 },
    { "id": "box_3", "length": 10, "width": 12, "height": 15, "x": 0, "y": 12, "z": 0 }
  ],
  "unpackedItems": [ { "id": "box_1", "quantity": 2 } ],
  "packedItemsVolumePercentage": 94.74,
  "packedBinVolumePercentage": 15.0,
  "viPaqData": "AAACAAooPAoMDwAAAAoMDwAMAA=="
}

pack/compare-bins wraps one such result per bin in a results array, in the order the bins were sent.


βš™οΈ Parameters

Every fit and pack request carries a parameters object.

Bins and items are integers of at least 1, in whatever unit you use, as long as it is the same one everywhere. Every id you send is echoed back on the matching result.


🧠 Algorithm

FFD, WFD and BFD are the individual heuristics, described in Core Concepts.

Best runs more than one and keeps the best result. It does not run the same set on every route:

The response’s algorithmUsed says which heuristic produced the result you got.

Best the algorithm and best-bin the route are different things. The route picks a bin; Best picks a heuristic. BFD is Best Fit Decreasing, which is a third thing again.


🚦 Result Values

Fitting (status)

earlyExitReason is None on a check that ran to completion.

Packing (status)


❌ Errors

Errors are returned in RFC 7807 problem-details form.

Status When
400 The request body is missing or is not valid JSON.
404 The preset, or the bin within it, does not exist.
422 The request was read but failed validation. errors lists the fields.
429 Rate limited. Only when the Service Module is enabled.
500 An unhandled error.

The two presets endpoints are not rate limited.