Cartonization
Cartonization is a 3D packing service that you install in your own environment. One engine handles every cubing level: order lines into boxes (cartonization), cartons onto pallets (palletization), and goods into rack bins (slotting). It runs several packing algorithms and returns the best result, together with every algorithm's ranking.
Two parts of your system use it:
- Your backend calls the JSON API (
POST /api/pack) server-to-server. It builds the request from your own data: the order lines, your item master (dimensions, weights, handling rules) and your box master (the box types you stock). See Calling the API. - Your frontend shows the result with four display components that your install serves: Summary, Algorithm ranking, Containers and a 3D View. They only display a result, and never call the API themselves. See Embedding the components.
Every request and response field, the error codes and the limits are in the Reference.
How it fits together: the trigger flow#
In a typical integration, a user clicks a button in your application (for example "Cartonize" on an order or at a packing station). Your frontend asks your backend, your backend asks the cartonization install, and the response travels back unchanged to the components:
user your frontend your backend cartonization install
│ │ │ │
│ clicks your │ │ │
│ "Cartonize" ──▶│ POST /api/cartonize ────────▶│ items = order lines │
│ │ { orderId, lines } │ x your item master │
│ │ │ containers = your box master │
│ │ │ │
│ │ │── POST /api/pack ────────────────────▶│ solves in a
│ │ │ includeAllSolutions: true │ worker thread
│ │ │◀──────────────────── pack response ───│
│ │◀───── the response, unchanged │ │
│ │ │ │
│ │ getGroup('station').setResult(response) │
│ sees boxes, │ the components render it; they never call the API │
│ 3D, ranking ◀──│ │
│ │◀──────── /widget/<version>/cartonization-components.js (at page load) │- The user triggers it. The button, the form and the loading and error messages are your own UI. Before the first result, the components show an empty state.
- Your frontend calls your backend with what the user is packing, for example
{ orderId, lines: [{ sku, quantity }] }./api/cartonizeis just the name the samples use; it is your endpoint, with your authentication. - Your backend builds the pack request. It maps each SKU to its dimensions and weight from your item master (and rejects
unknown SKUs with a 400 your frontend can show), adds the box types from your box master, and sets
includeAllSolutions: trueso that the ranking component can open every algorithm's solution. - Your backend calls
POST /api/packon the install and returns the response body to the frontend unchanged. - Your frontend sets the response on the group (
getGroup('station').setResult(response), or theresultproperty of any component in the group). Every component in the group updates, and the selection resets to the best solution and container #1. On an error, setnull, so no component keeps showing the previous packing.
Why the API is called from your backend#
- The API has no authentication: anyone who can reach the port can use it. Keep it on an internal network or behind your gateway, and don't expose it to browsers. It sends no CORS headers, so browser code on another origin can't call it anyway.
- Your backend owns the data. It knows the order, the products and the boxes, and it can check them before packing.
- Your backend can add what your users need (authentication, logging, saving the chosen packing) without changing the frontend contract.
The browser only loads the components script from the install, and that script is public.
What your install serves#
| URL | What |
|---|---|
POST /api/pack, POST /api/capacity, POST /api/pack/multi-level, GET /api/algorithms |
The JSON API, for your backend (Calling the API) |
GET /health |
{"status":"ok"}, for load balancers and monitoring |
GET /v1/info |
The version and the license in use, for monitoring (Reference) |
/docs/status.html |
The Status page: health, version and license of this install |
/widget/1.0.0/cartonization-components.js |
The display components, versioned and cacheable for a year (Loading the script) |
/widget/1.0.0/cartonization-components.d.ts |
Their TypeScript declarations |
/widget/cartonization-components.js |
Always the installed version (no-cache), for development |
/docs/ |
These pages |
/ |
The playground: an internal testing tool to try requests and see what the components show. It isn't meant for embedding. |
This install is version 1.0.0. The base URL is http://127.0.0.1:10081 unless your operator changed HOST / PORT
or put the install behind a reverse proxy; ask them for the URL your backend should use.
Working samples#
The install package has an examples/ directory with a complete trigger flow in several stacks. Each sample has a small
order form and a Cartonize button:
| Sample | What it is |
|---|---|
examples/backend-node |
Customer backend, Node node:http, no dependencies: POST /api/cartonize |
examples/backend-java |
The same backend as one JDK-only Java 17 file |
examples/html |
Plain HTML and JavaScript, runs under a strict Content-Security-Policy |
examples/angular |
Angular, standalone component |
examples/react |
React 19 + Vite + TypeScript |
examples/vue |
Vue 3 + Vite |
The code on these pages is taken from those samples and from tested client files when the docs are built, and the samples, the Java and TypeScript clients and these pages are checked end to end before each release.
Licensing#
The packing API needs a license key, checked offline. The download includes an evaluation (trial) license: everything works,
but responses are marked as trial and the components show a TRIAL mark. Without a valid license the packing API answers
402; everything else (these pages, the components script, GET /health, GET /v1/info) keeps working. See
License for how to get and install a key, and the Status page for the license of this install.