Estimate a packing job
Runs the same validation as POST /v1/pack and returns the price range, without creating a job or reserving credits.
Free. An invalid request answers 200 with valid: false and every problem in errors[].
Autenticação
Parâmetros do corpo
application/jsonreferencestringYour own reference (order number, shipment id…). Echoed back on the job.
vehiclesVehicle[]obrigatórioVehicle definitions. Each one may have quantity > 1. At least one.
idstringYour identifier, unique within the request. Results refer to it as vehicle_id. Defaults to vehicle_id.
vehicle_idstringA vehicle id from GET /v1/vehicles: a preset or one of your organization's vehicles (veh_…). Supplies type, name, dimensions, payload and every other saved value.
typestringVehicle type. Required unless vehicle_id is given. Only the types listed in GET /v1/limits (allowed_vehicle_types) are accepted.
trucktrailerflatbedcontainerpalletaircraftshipnamestringDisplay name (defaults to the saved vehicle's name or the id).
lengthnumber · cmInternal cargo-space length, along x (from the front wall toward the door). Required unless vehicle_id is given.
widthnumber · cmInternal cargo-space width, along z. Required unless vehicle_id is given.
heightnumber · cmInternal cargo-space height, along y. Required unless vehicle_id is given.
max_weightnumber · kgMaximum payload. Required unless vehicle_id is given.
quantityintegerHow many identical vehicles of this definition are available.
11–100floor_load_capacitynumber · kg/m²Floor load capacity: 0 or more (0 = no limit).
aux_deckbooleanThe vehicle has a second deck (double-decker).
falseaux_deck_heightnumber · cmSecond deck height above the floor. Required when aux_deck is true.
aux_deck_max_weightnumber · kgLoad limit of the second deck. Required when aux_deck is true.
blocked_areasRect[]Floor zones nothing may stand on (wheel arches, damage, reserved space). Each must lie on the vehicle floor.
xnumber · cmobrigatórioDistance from the front wall to the rectangle's near edge.
znumber · cmobrigatórioDistance from the right wall (z = 0; right as seen from the door looking in) to the rectangle's near edge.
lengthnumber · cmobrigatórioExtent along x.
widthnumber · cmobrigatórioExtent along z.
axle_positionsAcesso mediante pedidonumber[] · cmAxle (support point) positions measured from the front of the cargo area; negative = in front of it. Same length as axle_max_loads. Each between −300 (an axle ahead of the cargo area, e.g. a rigid truck's front axle under the cab) and the vehicle length.
axle_max_loadsAcesso mediante pedidonumber[] · kgMaximum cargo load per axle, in the order of axle_positions. Each greater than 0 and at most 100000.
cog_range_xAcesso mediante pedidonumber · cmAllowed centre-of-gravity deviation from the middle of the length: 0 to length / 2.
cog_range_yAcesso mediante pedidonumber · cmAllowed centre-of-gravity deviation from the middle of the width: 0 to width / 2.
tractor_weightAcesso mediante pedidonumber · kgSemi-trailer axle model: tractor unit mass.
empty_trailer_weightAcesso mediante pedidonumber · kgSemi-trailer axle model: unladen trailer mass.
front_axle_to_middle_axleAcesso mediante pedidonumber · cmSemi-trailer axle model: tractor front axle to drive (middle) axle.
front_axle_to_tractor_cogAcesso mediante pedidonumber · cmSemi-trailer axle model: front axle to tractor centre of gravity.
front_axle_to_kingpinAcesso mediante pedidonumber · cmSemi-trailer axle model: front axle to kingpin (fifth wheel).
kingpin_to_rear_axleAcesso mediante pedidonumber · cmSemi-trailer axle model: kingpin to trailer rear axle group.
trailer_cog_to_rear_axleAcesso mediante pedidonumber · cmSemi-trailer axle model: trailer centre of gravity to rear axle group.
trailer_start_to_kingpinAcesso mediante pedidonumber · cmSemi-trailer axle model: trailer front to kingpin.
max_middle_axle_weightAcesso mediante pedidonumber · kgSemi-trailer axle model: legal drive (middle) axle limit.
max_rear_axle_weightAcesso mediante pedidonumber · kgSemi-trailer axle model: legal rear axle group limit.
itemsItem[]obrigatórioItem definitions. Each one may have quantity > 1. At least one.
idstringYour identifier, unique within the request. Results refer to it as item_id. Defaults to template_id.
template_idstringA template id (tpl_…) from GET /v1/templates. Supplies every item field; fields sent next to it override them.
labelstringDisplay label (defaults to the id).
shapestringItem shape. cylinder and drum use radius + height instead of length + width; pallet and drum always stay upright.
boxcylinderpalletbagdrumPredefinição "box"lengthnumber · cmLength. Required unless shape is cylinder or drum.
widthnumber · cmWidth. Required unless shape is cylinder or drum.
heightnumber · cmobrigatórioHeight (the vertical side when the item stands as defined).
radiusnumber · cmRadius. Required when shape is cylinder or drum.
weightnumber · kgobrigatórioWeight of ONE unit.
quantityintegerNumber of identical units.
11–10000stackablebooleanOther items may be placed on top of this one.
truemax_stack_weightnumber · kgMaximum weight that may rest on one unit. 0 = unlimited.
0rotationstringall = any of the six orientations; upright = may only turn around the vertical axis (this side up); fixed = never rotated.
alluprightfixedPredefinição "all"hazardousbooleanDangerous goods: kept low and separated from other hazardous items.
falsepriorityintegerLoad priority. Higher = loaded first and kept when space runs out. 0 = none.
0groupstringName of the group this item belongs to (see groups and options.group_routing).
colorstringDisplay colour as #rrggbb (viewer and PDF only).
nesting_heightnumber · cmTelescoping overlap when identical units stack (nested crates, buckets).
0groupsGroup[]Optional groups (customers, stops, orders). Required for every group an item names when options.group_routing is not "none"; otherwise groups are created from the item group names in order of appearance.
namestringobrigatórioGroup name, referenced by Item.group.
orderintegerLoading order (lower = loaded first). Defaults to the position in the list.
colorstringDisplay colour as #rrggbb.
optionsOptionsPacking options. Every field is optional.
packing_modestringauto = when the listed vehicles are full, more copies of the most suitable vehicle are added (up to the job's vehicle limit); fleet_only = only the listed vehicles are used, anything that does not fit is reported as unplaced.
autofleet_onlyPredefinição "auto"group_routingstringnone = groups are informational; wall = each group gets its own section of the vehicle; routing = groups load in order and a later group may sit on or beside an earlier one but never below it (multi-stop delivery); no_stack = groups load in order side by side, never on top of each other.
nonewallroutingno_stackPredefinição "none"allow_overweightbooleanIgnore vehicle payload limits.
falsemax_stack_itemsintegerMaximum items in one stack. 0 = unlimited.
0max_stack_density_kg_m2number · kg/m²Maximum stack weight per floor area. 0 = unlimited.
0lock_rotationsbooleanKeep the first orientation that fits the vehicle height.
falsegroup_identical_binsbooleanTreat identical vehicles as one pool.
falsetime_limitnumber · sUpper bound on compute time for the whole job. 0 = automatic (capped at max_time_limit_seconds from GET /v1/limits). When the limit is reached the best plan found so far is returned. You pay only for the compute time actually used.
0enforce_axleAcesso mediante pedidobooleanReject placements that overload an axle group, on vehicles that carry all ten axle-model fields.
falseExemplo de pedido
curl -X POST "https://runner.cargoduo.com/v1/estimate" \
-H "Authorization: Bearer $CARGODUO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000
}
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": false
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright"
}
],
"options": {
"packing_mode": "auto"
}
}'const res = await fetch("https://runner.cargoduo.com/v1/estimate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CARGODUO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000
}
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": false
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright"
}
],
"options": {
"packing_mode": "auto"
}
}),
});
const data = await res.json();
console.log(res.status, data);import os
import requests
response = requests.post(
"https://runner.cargoduo.com/v1/estimate",
headers={"Authorization": f"Bearer {os.environ['CARGODUO_API_KEY']}"},
json={
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000,
},
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": False,
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright",
},
],
"options": {
"packing_mode": "auto",
},
},
)
print(response.status_code, response.json())package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
body := strings.NewReader(`{
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000
}
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": false
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright"
}
],
"options": {
"packing_mode": "auto"
}
}`)
req, err := http.NewRequest("POST", "https://runner.cargoduo.com/v1/estimate", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("CARGODUO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.StatusCode, string(out))
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String body = """
{
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000
}
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": false
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright"
}
],
"options": {
"packing_mode": "auto"
}
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://runner.cargoduo.com/v1/estimate"))
.header("Authorization", "Bearer " + System.getenv("CARGODUO_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("CARGODUO_API_KEY"));
var json = """
{
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000
}
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": false
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright"
}
],
"options": {
"packing_mode": "auto"
}
}
""";
var request = new HttpRequestMessage(HttpMethod.Post, "https://runner.cargoduo.com/v1/estimate")
{
Content = new StringContent(json, Encoding.UTF8, "application/json"),
};
var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");<?php
$payload = <<<'JSON'
{
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000
}
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": false
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright"
}
],
"options": {
"packing_mode": "auto"
}
}
JSON;
$ch = curl_init('https://runner.cargoduo.com/v1/estimate');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CARGODUO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), ' ', $response, PHP_EOL;require "net/http"
require "uri"
uri = URI("https://runner.cargoduo.com/v1/estimate")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("CARGODUO_API_KEY")}"
request["Content-Type"] = "application/json"
request.body = <<~'JSON'
{
"reference": "order-1042",
"vehicles": [
{
"id": "trailer",
"type": "trailer",
"name": "13.6 m trailer",
"length": 1360,
"width": 245,
"height": 270,
"max_weight": 24000
}
],
"items": [
{
"id": "pallet-eu",
"label": "Euro pallet",
"length": 120,
"width": 80,
"height": 140,
"weight": 450,
"quantity": 18,
"stackable": false
},
{
"id": "carton-a",
"label": "Carton A",
"length": 60,
"width": 40,
"height": 40,
"weight": 12,
"quantity": 40,
"rotation": "upright"
}
],
"options": {
"packing_mode": "auto"
}
}
JSON
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts response.code, response.bodyExemplo de resposta
{
"valid": true,
"errors": [],
"warnings": [],
"items": 58,
"max_vehicles": 3,
"estimated_cost": {
"min_credits": 0.26,
"max_credits": 1.11
},
"estimated_seconds": 90,
"balance": {
"available_credits": 147.75
}
}Respostas
200OKValidation result and price range.
NomeTipoObrigatórioDescriçãovalidbooleanbooleanNãoThe request would be accepted by POST /v1/pack.
errorsErrorDetail[]ErrorDetail[]NãoValidation errors (empty when valid).
pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.
warningsWarning[]Warning[]NãoNon-blocking remarks.
codestringstringNãoMachine code.
messagestringstringNãoEnglish explanation.
itemsintegerintegerNãoTotal item units.
max_vehiclesintegerintegerNãoMost vehicles the job may load.
estimated_costCostRangeCostRangeNãoPrice range in credits.
min_creditsnumber · creditsnumber · creditsNãoLowest plausible price (fewest vehicles, no compute).
max_creditsnumber · creditsnumber · creditsNãoWorst case: max_vehicles loaded and the full compute budget used. This is what POST /v1/pack reserves.
estimated_secondsnumber · snumber · sNãoCompute budget the job would get (an upper bound; most jobs finish sooner).
balanceEstimateBalanceEstimateBalanceNãoYour available credits.
available_creditsnumber · creditsnumber · creditsNão400Bad request
invalid_jsoninvalid_jsonThe body is not valid JSON or a field has the wrong type.
Todos os códigos de erroNomeTipoObrigatórioDescriçãoerrorErrorBodyobrigatórioErrorBodySimcodestringobrigatóriostringSimMachine code (snake_case). Branch on this, never on
message.messagestringobrigatóriostringSimEnglish explanation.
request_idstringobrigatóriostringSimSame as the X-Request-Id header. Quote it when contacting support.
detailsErrorDetail[]ErrorDetail[]NãoPer-field problems (
validation_failed).pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.
401Unauthorized
unauthorizedkey_revokedkey_expiredunauthorizedMissing, malformed or unknown API key.key_revokedThe key was revoked.key_expiredThe key passed its expiry date.
Todos os códigos de erroNomeTipoObrigatórioDescriçãoerrorErrorBodyobrigatórioErrorBodySimcodestringobrigatóriostringSimMachine code (snake_case). Branch on this, never on
message.messagestringobrigatóriostringSimEnglish explanation.
request_idstringobrigatóriostringSimSame as the X-Request-Id header. Quote it when contacting support.
detailsErrorDetail[]ErrorDetail[]NãoPer-field problems (
validation_failed).pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.
403Forbidden
ip_not_allowedsubscription_inactiveaccount_inactivescope_missingip_not_allowedThe calling IP is not on the key's allowlist.subscription_inactiveThe organization has no active subscription that includes the API.account_inactiveThe organization is suspended, or has no owner whose account is active.scope_missingThe key lacks a scope this endpoint needs.
Todos os códigos de erroNomeTipoObrigatórioDescriçãoerrorErrorBodyobrigatórioErrorBodySimcodestringobrigatóriostringSimMachine code (snake_case). Branch on this, never on
message.messagestringobrigatóriostringSimEnglish explanation.
request_idstringobrigatóriostringSimSame as the X-Request-Id header. Quote it when contacting support.
detailsErrorDetail[]ErrorDetail[]NãoPer-field problems (
validation_failed).pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.
413Payload too large
payload_too_largepayload_too_largeThe request body exceeds 10 MB.
Todos os códigos de erroNomeTipoObrigatórioDescriçãoerrorErrorBodyobrigatórioErrorBodySimcodestringobrigatóriostringSimMachine code (snake_case). Branch on this, never on
message.messagestringobrigatóriostringSimEnglish explanation.
request_idstringobrigatóriostringSimSame as the X-Request-Id header. Quote it when contacting support.
detailsErrorDetail[]ErrorDetail[]NãoPer-field problems (
validation_failed).pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.
429Too many requests
rate_limitedrate_limitedToo many requests in the current minute, hour or day (per key or per organization), or more than 60 failed authentications per minute from your IP address.
Todos os códigos de erroNomeTipoObrigatórioDescriçãoerrorErrorBodyobrigatórioErrorBodySimcodestringobrigatóriostringSimMachine code (snake_case). Branch on this, never on
message.messagestringobrigatóriostringSimEnglish explanation.
request_idstringobrigatóriostringSimSame as the X-Request-Id header. Quote it when contacting support.
detailsErrorDetail[]ErrorDetail[]NãoPer-field problems (
validation_failed).pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.
500Internal server error
internal_errorinternal_errorSomething failed on our side.
Todos os códigos de erroNomeTipoObrigatórioDescriçãoerrorErrorBodyobrigatórioErrorBodySimcodestringobrigatóriostringSimMachine code (snake_case). Branch on this, never on
message.messagestringobrigatóriostringSimEnglish explanation.
request_idstringobrigatóriostringSimSame as the X-Request-Id header. Quote it when contacting support.
detailsErrorDetail[]ErrorDetail[]NãoPer-field problems (
validation_failed).pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.
503Service unavailable
api_disabledapi_disabledThe API is temporarily disabled (maintenance) or switched off for the organization.
Todos os códigos de erroNomeTipoObrigatórioDescriçãoerrorErrorBodyobrigatórioErrorBodySimcodestringobrigatóriostringSimMachine code (snake_case). Branch on this, never on
message.messagestringobrigatóriostringSimEnglish explanation.
request_idstringobrigatóriostringSimSame as the X-Request-Id header. Quote it when contacting support.
detailsErrorDetail[]ErrorDetail[]NãoPer-field problems (
validation_failed).pathstringstringNãoJSON path of the offending field, e.g. items[3].length.
codestringstringNãorequired,invalid_value,out_of_range,duplicate_id,unknown_vehicle,unknown_template,type_not_allowed,unknown_group,does_not_fit,too_many_items,too_many_vehicles,unknown_field,invalid_json.messagestringstringNãoEnglish explanation.