API de Carregamento
Envie a carga e receba um plano de carregamento otimizado e fisicamente válido — posições, metros de carga, pés lineares e posições de paletes faturadas. O mesmo mecanismo usado no aplicativo, validado continuamente com layouts reais de despachantes. Acesso ao sandbox em todos os planos; acesso em produção no plano Enterprise.
Comece rapidamente
- Faça login → clique no seu nome → API → gere uma chave.
- Envie um trabalho de carregamento (este é executado no sandbox — gratuito em todos os planos):
curl -X POST https://hansatic.com/api/v1/pack \
-H "Authorization: Bearer hk_live_..." \
-H "Content-Type: application/json" \
-d '{
"vehicle": "CURTAINSIDER_136",
"objective": "ldm",
"sandbox": true,
"items": [{
"name": "Machine crate",
"length": 2300, "width": 750, "height": 1400,
"weight": 300, "quantity": 7,
"stackable": false, "tiltable": false
}]
}'{
"job_id": "5e3617d1-abe4-4549-b7e6-d18c6baf814f",
"status": "queued",
"sandbox": true,
"status_url": "https://hansatic.com/api/v1/jobs/5e3617d1-..."
}Consulte o status_url (com o mesmo cabeçalho de autenticação) até que status seja "done":
{
"job_id": "5e3617d1-...",
"status": "done",
"result": {
"placed_count": 7,
"unplaced_count": 0,
"units": "metric",
"metrics": {
"ldm_m": 5.25,
"span_mm": 5250,
"linear_ft": 17.2,
"pallet_positions_eur": 14,
"total_weight_kg": 2100,
"overlaps": 0
},
"items": [
{ "id": "...", "name": "Machine crate", "placed": true,
"x": 8370, "y": 0, "z": 0,
"rotation_deg": 90, "tilt_deg": 0, "...": "..." }
],
"plan_url": "https://hansatic.com/en/app/plans/..."
}
}Endpoints
POST /api/v1/pack
Valida e enfileira um trabalho de carregamento. Retorna 202 com um job_id. Suporta o cabeçalho Idempotency-Key — novas tentativas com a mesma chave retornam o trabalho original em vez de processar o carregamento duas vezes.
GET /api/v1/jobs/{id}
Status do trabalho e, quando concluído, o resultado completo. Os resultados são mantidos por 30 dias; nos planos de produção, ficam armazenados permanentemente no seu workspace.
GET /api/v1/openapi.json
O contrato OpenAPI 3.1 legível por máquina — importe-o no Postman, geradores de código ou aponte sua ferramenta de IA de programação para ele. Os códigos de veículos são injetados a partir do mecanismo ativo, garantindo que esteja sempre atualizado. Abra a especificação ↗
Campos da resposta
O objeto result de um trabalho concluído:
| Campo | Tipo | Descrição |
|---|---|---|
| placed_count / unplaced_count | integer | Quantos itens foram carregados / não couberam. |
| units | "metric" | "imperial" | As unidades em que todos os valores numéricos abaixo são expressos (ecoam a solicitação). |
| metrics.ldm_m | number | Metros de carga — a extensão do bloco de carga (máximo final − mínimo inicial). |
| metrics.linear_ft | number | A mesma extensão em pés lineares (LTL nos EUA). |
| metrics.span_mm | integer | A extensão em mm, sempre métrica. |
| metrics.pallet_positions_eur | integer | null | Posições de paletes EUR faturadas. null quando o layout é grande demais para ser medido. |
| metrics.total_weight_kg | number | Peso carregado, sempre em kg. |
| metrics.overlaps | integer | Pares com interpenetração — sempre 0 em um layout válido. |
| items[].placed | boolean | Se o item foi incluído no layout. |
| items[].x / y / z | number | null | Posição nas unidades da solicitação: x a partir da extremidade da porta, y a partir da parede esquerda, z a partir do chão. Todos os três são null quando placed é false. |
| items[].rotation_deg / tilt_deg | 0 | 90 | Orientação: rotação em torno do eixo vertical; tilt = deitado de lado. |
| items[].length / width / height / weight | number | O item conforme enviado, ecoado nas unidades da solicitação. |
| plan_url | string | null | O plano criado no aplicativo. null para trabalhos no sandbox. |
Versionamento e estabilidade
O contrato é versionado no caminho (/api/v1/). Dentro da v1, as alterações são apenas aditivas — novos campos opcionais na solicitação, novos campos na resposta, novos códigos de veículos e códigos de erro podem ser adicionados, e os clientes devem ignorar campos que não reconhecem. Campos existentes nunca mudam de significado ou tipo, e nada é removido. Uma mudança incompatível resulta em um novo caminho de versão, com a v1 mantida em paralelo por pelo menos 12 meses e aviso de descontinuação enviado por e-mail para todos os workspaces com uma chave ativa.
Campos da solicitação
| Campo | Tipo | Descrição |
|---|---|---|
| vehicle | string | Um código de veículo das tabelas abaixo. Ou passe {customVehicleId} (um veículo da frota do seu workspace). |
| objective | "ldm" | "pallets" | Minimizar metros de carga ou minimizar posições de paletes faturadas. Padrão "ldm". |
| units | "metric" | "imperial" | Como as dimensões e pesos dos itens são interpretados E retornados: mm/kg (padrão) ou pol/lb. As posições na resposta seguem as mesmas unidades. |
| items | array, required | A lista de carga (campos abaixo). |
| sandbox | boolean | Modo de teste: resultado completo, nada é persistido. Disponível em todos os planos. |
| name | string | Nome do plano (modo produção). |
| ldm_limit_m | number | Restringe a carga aos primeiros N metros de carga (caminhões). |
| budget_ms | number | Orçamento de tempo de otimização (produção; padrão 30000, máximo 300000). |
| callback_url | https URL | Envia o resultado via POST quando o trabalho for concluído, assinado (veja Webhooks). |
Campos dos itens
| Campo | Tipo | Descrição |
|---|---|---|
| length / width / height | number, required | Dimensões do item, interpretadas nas unidades da solicitação (mm por padrão, polegadas com "units": "imperial"). |
| weight | number, required | Peso do item (kg por padrão, lb com "units": "imperial"). |
| quantity | integer, default 1 | Expande para unidades individuais. |
| name | string, optional | Exibido no plano e na resposta. |
| stackable | boolean, default true | Permite que outros itens sejam colocados em cima deste. |
| max_stack | number, optional | Peso máximo que este item pode suportar em cima (mesmas unidades do peso). |
| fragile | boolean, default false | Itens frágeis são colocados apenas nas camadas superiores. |
| tiltable | boolean, default true | Se o item pode ser colocado de lado. |
| destination_stop | integer, default 1 | Parada de entrega para carregamento LIFO em múltiplas paradas. |
Códigos de veículos
Gerados a partir das especificações do mecanismo ativo. Veículos personalizados da frota do seu workspace funcionam via custom_vehicle_id.
Caminhões e reboques
| Código | Veículo | Interior (C×L×A) | Carga útil |
|---|---|---|---|
| CURTAINSIDER_136 | 13.6m Curtainsider | 13.62 × 2.48 × 2.70 m | 24 t |
| BOX_136 | 13.6m Box Trailer | 13.62 × 2.46 × 2.68 m | 24 t |
| MEGA_136 | 13.6m Mega Trailer | 13.62 × 2.48 × 3.00 m | 22.5 t |
| MEGA_CURTAIN_136 | 13.6m Mega Curtainsider | 13.62 × 2.48 × 3.00 m | 22 t |
| FLATBED_136 | 13.6m Flatbed | 13.62 × 2.48 × 3.00 m | 25 t |
| REEFER_136 | 13.6m Reefer | 13.32 × 2.44 × 2.54 m | 22 t |
| CURTAINSIDER_75 | 7.5m City Curtainsider | 7.50 × 2.48 × 2.70 m | 12 t |
| SWAPBODY_715 | 7.15m Swap Body | 7.15 × 2.48 × 2.70 m | 12 t |
| SWAPBODY_745 | 7.45m Swap Body | 7.45 × 2.48 × 2.70 m | 12 t |
| DRY_VAN_53 | 53ft Dry Van | 16.15 × 2.59 × 2.74 m | 20 t |
| FLATBED_53 | 53ft Flatbed | 16.15 × 2.59 × 3.66 m | 22 t |
| REEFER_53 | 53ft Reefer | 15.85 × 2.46 × 2.59 m | 18.5 t |
| CURTAINSIDER_125_CN | 12.5m Curtainsider (CN) | 12.50 × 2.50 × 2.80 m | 27 t |
| FLATBED_40_IN | 40ft Flatbed (IN) | 12.19 × 2.50 × 3.50 m | 26 t |
| BOX_138_BR | 13.8m Box Van (BR) | 13.80 × 2.50 × 2.90 m | 28 t |
| CURTAINSIDER_12_ZA | 12m Curtainsider (ZA) | 12.00 × 2.48 × 2.70 m | 28 t |
Contêineres
| Código | Contêiner | Interior (C×L×A) | Carga útil |
|---|---|---|---|
| 20DC | 20' Dry Container | 5.89 × 2.35 × 2.39 m | 21.727 t |
| 20HC | 20' High Cube | 5.89 × 2.35 × 2.70 m | 21.58 t |
| 40DC | 40' Dry Container | 12.03 × 2.35 × 2.39 m | 26.63 t |
| 40HC | 40' High Cube | 12.03 × 2.35 × 2.70 m | 26.58 t |
| 45HC | 45' High Cube | 13.56 × 2.35 × 2.70 m | 25.68 t |
| 20OT | 20' Open Top | 5.89 × 2.35 × 2.39 m | 21.64 t |
| 40OT | 40' Open Top | 12.03 × 2.35 × 2.39 m | 26.58 t |
| 20RF | 20' Reefer | 5.44 × 2.29 × 2.27 m | 21 t |
| 40RF | 40' Reefer | 11.58 × 2.29 × 2.21 m | 25.6 t |
| 40RFHC | 40' Reefer High Cube | 11.58 × 2.29 × 2.54 m | 25.88 t |
| 53DC | 53' Domestic | 16.15 × 2.59 × 2.90 m | 26 t |
Níveis de acesso e limites
| Sandbox (todos os planos) | Produção (Enterprise) | |
|---|---|---|
| Chamadas | 25 bem-sucedidas / mês | 5.000 carregamentos bem-sucedidos / mês |
| Itens por lista de carga | 20 | 5,000 |
| Trabalhos simultâneos | 1 | 10 |
| Orçamento de otimização | 10 s | 30 s padrão, até 300 s |
| Persistência | Nada é armazenado | Cada carregamento cria um plano real no seu workspace |
Apenas carregamentos bem-sucedidos são contabilizados — validações e jobs com falha nunca são cobrados na cota. Ambos os contadores são reiniciados no dia 1º (UTC). Os resultados da sandbox são completos e sem limitações — os limites são a barreira, não o resultado. Precisa de mais de 5.000 carregamentos por mês? Fale conosco sobre preços para volumes elevados e licenciamento OEM.
Webhooks
Passe callback_url para receber o resultado via POST quando o trabalho for concluído. Cada callback inclui X-Hansatic-Signature: um HMAC-SHA256 do corpo bruto com o segredo do webhook da sua chave (exibido uma vez na criação da chave). Verifique-o:
const crypto = require('crypto');
function verify(rawBody, signatureHeader, webhookSecret) {
const expected = crypto.createHmac('sha256', webhookSecret)
.update(rawBody).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(signatureHeader));
}A entrega é feita em uma única tentativa com timeout de 5s — o status_url permanece sempre como a fonte da verdade.
Erros
Todos os erros seguem o formato { "error": { "code", "message", ... } } — código legível por máquina, mensagem legível por humanos e field quando um campo específico da entrada está incorreto.
| Código | HTTP | Significado |
|---|---|---|
| invalid_key | 401 | Chave de API ausente, malformada ou revogada. |
| invalid_json | 400 | O corpo não é um JSON válido. |
| invalid_vehicle | 400 | Código de veículo ou {customVehicleId} desconhecido. |
| invalid_items | 400 | Um campo de item está ausente, não é numérico ou está fora do intervalo válido. |
| suspicious_dimensions | 400 | Todas as dimensões abaixo de 100mm — provavelmente polegadas enviadas como mm. Passe "units": "imperial". |
| invalid_units | 400 | units deve ser "metric" ou "imperial". |
| invalid_objective | 400 | objective deve ser "ldm" ou "pallets". |
| invalid_callback | 400 | callback_url deve ser https. |
| too_many_items | 400 | A lista de carga excede o limite de itens para o seu nível de acesso. |
| upgrade_required | 402 | O modo produção requer o plano Enterprise. Use o sandbox ou faça upgrade. |
| sandbox_limit_reached | 402 | Cota mensal do sandbox esgotada — reinicia no dia 1º. |
| quota_exceeded | 402 | Cota mensal de 5.000 carregamentos atingida — reinicia no dia 1º. Para volumes maiores: entre em contato. |
| too_many_jobs | 429 | Limite de trabalhos simultâneos atingido. Consulte os trabalhos em execução e tente novamente. |
| not_found | 404 | Nenhum trabalho encontrado para este workspace. |
Dúvidas, limites maiores ou um conector que você precisa (Zapier, Excel, MCP)? hello@hansatic.com