Quick start
-
Get an API key
Sign up, pick a plan, and the key arrives by email.
-
Or try it with the demo credentials
These work without an account, against the live solver.
"apiKey": "test", "username": "test" -
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. |
Prompts it understands
Pack 50 boxes of 60x40x30 cm into a 20ft containerLoad 100 fragile items (80x60x40cm, max stack 3) into a 40ft high cubeShip mixed pallets: 10x euro pallets, 15x US pallets using the best container mixShip 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. 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"
}
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. |
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." }
Examples
The same call, in four languages.
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());
}
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 |
| Growth | $199 | 10,000 | $0.03 |
| Scale | $499 | 50,000 | $0.015 |
| Enterprise | Talk to us | Agreed volume, on-premise if you need it | Custom constraints, SLA |
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.
Get an API key