Packing API

Отправьте груз и получите оптимизированный, физически корректный план загрузки — с указанием позиций, погрузочных метров, линейных футов и расчётных паллетных мест. Тот же движок, что и в приложении, постоянно проверяемый на реальных схемах диспетчеров. Доступ к песочнице на каждом тарифном плане; продакшен-доступ — на тарифе Enterprise.

Быстрый старт

  1. Войдите в систему → нажмите на своё имя → API → сгенерируйте ключ.
  2. Отправьте задание на упаковку (этот пример выполняется в песочнице — бесплатно на каждом тарифном плане):
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-..."
}

Проверяйте status_url (с тем же заголовком авторизации), пока status не станет "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/..."
  }
}

Эндпоинты

POST /api/v1/pack

Проверяет и ставит в очередь задание на упаковку. Возвращает 202 с job_id. Поддерживает заголовок Idempotency-Key — повторные запросы с тем же ключом возвращают исходное задание вместо повторной упаковки.

GET /api/v1/jobs/{id}

Статус задания и, по завершении, полный результат. Результаты хранятся 30 дней; на продакшен-тарифах данные остаются в вашем рабочем пространстве навсегда.

GET /api/v1/openapi.json

Машинно-читаемая спецификация OpenAPI 3.1 — импортируйте её в Postman, генераторы кода или используйте с инструментами ИИ-программирования. Коды транспортных средств подгружаются из работающего движка, поэтому спецификация всегда актуальна. Открыть спецификацию ↗

Поля ответа

Объект result для завершённого задания:

ПолеТипОписание
placed_count / unplaced_countintegerКоличество размещённых / неразмещённых предметов.
units"metric" | "imperial"Единицы измерения, в которых представлены все числовые значения ниже (дублируются из запроса).
metrics.ldm_mnumberПогрузочные метры — протяжённость грузового блока (максимальный конец − минимальное начало).
metrics.linear_ftnumberТа же протяжённость в линейных футах (для американских LTL-перевозок).
metrics.span_mmintegerПротяжённость в миллиметрах, всегда в метрической системе.
metrics.pallet_positions_eurinteger | nullРасчётные позиции EUR-паллет. Значение null, если схема слишком велика для измерения.
metrics.total_weight_kgnumberОбщий вес размещённых предметов, всегда в килограммах.
metrics.overlapsintegerПары пересекающихся предметов — всегда 0 для корректной схемы.
items[].placedbooleanУдалось ли разместить предмет в схеме.
items[].x / y / znumber | nullПозиция в единицах измерения запроса: x — от торца двери, y — от левой стенки, z — от пола. Все три значения равны null, если placed — false.
items[].rotation_deg / tilt_deg0 | 90Ориентация: поворот вокруг вертикальной оси; tilt — предмет положен на бок.
items[].length / width / height / weightnumberРазмеры предмета из запроса, дублируются в единицах измерения запроса.
plan_urlstring | nullСозданный план в приложении. Значение null для заданий в песочнице.

Версионирование и стабильность

Контракт версионируется в пути (/api/v1/). В рамках v1 изменения только аддитивные — новые необязательные поля запроса, новые поля ответа, новые коды транспортных средств и коды ошибок. Клиенты должны игнорировать нераспознанные поля. Существующие поля никогда не меняют значение или тип, и ничто не удаляется. Критические изменения ведут к созданию нового пути версии, при этом v1 поддерживается параллельно не менее 12 месяцев с уведомлением об устаревании по электронной почте каждому рабочему пространству с активным ключом.

Поля запроса

ПолеТипОписание
vehiclestringКод транспортного средства из таблиц ниже. Или передайте {customVehicleId} (транспорт из вашего парка).
objective"ldm" | "pallets"Минимизировать погрузочные метры или расчётные паллетные позиции. По умолчанию — "ldm".
units"metric" | "imperial"Единицы измерения для размеров и веса предметов, а также возвращаемых данных: mm/kg (по умолчанию) или in/lb. Позиции в ответе используют те же единицы.
itemsarray, requiredМанифест груза (поля описаны ниже).
sandboxbooleanТестовый режим: полный результат, данные не сохраняются. Доступен на каждом тарифном плане.
namestringНазвание плана (в продакшен-режиме).
ldm_limit_mnumberОграничение загрузки первыми N погрузочными метрами (для грузовиков).
budget_msnumberБюджет времени на оптимизацию (в продакшен-режиме; по умолчанию 30000, максимум 300000).
callback_urlhttps URLАдрес для POST-запроса с результатом по завершении задания, подписанный (см. Вебхуки).

Поля предметов

ПолеТипОписание
length / width / heightnumber, requiredРазмеры предмета в единицах измерения запроса (по умолчанию — миллиметры, дюймы при "units": "imperial").
weightnumber, requiredВес предмета (по умолчанию — килограммы, фунты при "units": "imperial").
quantityinteger, default 1Раскладывается на отдельные единицы.
namestring, optionalОтображается в плане и ответе.
stackableboolean, default trueМожет ли другой груз размещаться поверх этого предмета.
max_stacknumber, optionalМаксимальный вес, который может выдержать предмет сверху (в тех же единицах, что и вес).
fragileboolean, default falseХрупкие предметы размещаются только на верхних уровнях.
tiltableboolean, default trueМожно ли положить предмет на бок.
destination_stopinteger, default 1Пункт доставки для загрузки по принципу LIFO (последним пришёл — первым вышел) при нескольких остановках.

Коды транспортных средств

Сгенерированы на основе актуальных спецификаций движка. Пользовательские транспортные средства из вашего парка работают через custom_vehicle_id.

Грузовики и прицепы

КодТранспортВнутренние размеры (Д×Ш×В)Грузоподъёмность
CURTAINSIDER_13613.6m Curtainsider13.62 × 2.48 × 2.70 m24 t
BOX_13613.6m Box Trailer13.62 × 2.46 × 2.68 m24 t
MEGA_13613.6m Mega Trailer13.62 × 2.48 × 3.00 m22.5 t
MEGA_CURTAIN_13613.6m Mega Curtainsider13.62 × 2.48 × 3.00 m22 t
FLATBED_13613.6m Flatbed13.62 × 2.48 × 3.00 m25 t
REEFER_13613.6m Reefer13.32 × 2.44 × 2.54 m22 t
CURTAINSIDER_757.5m City Curtainsider7.50 × 2.48 × 2.70 m12 t
SWAPBODY_7157.15m Swap Body7.15 × 2.48 × 2.70 m12 t
SWAPBODY_7457.45m Swap Body7.45 × 2.48 × 2.70 m12 t
DRY_VAN_5353ft Dry Van16.15 × 2.59 × 2.74 m20 t
FLATBED_5353ft Flatbed16.15 × 2.59 × 3.66 m22 t
REEFER_5353ft Reefer15.85 × 2.46 × 2.59 m18.5 t
CURTAINSIDER_125_CN12.5m Curtainsider (CN)12.50 × 2.50 × 2.80 m27 t
FLATBED_40_IN40ft Flatbed (IN)12.19 × 2.50 × 3.50 m26 t
BOX_138_BR13.8m Box Van (BR)13.80 × 2.50 × 2.90 m28 t
CURTAINSIDER_12_ZA12m Curtainsider (ZA)12.00 × 2.48 × 2.70 m28 t

Контейнеры

КодКонтейнерВнутренние размеры (Д×Ш×В)Грузоподъёмность
20DC20' Dry Container5.89 × 2.35 × 2.39 m21.727 t
20HC20' High Cube5.89 × 2.35 × 2.70 m21.58 t
40DC40' Dry Container12.03 × 2.35 × 2.39 m26.63 t
40HC40' High Cube12.03 × 2.35 × 2.70 m26.58 t
45HC45' High Cube13.56 × 2.35 × 2.70 m25.68 t
20OT20' Open Top5.89 × 2.35 × 2.39 m21.64 t
40OT40' Open Top12.03 × 2.35 × 2.39 m26.58 t
20RF20' Reefer5.44 × 2.29 × 2.27 m21 t
40RF40' Reefer11.58 × 2.29 × 2.21 m25.6 t
40RFHC40' Reefer High Cube11.58 × 2.29 × 2.54 m25.88 t
53DC53' Domestic16.15 × 2.59 × 2.90 m26 t

Уровни доступа и ограничения

Песочница (на каждом тарифном плане)Продакшен (тариф Enterprise)
Запросы25 успешных в месяц5 000 успешных упаковок / месяц
Предметов в манифесте205,000
Одновременных заданий110
Бюджет оптимизации10 с30 с по умолчанию, до 300 с
Сохранение данныхДанные не сохраняютсяКаждая упаковка создаёт реальный план в вашем рабочем пространстве

Счёт идёт только по успешно выполненным упаковкам — неудачные проверки и задания не расходуют квоту. Оба счётчика сбрасываются 1-го числа (UTC). Результаты в песочнице полные и не урезаны — ограничения касаются только количества запросов, а не качества выходных данных. Нужно больше 5 000 упаковок в месяц? Свяжитесь с нами, чтобы обсудить условия для крупных объёмов и OEM-партнёрства.

Вебхуки

Передайте callback_url, чтобы получить результат через POST при завершении задания. Каждый вебхук содержит X-Hansatic-Signature: HMAC-SHA256 от исходного тела запроса с использованием вебхук-секрета вашего ключа (отображается однократно при создании ключа). Проверяйте подпись:

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));
}

Доставка выполняется однократно с тайм-аутом 5 с — status_url всегда остаётся источником истины.

Ошибки

Все ошибки имеют формат { "error": { "code", "message", ... } } — машинно-читаемый код, понятное человеку сообщение и field, если проблема связана с конкретным полем ввода.

КодHTTPЗначение
invalid_key401Отсутствует, некорректный или отозванный API-ключ.
invalid_json400Тело запроса не является допустимым JSON.
invalid_vehicle400Неизвестный код транспортного средства или {customVehicleId}.
invalid_items400Отсутствует, нечисловое или выходящее за допустимый диапазон поле предмета.
suspicious_dimensions400Все размеры менее 100 мм — вероятно, дюймы переданы как миллиметры. Укажите "units": "imperial".
invalid_units400Поле units должно быть "metric" или "imperial".
invalid_objective400Поле objective должно быть "ldm" или "pallets".
invalid_callback400callback_url должен использовать протокол https.
too_many_items400Манифест превышает лимит предметов для вашего уровня доступа.
upgrade_required402Для продакшен-режима требуется тариф Enterprise. Используйте песочницу или обновите тариф.
sandbox_limit_reached402Месячный лимит песочницы исчерпан — сбрасывается 1-го числа.
quota_exceeded402Месячная квота в 5 000 упаковок исчерпана — сброс счётчика 1-го числа. Для увеличения объёма обратитесь к нам.
too_many_jobs429Достигнут лимит одновременных заданий. Проверьте статус текущих заданий и повторите попытку.
not_found404Задание с таким идентификатором не найдено в этом рабочем пространстве.

Вопросы, увеличение лимитов или нужный коннектор (Zapier, Excel, MCP)? hello@hansatic.com