API

One endpoint. Describe the shipment in plain English, get back the containers it fits in, optional item placements and a link to the 3D result.

Quick start

  1. Get an API key

    Sign up, pick a plan, and the key arrives by email.

    Sign up

  2. Or try it with the demo credentials

    These work without an account, against the live solver. The demo returns the load summary and the link to the 3D plan; item coordinates need a key of your own.

    "apiKey": "test",
    "username": "test"
  3. Make the call

    curl -X POST 'https://3dpack.ing/api/ai/calculate' \
      -H 'Content-Type: application/json' \
      -d '{
        "prompt": "Pack 500 boxes of 100x100x100 mm into a 1m x 1m x 1m container",
        "apiKey": "test",
        "username": "test"
      }'

    Response

    {
      "containers": [{
        "containerDims": { "length": 1000, "width": 1000, "height": 1000 },
        "totalQuantity": 500,
        "itemQuantities": { "Boxes": 500 },
        "volumeUsage": 50.0,
        "weightUsage": 0.0
      }],
      "unpackedItems": { "total": 0, "breakdown": {} },
      "linkToResult": "https://3dpack.ing/app?g=example-guid"
    }

    500 items packed, half the container used, and a link you can open.

The endpoint

POST/api/ai/calculate

Send a description of the shipment and your credentials as JSON. The description is parsed into items, constraints and container preferences, packed by the solver, and returned with a shareable link to the 3D view.

Request body

Field Type Required Notes
prompt string Yes What you are shipping, in plain English. Truncated at 4,000 characters.
apiKey string Yes Your key, or the string “test” for the shared demo — which answers everything except item coordinates. May also be sent as an X-API-Key header.
username string Yes The account the key belongs to. Required whenever a key is sent.
speed string No One of fast, normal or thorough. Defaults to the solver's own choice.
stability integer No How much of a box must rest on what is underneath it, 75 to 100. Omit for 75, the standard rule. Raise it for cargo that must not overhang — 100 means every stacked box sits fully supported, which is steadier and fits fewer.

Prompts it understands

  • Pack 50 boxes of 60x40x30 cm into a 20ft container
  • Load 100 fragile items (80x60x40cm, max stack 3) into a 40ft high cube
  • Ship mixed pallets: 10x euro pallets, 15x US pallets using the best container mix
  • Ship 24 pcs 200.3x120.2x100.2 cm (non-tiltable) using an optimal mix of 40ft and 20ft containers

Response

containers is one entry per container used. Each entry includes utilisation, the five largest overlapping free-space pockets and, when requested, every item placement. unpackedItems reports anything that did not fit. linkToResult opens the same plan in the 3D viewer.

{
  "containers": [
    {
      "containerDims": { "length": 1203.2, "width": 235.0, "height": 269.24 },
      "totalQuantity": 20,
      "itemQuantities": { "Pallets": 20 },
      "volumeUsage": 63.4,
      "weightUsage": 41.8
    },
    {
      "containerDims": { "length": 589.28, "width": 235.0, "height": 239.0 },
      "totalQuantity": 4,
      "itemQuantities": { "Pallets": 4 },
      "volumeUsage": 29.2,
      "weightUsage": 18.3
    }
  ],
  "unpackedItems": { "total": 0, "breakdown": {} },
  "linkToResult": "https://3dpack.ing/app?g=56455ed9-5339-4f46-8c41-cb7462f7aaa1"
}

Item coordinates

Add the coordinates query parameter when your system needs the placement of every packed item. Each container then includes an items array with the item name, its packed dimensions and the x, y and z coordinates of its corner, in the request's unit.

curl -X POST 'https://3dpack.ing/api/ai/calculate?coordinates=true' \
  -H 'Content-Type: application/json' \
  -d '{
    "prompt": "Pack 2 boxes of 60x40x30 cm into a 1m cube",
    "apiKey": "YOUR_KEY",
    "username": "you@company.com"
  }'
// Each packed container also includes:
"items": [{
  "name": "Boxes",
  "length": 60.0, "width": 40.0, "height": 30.0,
  "x": 0.0, "y": 0.0, "z": 0.0
}]

Coordinates are part of a paid API plan; the shared demo account answers 402 when they are requested. The parameter is opt-in to keep summary responses small. The packed dimensions show the chosen orientation. Source-system item IDs and an explicit loading sequence are not part of the public contract today.

Typed rows: the solver API

For systems that already hold the shipment as rows. Send candidate containers and items as JSON and get every placement back — the solver's own contract, with no language model in between. Part of the API plans and Business; the plain-English endpoint above is the one with the free demo.

POST/api/v1/calculate

Headers

Field Type Required Notes
X-API-Key header Yes The key from your API plan or Business subscription.
X-API-Username header Yes The account the key belongs to. A key without it is a 400.
Content-Type header Yes application/json

Request body

Whole numbers in any unit, used consistently — millimetres and grams are the usual choice; each dimension may be 1 to 19,999. Candidates are the containers or trucks the solver may choose from; items carry a quantity, an optional weight, and the stacking rules the planner exposes. Every field is in the OpenAPI specification.

curl -X POST 'https://3dpack.ing/api/v1/calculate' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'X-API-Username: you@company.com' \
  -d '{
    "Candidates": [
      { "Length": 12030, "Width": 2350, "Height": 2390, "MaxWeight": 26700000 }
    ],
    "Items": [
      { "TagOrColor": "pallets", "Length": 1200, "Width": 800, "Height": 1400,
        "Weight": 450000, "Quantity": 24 },
      { "TagOrColor": "crates", "Length": 1000, "Width": 1000, "Height": 900,
        "Weight": 300000, "Quantity": 6, "KeepTop": true, "NoTop": true }
    ],
    "Speed": "Fast"
  }'

Response

The container the solver chose, every placed piece with its packed dimensions and the position of its corner in your units, the pieces that did not fit with their quantities, and the empty spaces left over.

{
  "SelectedContainer": { "Length": 12030, "Width": 2350, "Height": 2390, "MaxWeight": 26700000 },
  "ItemsPut": [
    { "Item": { "TagOrColor": "pallets", "Length": 1200, "Width": 800, "Height": 1400,
                "Quantity": 1, "ContainerIndex": 0 },
      "Coord": { "X": 0, "Y": 0, "Z": 0 } },
    { "Item": { "TagOrColor": "pallets", "Length": 1200, "Width": 800, "Height": 1400,
                "Quantity": 1, "ContainerIndex": 0 },
      "Coord": { "X": 0, "Y": 800, "Z": 0 } }
  ],
  "ItemsNotPut": [],
  "EmptyContainers": [
    { "Coord": { "X": 0, "Y": 0, "Z": 1400 }, "Length": 12030, "Width": 2350, "Height": 990,
      "ContainerIndex": 0 }
  ]
}

Which box: cartonization

POST/api/v1/best-boxes

The order-to-box question. Send one item and up to twenty candidate boxes, and get back, for each box, how many of the item it takes, the placements, and the volume left over — the shape an order system needs to pick a carton.

curl -X POST 'https://3dpack.ing/api/v1/best-boxes' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'X-API-Username: you@company.com' \
  -d '{
    "Candidates": [
      { "Length": 400, "Width": 300, "Height": 300 },
      { "Length": 600, "Width": 400, "Height": 400 }
    ],
    "Item": { "Length": 180, "Width": 120, "Height": 90 }
  }'
// Answers one entry per candidate:
[{ "ContainerDimensions": "400x300x300", "Quantity": 16, "RemainingVolume": 4896000, "ItemsPut": [ ... ] }, ...]

Both endpoints forward your rows to the solver unchanged and return its answer unchanged, so the specification is the contract. They are available on the API plans and Business — the plans that include several containers, stacking capacities and no ceiling on load size. A pack, Pro or free key is answered 402.

Errors

Failures come back as JSON with a single error field, and the status code says which kind it is.

Status Meaning
400 A key was sent without a username. Send both, or neither.
401 No API key in the body or the X-API-Key header.
402 Not an error. The request is valid and asks for something the plan does not cover — multi-container optimisation, or a shipment above the free-tier size. Relay the offer rather than reporting a failure.
403 The key was rejected, or the account it belongs to has no credit left. The message says which.
500 The request reached the solver and something went wrong there. The message says what.
502 The solver did not answer in time. Nothing was charged for a request the solver never received; try again in a moment.
{ "error": "When using API key, 'username' is also required in the request." }

OpenAPI specification

Examples

The same call, in four languages.

Language
const response = await fetch('https://3dpack.ing/api/ai/calculate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    prompt: 'Pack 50 boxes of 60x40x30 cm into a 20ft container',
    apiKey: 'YOUR_API_KEY',
    username: 'YOUR_USERNAME'
  })
});

const result = await response.json();
console.log(`3D visualisation: ${result.linkToResult}`);
console.log(`Containers used: ${result.containers.length}`);
import requests

response = requests.post(
    'https://3dpack.ing/api/ai/calculate',
    json={
        'prompt': 'Pack 50 boxes of 60x40x30 cm into a 20ft container',
        'apiKey': 'YOUR_API_KEY',
        'username': 'YOUR_USERNAME',
    },
)
response.raise_for_status()

result = response.json()
print(f"3D visualisation: {result['linkToResult']}")
print(f"Containers used: {len(result['containers'])}")
using var client = new HttpClient();

var request = new
{
    prompt = "Pack 50 boxes of 60x40x30 cm into a 20ft container",
    apiKey = "YOUR_API_KEY",
    username = "YOUR_USERNAME"
};

var response = await client.PostAsJsonAsync(
    "https://3dpack.ing/api/ai/calculate", request);
response.EnsureSuccessStatusCode();

var result = await response.Content.ReadFromJsonAsync<JsonElement>();
Console.WriteLine(result.GetProperty("linkToResult").GetString());
OkHttpClient client = new OkHttpClient();

String json = """
    {"prompt": "Pack 50 boxes of 60x40x30 cm into a 20ft container",
     "apiKey": "YOUR_API_KEY",
     "username": "YOUR_USERNAME"}
    """;

Request request = new Request.Builder()
    .url("https://3dpack.ing/api/ai/calculate")
    .post(RequestBody.create(json, MediaType.parse("application/json")))
    .build();

try (Response response = client.newCall(request).execute()) {
    System.out.println(response.body().string());
}

MCP server

The same solver, as a tool an AI assistant can call for itself. Describe a shipment in plain English and it answers with the containers the cargo fits in, how full each one is, what did not fit, and a link to the interactive 3D plan. Asked whether 500 cartons fit in a 40-foot, an assistant without it does arithmetic on volumes — which ignores stacking, orientation and weight limits, and overstates what fits by a wide margin on real cargo.

Install

Claude Code, one line:

claude mcp add 3dpacking -- npx -y @3dpacking/mcp-server

Claude Desktop

{
  "mcpServers": {
    "3dpacking": {
      "command": "npx",
      "args": ["-y", "@3dpacking/mcp-server"]
    }
  }
}

It works immediately, with no account — the first calls run against a shared demo account on the free plan. To bill against your own limits, set THREEDPACKING_API_KEY and THREEDPACKING_USERNAME together; the API rejects a key without the username it belongs to. Published as @3dpacking/mcp-server on npm, and as ing.3dpack/container-loading in the MCP registry.

Source on GitHub

Pricing

Priced on calculations, not seats, because calculations are what your volume actually costs us and what your savings actually track. Every tier has the whole API — natural-language input, all six orientations, stacking and weight rules, centre of gravity. There is no feature held back for a higher tier.

Plan Per month Calculations included Beyond that
Starter $49 1,000 Talk to us Get a key
Growth $199 10,000 Talk to us Get a key
Scale $499 50,000 Talk to us Get a key
Enterprise Talk to us Agreed volume, on-premise if you need it Custom constraints, SLA Talk to us

Prices in USD, billed monthly; cancel whenever. Automatic per-call overage billing is not currently offered. If you expect to exceed the included monthly volume or need an evaluation allowance, contact us to agree capacity and pricing before increasing usage.

That is the whole API

One call in, a packed container out.