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.

    "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”. 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": "test",
    "username": "test"
  }'

// 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
}]

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.

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.
{ "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 $0.05 Get a key
Growth $199 10,000 $0.03 Get a key
Scale $499 50,000 $0.015 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. Overage is charged per calculation at the rate above rather than cutting you off mid-integration — a load plan failing in production because a counter rolled over is nobody's idea of a good outcome. If you are evaluating and need room to test, say so and we will open the limit while you do.

That is the whole API

One call in, a packed container out.