Carton selection (beta)
Choose packaging and produce a 3D packing arrangement for a set of items.
packing.solve
Beta
job
How to call it
REST
POST
/v1/packing/solve
202
GraphQL
mutation
openPackingSolve
MCP
open_packing_solve
Choose which packagings to use for a set of items and how to split the items across them. Dimensions in centimetres, weights in kilograms. Billed one job.
Request schema
Generated from the same validation rules the endpoint runs, so a field cannot be documented without being validated.
POST /v1/packing/solve
{
"type": "object",
"properties": {
"callback": {
"type": [
"object",
"null"
],
"properties": {
"events": {
"type": "array",
"items": {
"type": "string",
"maxLength": 32
}
},
"format": {
"type": [
"string",
"null"
],
"enum": [
"native",
"ce_binary",
"ce_structured"
]
},
"secret": {
"type": [
"string",
"null"
],
"minLength": 16,
"maxLength": 255,
"description": "Required when callback.signature is standard_webhooks."
},
"signature": {
"type": [
"string",
"null"
],
"enum": [
"native",
"standard_webhooks"
]
},
"url": {
"type": "string",
"maxLength": 2048,
"format": "uri",
"description": "Required when callback is present."
}
}
},
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"can_rotate": {
"type": [
"boolean",
"null"
]
},
"height_cm": {
"type": "number",
"exclusiveMinimum": 0
},
"id": {
"type": [
"string",
"null"
],
"maxLength": 128
},
"length_cm": {
"type": "number",
"exclusiveMinimum": 0
},
"max_stack_layers": {
"type": [
"integer",
"null"
],
"minimum": 1
},
"name": {
"type": [
"string",
"null"
],
"maxLength": 191
},
"orientation": {
"type": [
"string",
"null"
],
"enum": [
"any",
"upright_only",
"side_only"
]
},
"quantity": {
"type": [
"integer",
"null"
],
"minimum": 1
},
"sku": {
"type": [
"string",
"null"
],
"maxLength": 128
},
"stackable": {
"type": [
"boolean",
"null"
]
},
"weight_kg": {
"type": [
"number",
"null"
],
"minimum": 0
},
"width_cm": {
"type": "number",
"exclusiveMinimum": 0
}
},
"required": [
"height_cm",
"length_cm",
"width_cm"
]
}
},
"mode": {
"type": [
"string",
"null"
],
"enum": [
"auto",
"sync",
"async"
]
},
"packagings": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"inner_height_cm": {
"type": "number",
"exclusiveMinimum": 0
},
"inner_length_cm": {
"type": "number",
"exclusiveMinimum": 0
},
"inner_width_cm": {
"type": "number",
"exclusiveMinimum": 0
},
"key": {
"type": [
"string",
"null"
],
"maxLength": 128
},
"max_payload_kg": {
"type": [
"number",
"null"
],
"minimum": 0
},
"name": {
"type": [
"string",
"null"
],
"maxLength": 191
},
"outer_volume_cm3": {
"type": [
"number",
"null"
],
"minimum": 0
},
"quantity_limit": {
"type": [
"integer",
"null"
],
"minimum": 1
},
"tare_weight_kg": {
"type": [
"number",
"null"
],
"minimum": 0
},
"unit_cost": {
"type": [
"number",
"null"
],
"minimum": 0
}
},
"required": [
"inner_height_cm",
"inner_length_cm",
"inner_width_cm"
]
}
},
"target_utilization_percent": {
"type": [
"number",
"null"
],
"minimum": 1,
"maximum": 100
}
},
"additionalProperties": false,
"required": [
"items",
"packagings"
]
}
Request example
{
"packagings": [
{
"key": "box-m",
"name": "Medium box",
"inner_length_cm": 40,
"inner_width_cm": 30,
"inner_height_cm": 30,
"max_payload_kg": 20,
"unit_cost": 1.2
},
{
"key": "box-s",
"name": "Small box",
"inner_length_cm": 25,
"inner_width_cm": 20,
"inner_height_cm": 15,
"max_payload_kg": 10,
"unit_cost": 0.6
}
],
"items": [
{
"id": "SKU-1",
"name": "Mug",
"quantity": 4,
"length_cm": 12,
"width_cm": 10,
"height_cm": 10,
"weight_kg": 0.4
},
{
"id": "SKU-2",
"name": "Kettle",
"quantity": 1,
"length_cm": 25,
"width_cm": 20,
"height_cm": 25,
"weight_kg": 1.5
}
]
}
Response
What a successful call returns: the schema of `data` and `meta`, with a description of each field, followed by an example response from a real call.
POST /v1/packing/solve
Response schema
{
"description": "Ranked ways to pack the items into the packagings, each with the packages used, where every unit sits and the totals. Dimensions come back in millimetres and weights in grams. The example is shortened to the first candidate.",
"data": {
"type": "object",
"properties": {
"target_utilization_percent": {
"type": "number",
"description": "The utilization the solver aimed for."
},
"candidates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rank": {
"type": "integer",
"description": "1 is the recommended candidate."
},
"strategy": {
"type": "string",
"description": "How it was built: `single:<key>` (one packaging type) or `mixed`."
},
"packages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"package_index": {
"type": "integer",
"description": "From 1."
},
"packaging": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "The caller's packaging key."
},
"name": {
"type": [
"string",
"null"
]
},
"source_type": {
"type": "string",
"description": "Always `open` on this platform."
},
"source_id": {
"type": [
"integer",
"null"
],
"description": "Always null on this platform."
},
"inner_length_mm": {
"type": "integer"
},
"inner_width_mm": {
"type": "integer"
},
"inner_height_mm": {
"type": "integer"
},
"outer_volume_mm3": {
"type": "integer"
},
"max_payload_g": {
"type": "integer"
},
"tare_weight_g": {
"type": "integer"
},
"unit_cost": {
"type": [
"number",
"null"
]
}
}
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"item_id": {
"type": "string"
},
"name": {
"type": [
"string",
"null"
]
},
"sku": {
"type": [
"string",
"null"
]
},
"quantity": {
"type": "integer"
}
}
},
"description": "What goes in this package."
},
"placements": {
"type": "array",
"items": {
"type": "object",
"properties": {
"x_mm": {
"type": "number",
"description": "Position along the package length, from the inner rear-left-bottom corner."
},
"y_mm": {
"type": "number",
"description": "Position along the width axis."
},
"z_mm": {
"type": "number",
"description": "Height above the floor."
},
"length_mm": {
"type": "number",
"description": "Footprint along x after rotation."
},
"width_mm": {
"type": "number",
"description": "Footprint along y after rotation."
},
"height_mm": {
"type": "number",
"description": "Extent along z after rotation."
},
"rotation_key": {
"type": "string",
"description": "How the item was turned: the order its own length (L), width (W) and height (H) take along x, y and z."
},
"stack_level": {
"type": "integer",
"description": "1 on the floor, 2 on top of one item, and so on."
},
"container_index": {
"type": "integer",
"description": "Which container or package, from 1."
},
"unit_sequence": {
"type": "integer",
"description": "Loading order within the container, from 1."
},
"unit_key": {
"type": "string",
"description": "Identifies the unit: `item-{row}-{n}`, row and unit counted from 1."
},
"item_id": {
"type": "string",
"description": "The caller's item id."
},
"name": {
"type": "string"
},
"sku": {
"type": [
"string",
"null"
]
},
"weight_g": {
"type": "number",
"description": "Weight of the unit."
},
"cargo_form": {
"type": "string",
"description": "`loose`, or `pallet` for a unit built on a pallet."
},
"source_item_count": {
"type": "integer",
"description": "Items the unit stands for (above 1 for a built pallet)."
},
"pallet_group_key": {
"type": [
"string",
"null"
],
"description": "The pallet this unit was built into, when palletized."
},
"metadata": {
"type": "object",
"description": "The item's handling rules as the solver applied them.",
"properties": {
"stackable": {
"type": "boolean"
},
"max_stack_layers": {
"type": [
"integer",
"null"
]
},
"bearing_level": {
"type": [
"integer",
"null"
]
},
"allowed_orientations": {
"type": "array",
"items": {
"type": "string"
},
"description": "The rotations this item may take."
},
"stack_level": {
"type": "integer"
}
}
}
}
},
"description": "One entry per unit."
},
"metrics": {
"type": "object",
"properties": {
"unit_count": {
"type": "integer"
},
"packed_volume_mm3": {
"type": "integer"
},
"inner_volume_mm3": {
"type": "integer"
},
"utilization_percent": {
"type": "number"
},
"net_weight_g": {
"type": "integer"
},
"gross_weight_g": {
"type": "integer",
"description": "Net weight plus tare."
},
"gravity": {
"type": "object",
"description": "Centre of gravity of the packed contents.",
"properties": {
"cog_x_mm": {
"type": "number"
},
"cog_y_mm": {
"type": "number"
},
"cog_z_mm": {
"type": "number"
},
"offset_x_percent": {
"type": "number",
"description": "Centre of gravity off the middle along x, in percent of the length."
},
"offset_y_percent": {
"type": "number"
},
"cog_height_percent": {
"type": "number"
},
"balanced": {
"type": "boolean"
}
}
}
}
},
"validation": {
"type": "object",
"properties": {
"passed": {
"type": "boolean",
"description": "An independent check found no overlap and nothing outside the package."
},
"version": {
"type": "string"
}
}
},
"checksum": {
"type": "string",
"description": "Identifies this exact package layout."
}
}
}
},
"unplaced": {
"type": "array",
"items": {
"type": "object",
"properties": {},
"additionalProperties": true
},
"description": "Units no package could take."
},
"totals": {
"type": "object",
"properties": {
"package_count": {
"type": "integer"
},
"total_outer_volume_mm3": {
"type": "integer"
},
"total_inner_volume_mm3": {
"type": "integer"
},
"packed_volume_mm3": {
"type": "integer"
},
"wasted_volume_mm3": {
"type": "integer"
},
"overall_utilization_percent": {
"type": "number"
},
"total_net_weight_g": {
"type": "integer"
},
"total_gross_weight_g": {
"type": "integer"
},
"total_cost": {
"type": [
"number",
"null"
],
"description": "Sum of the packagings' `unit_cost`."
},
"unplaced_quantity": {
"type": "integer"
}
}
},
"warnings": {
"type": "array",
"items": {
"type": "string"
},
"description": "Codes of what this candidate falls short on."
}
}
}
}
}
},
"meta": {
"type": "object",
"properties": {},
"additionalProperties": true
}
}
Response example
{
"request_id": "req_01k8zq3m5n7p9r1t3v5x7z9b2d",
"capability": "packing.solve",
"billing": {
"unit": "job",
"quantity": 1,
"counted": true,
"breakdown": {
"packagings": 2,
"item_rows": 2,
"units": 5
}
},
"data": {
"target_utilization_percent": 85,
"candidates": [
{
"rank": 1,
"strategy": "single:box-m",
"packages": [
{
"package_index": 1,
"packaging": {
"key": "box-m",
"name": "Medium box",
"source_type": "open",
"source_id": null,
"inner_length_mm": 400,
"inner_width_mm": 300,
"inner_height_mm": 300,
"outer_volume_mm3": 36000000,
"max_payload_g": 20000,
"tare_weight_g": 0,
"unit_cost": 1.2
},
"items": [
{
"item_id": "SKU-2",
"name": "Kettle",
"sku": null,
"quantity": 1
},
{
"item_id": "SKU-1",
"name": "Mug",
"sku": null,
"quantity": 4
}
],
"placements": [
{
"x_mm": 0,
"y_mm": 0,
"z_mm": 0,
"length_mm": 250,
"width_mm": 200,
"height_mm": 250,
"rotation_key": "LWH",
"stack_level": 1,
"container_index": 1,
"unit_sequence": 1,
"unit_key": "item-2-5",
"item_id": "SKU-2",
"name": "Kettle",
"sku": null,
"weight_g": 1500,
"cargo_form": "loose",
"source_item_count": 1,
"pallet_group_key": null,
"metadata": {
"stackable": true,
"max_stack_layers": null,
"bearing_level": null,
"allowed_orientations": [
"LWH",
"WLH",
"LHW"
],
"stack_level": 1
}
},
{
"x_mm": 0,
"y_mm": 200,
"z_mm": 0,
"length_mm": 120,
"width_mm": 100,
"height_mm": 100,
"rotation_key": "LWH",
"stack_level": 1,
"container_index": 1,
"unit_sequence": 2,
"unit_key": "item-1-1",
"item_id": "SKU-1",
"name": "Mug",
"sku": null,
"weight_g": 400,
"cargo_form": "loose",
"source_item_count": 1,
"pallet_group_key": null,
"metadata": {
"stackable": true,
"max_stack_layers": null,
"bearing_level": null,
"allowed_orientations": [
"LWH",
"WLH",
"WHL"
],
"stack_level": 1
}
},
{
"x_mm": 120,
"y_mm": 200,
"z_mm": 0,
"length_mm": 120,
"width_mm": 100,
"height_mm": 100,
"rotation_key": "LWH",
"stack_level": 1,
"container_index": 1,
"unit_sequence": 3,
"unit_key": "item-1-2",
"item_id": "SKU-1",
"name": "Mug",
"sku": null,
"weight_g": 400,
"cargo_form": "loose",
"source_item_count": 1,
"pallet_group_key": null,
"metadata": {
"stackable": true,
"max_stack_layers": null,
"bearing_level": null,
"allowed_orientations": [
"LWH",
"WLH",
"WHL"
],
"stack_level": 1
}
},
{
"x_mm": 250,
"y_mm": 0,
"z_mm": 0,
"length_mm": 120,
"width_mm": 100,
"height_mm": 100,
"rotation_key": "LWH",
"stack_level": 1,
"container_index": 1,
"unit_sequence": 4,
"unit_key": "item-1-3",
"item_id": "SKU-1",
"name": "Mug",
"sku": null,
"weight_g": 400,
"cargo_form": "loose",
"source_item_count": 1,
"pallet_group_key": null,
"metadata": {
"stackable": true,
"max_stack_layers": null,
"bearing_level": null,
"allowed_orientations": [
"LWH",
"WLH",
"WHL"
],
"stack_level": 1
}
},
{
"x_mm": 250,
"y_mm": 100,
"z_mm": 0,
"length_mm": 120,
"width_mm": 100,
"height_mm": 100,
"rotation_key": "LWH",
"stack_level": 1,
"container_index": 1,
"unit_sequence": 5,
"unit_key": "item-1-4",
"item_id": "SKU-1",
"name": "Mug",
"sku": null,
"weight_g": 400,
"cargo_form": "loose",
"source_item_count": 1,
"pallet_group_key": null,
"metadata": {
"stackable": true,
"max_stack_layers": null,
"bearing_level": null,
"allowed_orientations": [
"LWH",
"WLH",
"WHL"
],
"stack_level": 1
}
}
],
"metrics": {
"unit_count": 5,
"packed_volume_mm3": 17300000,
"inner_volume_mm3": 36000000,
"utilization_percent": 48.056,
"net_weight_g": 3100,
"gross_weight_g": 3100,
"gravity": {
"cog_x_mm": 171.5,
"cog_y_mm": 138.7,
"cog_z_mm": 86.3,
"offset_x_percent": 14.27,
"offset_y_percent": 7.53,
"cog_height_percent": 28.76,
"balanced": true
}
},
"validation": {
"passed": true,
"version": "independent-aabb-1.3"
},
"checksum": "9fdc5c755fec1f510d77baa4a8aa726475f0545da45cd171cc9e43ff640ad0d1"
}
],
"unplaced": [],
"totals": {
"package_count": 1,
"total_outer_volume_mm3": 36000000,
"total_inner_volume_mm3": 36000000,
"packed_volume_mm3": 17300000,
"wasted_volume_mm3": 18700000,
"overall_utilization_percent": 48.056,
"total_net_weight_g": 3100,
"total_gross_weight_g": 3100,
"total_cost": 1.2,
"unplaced_quantity": 0
},
"warnings": []
}
],
"unpackable": []
},
"meta": {
"solver_version": "packing-selection-1.0",
"validator_version": "independent-aabb-1.3",
"units": {
"dimensions": "cm",
"weight": "kg"
},
"mode": "sync"
}
}
Example response when queued (202)
{
"request_id": "req_01k8zq3m5n7p9r1t3v5x7z9b2d",
"capability": "packing.solve",
"billing": {
"unit": "job",
"quantity": 1,
"counted": true,
"breakdown": {
"packagings": 2,
"item_rows": 2,
"units": 5
}
},
"data": {
"job": {
"id": "job_01k8zq4a6c8e0g2j4l6n8q0s2u",
"status": "queued",
"capability": "packing.solve",
"poll_after_ms": 1000,
"result_url": "/v1/jobs/job_01k8zq4a6c8e0g2j4l6n8q0s2u/result",
"cancel_url": "/v1/jobs/job_01k8zq4a6c8e0g2j4l6n8q0s2u/cancel"
}
},
"meta": {
"mode": "async"
}
}
What it costs
One solve run, whatever the item count.
Every billable response carries a billing block with the unit, the quantity and how the quantity was derived.
Errors it can return
| Status | Code | Description |
|---|---|---|
| 401 | TOKEN_INVALID |
Unknown or revoked API token. |
| 401 | TOKEN_MISSING |
No API token. Send Authorization: Bearer <your token>. |
| 402 | QUOTA_EXHAUSTED |
The included allowance for this capability is used up for the current period. |
| 403 | CAPABILITY_NOT_ENABLED |
This capability is not enabled for your account. See :doc to enable it. |
| 403 | CAPABILITY_NOT_GRANTED_TO_KEY |
Your account has this capability, but this API key was not granted it. |
| 403 | OPEN_API_DISABLED |
Open Platform access is not enabled for this account. |
| 422 | SOLVE_INFEASIBLE |
No plan satisfies every constraint. Check time windows, capacities and skills. |
| 422 | VALIDATION_FAILED |
The request failed validation. See details. |
| 429 | CONCURRENCY_LIMIT |
Too many solves are already running for this account. Retry when one finishes. |
| 429 | RATE_LIMITED |
Too many requests. Please retry after the indicated delay. |
| 500 | INTERNAL_ERROR |
An unexpected error occurred. Quote the request_id when contacting support. |