Быстрый старт интеграции
Интеграционный API живёт под /api/v1/integration/*, версионирован и не меняется несовместимо в
рамках v1. Полный справочник — раздел API интегратора слева; он собран из той же
спецификации, по которой работает сама система.
1. Получите ключ
Заголовок раздела «1. Получите ключ»Администратор компании создаёт ключ на экране Управление доступом → API-ключи: имя, скоупы, лимит запросов в минуту (по умолчанию 2000). Значение ключа показывается один раз.
Скоупы:
| Скоуп | Даёт |
|---|---|
orders:write |
создание и изменение заявок, отмена, отказ, переупаковка, оплата, мини-статусы, теги |
orders:read |
pull заявок со статусами |
trips:read |
pull рейсов |
vehicles:read |
чтение машин |
couriers:write |
синхронизация водителей |
Ключ передаётся в каждом запросе:
Authorization: ApiKey <ключ>Проверка, что ключ живой и к какой компании относится:
GET /api/v1/integration/whoami→ { "tenantId": "722d70cb-…", "keyId": "7d95dc4b-…", "scopes": ["orders:write"] }2. Отправьте заявку
Заголовок раздела «2. Отправьте заявку»POST /api/v1/integration/orders/sync — upsert по externalId: повторная отправка с тем же
externalId обновляет заявку, а не создаёт вторую. Это и есть идемпотентность интеграции: безопасно
ретраить и досылать.
{ "externalId": "ERP-000123", "customId": null, "type": "Delivery", "price": 1250.0, "deliveryPrice": 0, "planDeliveryPeriod": { "startDate": "2026-09-03T09:00:00Z", "endDate": "2026-09-03T13:00:00Z" }, "planPickupPeriod": null, "addressFrom": null, "addressTo": { "line": "Bakı, Nizami küç. 10", "lat": 40.3777, "long": 49.8531, "details": null, "commentary": "звонить за 15 минут", "domofon": null, "flat": "12", "floor": "3", "porch": "1" }, "appType": null, "volume": 0.12, "weight": 18.5, "priority": 0, "additionalDetails": null, "details": null, "assembled": true, "statusGroup": null, "relatedToOrderId": null, "assignedDriverId": null, "assignedVehicleId": null, "lines": [ { "code": "SKU-1", "name": "Кофе 1 кг", "productId": "…", "warehouseId": "…", "requestedQty": 10, "weight": 1.0, "volume": 0.002, "dimensions": null, "requiredSkills": null, "priority": null, "unitPrice": 12.5, "role": null } ], "client": { "…": "…" }}Ответ 201 (создано) или 200 (обновлено):
{ "orderId": "…", "shortId": "A7K2Q", "outcome": "Created", "type": "Delivery" }Пакетная отправка — POST /api/v1/integration/orders/sync/bulk; ответ содержит результат по каждому
элементу и ошибки по индексу, одна плохая заявка не роняет пакет.
Что проверяется на входе (иначе 400 с полем и кодом): у каждой строки requestedQty > 0
(orders.line.requestedQty.invalid), вес и объём не отрицательные (orders.line.measure.invalid),
productId и warehouseId существуют в вашей компании и не архивированы
(orders.line.product.notFound, orders.line.warehouse.notFound, поле lines[i].productId /
lines[i].warehouseId), хотя бы у одного адреса есть координаты (orders.coordinates.required).
Водитель и машина из ERP. Если в вашей системе заявка уже закреплена за конкретным водителем и
машиной, передайте оба идентификатора — assignedDriverId и assignedVehicleId (GUID из справочников
PickUpper: GET /api/drivers?externalId=… находит водителя по вашему коду, GET /api/vehicles?search=… —
машину по названию или номеру). Планирование примет пару как данность: заявка не будет отдана другому
водителю, автоплан только построит маршрут по её стопам. Правила: оба поля или ни одного
(orders.assignment.incomplete), водитель существует и не в архиве (orders.assignment.driverNotFound),
машина активна (orders.assignment.vehicleNotFound). Если к моменту планирования водитель или машина
попали в архив, заявка останется незапланированной с причиной planning.assigned_pair_unavailable —
пришлите новую пару повторным sync (null в повторной отправке пару не снимает).
Что обязательно, чтобы заявка попала в план: координаты адреса, окно доставки, вес и объём по строкам. Заявка без габаритов не считается «нулевой» — планировщик откажет с кодом причины.
Повторная отправка и строки. Пока заявка не поставлена на рейс (статусы New, InPlanning) и по
её строкам нет исходов, повторный sync обновляет строки: строка с тем же code сохраняет свой
идентификатор и меняет количество/вес/объём, новый code добавляется, отсутствующий убирается.
Как только заявка спланирована или по ней записан исход, изменённая строка отвечает
409 orders.lines.immutable — правка не теряется молча, ERP узнаёт, что её нужно сделать через
отмену или возврат в интейк. Повторная отправка отменённой заявки возвращает её в работу:
ответ 200, outcome: "Restored", статус New.
3. Заберите статусы
Заголовок раздела «3. Заберите статусы»Pull с курсором, не опрос всей базы:
GET /api/v1/integration/orders?since=2026-09-03T00:00:00Z&limit=200→ { "items": [ … ], "nextCursor": "eyJ…" }GET /api/v1/integration/orders?cursor=eyJ…Курсор непрозрачный; храните последний nextCursor и продолжайте с него — страницы упорядочены по
времени изменения и не теряют и не дублируют строки на границе. null в nextCursor — вы догнали
ленту. То же для рейсов: GET /api/v1/integration/trips.
Статусы заявки: New → InPlanning → Planned → InProgress → FullyDelivered | PartiallyDelivered | Returned | Collected | PartiallyCollected | NotCollected | Refused | Cancelled → Closed.
Заявка на забор (Pickup) и возврат (Return) завершаются статусами Collected (забрано всё),
PartiallyCollected (забрана часть) или NotCollected (ничего не забрано) — там, где доставка
получает FullyDelivered, PartiallyDelivered или Returned. Обмен (Rebox) получает статусы
доставки и становится FullyDelivered, только когда новое передано и старое забрано. Список статусов
может расти: неизвестное значение считайте незавершённым, а не ошибкой.
4. Ошибки и лимиты
Заголовок раздела «4. Ошибки и лимиты»- Любая ошибка — Problem Details с полем
typeиз каталога кодов; ошибки валидации несутerrorsпо полям. - Лимит запросов — на ключ, в минуту. Превышение:
429,type: orders.rate_limited, заголовокRetry-After. - Один ключ — одна компания: данные другой компании через него недоступны на уровне базы.
Что дальше
Заголовок раздела «Что дальше»- Каталог кодов ошибок — генерируется из реестра бэкенда.
- Реестр интеграционных событий — что будет доступно по webhooks.
- Справочник API интегратора — все маршруты, схемы и примеры.