PDF
Розділ: Сутності й поля

Довідник сутностей обміну

Усі типи сутностей обміну ApexSFA: поля payload, ключі ідемпотентності, порядок первинного завантаження, приклади конвертів.

Цей документ описує що саме облікова система може надіслати в ApexSFA і як портал це застосовує: для кожного entity_type — призначення, ключ ідемпотентності, поля payload, семантика delete, залежності, ліміти й формати.

Транспорт (підпис X-Signature, X-Tenant-Id, ліміти, загальні коди відповіді) описано в розділі 3; тут — лише те, що потрібно для побудови конвертів.

Зміст


1. Конверт і ендпоінти

МетодШляхЩо приймає
POST/api/v1/webhooks/1c/inboundодин конверт
POST/api/v1/webhooks/1c/inbound/batch{"items": [конверт, …], "partial": true} — від 1 до 5000 конвертів

Конверт

ПолеТипОбовʼязковеОпис
entity_typestringтакОдин із типів, перелічених у зведеній таблиці. Інше значення → 422 VALIDATION_ERROR.
operationstringтакcreate | update | upsert | delete. create, update і upsert обробляються однаково — як upsert. Окремо поводиться лише delete.
external_idstringтак1–50 символів. Ідентифікатор обʼєкта в обліковій системі (зазвичай GUID). Для багатьох сутностей — ключ ідемпотентності; див. кожну сутність.
payloadobjectні (за замовчуванням {})Поля сутності.

Примітка. Рекомендуємо GUID обʼєкта (36 символів). Ідентифікатори довші за 50 символів не використовуйте.

Відповідь

  • Одиночний конверт, успіх — 200:
JSON
{"data": {"accepted": true, "entity_id": "3f2a9c1e-7b4d-4e0a-9f51-2c8d6a1b0e47", "operation_performed": "upsert", "details": {"upserted": 412, "depleted": 3}}}

details — лічильники обробника (є не в усіх сутностей; напр. {"skipped": "manual_override"}).

  • Одиночний конверт, бізнес-помилка (запис не знайдено, порушене правило) — 422:
JSON
{"error": {"accepted": false, "error": "Product with code_1c=… not found — create it first"}}
  • Батч — 200 з результатом по кожному рядку:
JSON
{"data": {"accepted_count": 2, "failed_count": 1, "results": [
  {"index": 0, "entity_type": "product", "external_id": "…", "accepted": true, "entity_id": "…", "operation_performed": "upsert", "error": null, "details": null},
  {"index": 1, "entity_type": "price_list_item", "external_id": "…", "accepted": false, "entity_id": null, "operation_performed": null, "error": "Product with code_1c=… not found — create it first", "details": null}
]}}
  • partial: true (за замовчуванням) — кожен конверт у власній точці збереження; помилка одного не скасовує інших. Будь-яка помилка рядка стає accepted: false з текстом, а не помилкою всього пакета.
  • partial: false — увесь батч атомарно: на першій бізнес-помилці все відкочується, відповідь 422 {"error": {"code": "BATCH_ATOMIC_FAILURE", "message": "…", "accepted_so_far": N, "failed_at_index": N}}. У цьому режимі details по рядках не повертаються.
  • Порожній items → 200 з нулями (легальний «порожній хвіст» вигрузки).
  • Понад 5000 конвертів → 422 VALIDATION_ERROR з текстом batch too large.

Порада. Завжди надсилайте дані через /inbound/batch з partial: true — так кожен рядок отримує власний результат і текст помилки.

Постобробка лише батчу. Після батчу, у якому був хоча б один agent, портал підвʼязує документи обліку (goods_document, cash_document, борги), що прийшли раніше за торгового. Після батчу з counterparty — долінковує ієрархію контрагентів (дитина, що прийшла раніше за папку-батька). В одиночному ендпоінті цього не відбувається.


2. Загальні правила

Ідемпотентність. Повтор того самого конверта безпечний: майже всі сутності — upsert за природним ключем (зазвичай external_id). Окремого ключа запиту (request id) немає. Винятки, де повтор має побічний ефект, позначено в описі сутності (напр. debt_reset видаляє всі борги, trip перебудовує склад рейсу).

Частковий payload. Для більшості довідників поле оновлюється, лише якщо ключ присутній у payload. Відсутній ключ = «не чіпати». Явне null / "" = «очистити» (якщо поле не обовʼязкове).

Ручні правки на порталі. Записи, які редагували на порталі, обмін оновлює лише частково — зазвичай тільки is_active. Відповідь тоді містить details: {"skipped": "manual_override"}. Так поводяться product, manufacturer, counterparty, client_assignment; у agent/driver — поля ПІБ і телефону, виправлені в картці.

Філія. Тенант = одна точка синхронізації з одним рядком філії. Усі склади, торгові, водії, точки й рейси з обміну лягають у філію тенанта, від імені якого прийшов запит. Коди філії в payload (branch_code, branch_external_id, branch_code_1c, filial_code) приймаються, але не читаються.

Рядки. Пробіли по краях обрізаються, невидимі символи нульової ширини видаляються (у довідниках оргструктури, контрагентів, людей, транспорту, обладнання). Більшість текстових полів довідників обрізаються до розміру колонки без помилки. У client і product текстові поля пишуться як є — задовге значення дасть помилку рядка (у partial-батчі — accepted: false).

Числа.

ДеЩо приймається
Документи руху товару, каса, goods_period.totals, обладнання-транспорт (габарити, маса), logistics_productчисло або рядок; кома як десятковий роздільник, пробіли й нерозривні пробіли-тисячники допустимі: "1 234,50"
Дні відстрочки (payment_terms_days, days)7, 7.0, "7", "7,0"
Ціни (price, base_price, discount_percent), суми боргів (amount, remaining_amount), credit_limit, shipped_quantity, shipped_total_amount, кількості залишків (qty)число або рядок з крапкою: 12.5 або "12.50". Кома в цих полях — помилка.
product_stock.items[].amountкома допустима; некоректне значення → null без помилки

Рекомендація: гроші й кількості передавати рядком з крапкою ("1234.50") — так не губиться точність.

Дати й час.

ФорматДеЧасовий пояс
YYYY-MM-DD (зайве після 10-го символу ігнорується)більшість дат (inventory_date, on_date, date_from/date_to, doc_date/due_date боргів, as_of, дати партій)дата без часу
ISO 8601 дата-час YYYY-MM-DDTHH:MM:SS[±HH:MM|Z]goods_document.doc_date, cash_document.doc_date, started_at періодів, order_state_period.date_from, equipment_unit.installed_atбез зони = Europe/Kyiv; з зоною — як вказано
ISO 8601 дата-часsale.shipped_atпередавайте з явним зсувом (+03:00 або Z); порожнє значення — поточний момент

Закритий місяць. Для goods_document і goods_period документи з датою в закритому періоді не змінюються. Місяць M закривається з дня sales_close_day (за замовчуванням 10, допустимо 1–28) місяця M+1 за київським часом; адміністратор може відкрити період у налаштуваннях. Для каси (cash_*) такого захисту немає.


3. Рекомендований порядок першого завантаження

Порядок випливає з того, як обробники шукають посилання: «жорстке» посилання (немає — помилка) вимагає, щоб залежність прийшла раніше; «мʼяке» (немає — запис приймається без звʼязку) лише відкладає звʼязок до наступного обміну.

1. branch
2. warehouse, logistics_warehouse
3. supplier → supplier_point
4. price_type
5. manufacturer
6. product_category (батьки раніше за дітей) → product
7. agent, driver
8. vehicle → transport_list
9. counterparty (папки раніше за елементи — бажано) → client
10. client_assignment, manufacturer_price_type, manufacturer_payment_term
11. equipment_type → equipment_unit
12. price_list_item, product_external_code
13. Модуль логістики: logistics_manufacturer / logistics_own_manufacturer,
    logistics_counterparty → logistics_point,
    logistics_product_category → logistics_product → logistics_product_code
14. Залишки: product_stock, wms_stock, product_stock_snapshot, logistics_stock,
    stock_document, excise_marks
15. Документи: sale, logistics_order, debt_reset → debt_document,
    goods_document → goods_period, trip, cash_document + cash_balance → cash_period,
    order_state → order_state_period
ЗалежністьТипЩо буде, якщо залежності ще нема
warehouse, stock_document → філіяжорстка422 «Точка не має рядка філії…»; спершу branch
supplier_point → supplierжорстка422 NotFound
product_category.parent_code_1c → батьківська категоріяжорстка422
product.category_code_1c → категоріямʼякатовар без категорії; звʼязок — при наступному обміні товару
product.manufacturer_external_id → manufacturerмʼякатовар без звʼязку з виробником (текстова назва manufacturer лишається); звʼязок — при наступному обміні товару
price_list_item → productжорстка422 NotFound
price_list_item / client.price_list_code → прайс—прайс створюється автоматично; назва береться з price_type з тим самим code, якщо він уже є, інакше «Прайс {code}»
client.counterparty_external_id → counterpartyмʼякаточка без контрагента
client_assignment → client і agentжорстка422 NotFound
manufacturer_price_type → точкамʼякаdetails.skipped = client_not_found (не помилка)
manufacturer_price_type / manufacturer_payment_term → manufacturerжорстка422 NotFound
manufacturer_payment_term → counterpartyмʼякаdetails.skipped = counterparty_not_found
equipment_unit → equipment_typeжорстка (лише при створенні)422 NotFound
equipment_unit.client_code_1c → точкажорстка422 NotFound
vehicle.driver_external_id → водіймʼякаавто без водія
product_stock / wms_stock → складжорстка422 «Unknown warehouse»
product_stock / wms_stock / product_stock_snapshot → товармʼякарядок пропускається, коди — у details
goods_document → точка, контрагент, торговий, склад, виробник, товармʼякадокумент приймається з кодами й назвами; точку й торгового портал допривʼяже, коли вони прийдуть
debt_document → точка—точку (і контрагента) буде створено з полів боргу, якщо передано client_name
sale → заявка порталужорстка422 NotFound
trip (без number) → водійжорстка422 NotFound
logistics_point → logistics_counterpartyжорстка422 NotFound

4. Зведена таблиця entity_type

entity_typeГрупаПризначенняКлюч пошуку існуючогоdelete
branchОргструктураРядок філії точки синхронізаціїєдиний рядок філії тенанта; external_id привʼязується один разігнорується
warehouseОргструктураСкладexternal_idis_active=false
supplierПостачанняПостачальникexternal_idis_active=false
supplier_pointПостачанняТочка постачання постачальникаexternal_idis_active=false
price_typeПостачанняТип ціниexternal_idis_active=false
manufacturerКаталогВиробникexternal_idis_active=false
product_categoryКаталогКатегорія товарів (дерево)external_idмʼяке видалення
productКаталогТоварexternal_idмʼяке видалення
price_list_itemКаталогЦіна товару в прайсі(прайс за price_list_code, товар за product_code_1c)фізичне видалення
product_external_codeКаталогАртикул товару в мережі(товар, sync_kind_external_id)фізичне видалення
manufacturer_price_typeКаталогТип цін точки по виробнику(точка, виробник)мʼяке видалення
manufacturer_payment_termБоргиВідстрочка контрагента по виробнику(контрагент, виробник)мʼяке видалення
counterpartyКлієнтиКонтрагент (юрособа)external_idis_active=false
clientКлієнтиТоргова точкаexternal_idмʼяке видалення
client_assignmentКлієнтиПривʼязка точки до торгового(точка, торговий)видалення привʼязки
agentЛюдиТорговийexternal_idдоступ знято, запис лишається
driverЛюдиВодій / експедиторexternal_idне підтримується
vehicleТранспортАвтомобільexternal_idis_active=false
transport_listТранспортСписки авто й водіїв, що беруть участь в обміні— (снапшот)—
equipment_typeОбладнанняТип обладнанняexternal_idis_active=false
equipment_unitОбладнанняОдиниця обладнанняexternal_idмʼяке видалення
product_stockЗалишкиЗнімок залишків складу без партійсклад warehouse_code_1cне підтримується
product_stock_snapshotЗалишкиЗалишок складу на кінець дня (історія)(склад, дата)—
wms_stockЗалишкиЗнімок партій WMS-складусклад warehouse_code_1cне підтримується
stock_documentЗалишкиДокумент інвентаризації для ревізіїexternal_idне підтримується
excise_marksЗалишкиПакет акцизних марокУІ маркине підтримується
saleПродажіФакт відвантаження по заявці порталуid / номер заявки—
goods_documentПродажіДокумент руху товару (продажі, повернення, надходження…)external_idis_posted=false
goods_periodПродажіКінець вигрузки вікна + контрольні суми— (кожен конверт — новий запуск)—
debt_resetБоргиПовне скидання боргів перед новою вигрузкою——
debt_documentБоргиДокумент заборгованості точкиexternal_idstatus=closed
cash_documentКасаПКО / РКО / банківська випискаexternal_idis_posted=false
cash_balanceКасаЗалишок по касі / рахунку(account_code, вид коштів)фізичне видалення
cash_periodКасаКінець вигрузки вікна каси——
order_stateЗаявкиСтан заявки порталу в облікуexternal_id або order_number—
order_state_periodЗаявкиКінець списку станів → скасування зниклих——
tripРейсиХодка → рейс порталу / призначення водіяexternal_idрейс скасовано
logistics_orderЛогістикаЗаявка, створена в облікуexternal_idскасування, якщо не в рейсі
logistics_manufacturerЛогістикаВиробник із позначкою логістикияк manufacturerяк manufacturer
logistics_own_manufacturerЛогістикаВиробник модуля логістикиexternal_idis_active=false
logistics_counterpartyЛогістикаКонтрагент логістикиexternal_idis_active=false
logistics_pointЛогістикаТочка доставки логістикиexternal_idis_active=false
logistics_warehouseЛогістикаСклад логістикиexternal_idis_active=false
logistics_product_categoryЛогістикаКатегорія каталогу логістикиexternal_idis_active=false
logistics_productЛогістикаТовар каталогу логістикиexternal_idis_active=false
logistics_product_codeЛогістикаКод товару логістики в мережі(товар, kind_external_id)фізичне видалення
logistics_stockЛогістикаЗнімок залишків складу логістикисклад warehouse_code_1cне підтримується

«Не підтримується» = delete повертає 422.


5. Оргструктура й постачання

branch

Філія — це сама точка синхронізації. Обмін записує в її єдиний рядок GUID і адресу; другого рядка філії не створює.

  • Ключ. Береться єдиний рядок філії тенанта. Якщо в нього ще немає GUID — external_id записується в нього (якщо цей GUID не стоїть на іншому рядку). Якщо рядка немає взагалі — створюється (тоді name обовʼязкове).
  • Інший GUID (друга філія довідника обліку) → 200, details.skipped = "other branch of the same point", нічого не змінюється.
  • Повтор — ідемпотентний.
ПолеТипОбовʼязковеОпис
namestring ≤300лише якщо рядка філії ще немаєНазва. Існуючу назву обмін не перезаписує (її веде адміністратор платформи).
addressstring ≤2000ніАдреса.

delete: 200, details.skipped = "point branch is not deactivated" — філія не вимикається. Якщо рядка філії немає — 422.

При першій привʼязці GUID етапи заявки виставляються так, що етап «перевірка» на порталі вимкнено (цикл заявки веде облікова система).

warehouse

Склад торгового контуру.

  • Ключ: external_id. Склад завжди належить філії тенанта.
  • Новий склад веде залишки з облікової системи (product_stock).
ПолеТипОбовʼязковеОпис
namestring ≤300так при створенніПорожнім затерти не можна (422).
addressstring ≤2000ні
wms_enabledboolніЗмінюється лише якщо ключ передано. Відсутній ключ не скидає прапорець, увімкнений на порталі.
excise_enabledboolніТак само. Потрібен для excise_marks зі складом.
is_activeboolні
branch_external_id—ніПриймається, не читається.

delete: is_active=false; немає складу — 422.

supplier

Постачальник. Ключ: external_id.

ПолеТипОбовʼязковеОпис
namestring ≤500так при створенні
codestring ≤100ні
tax_idstring ≤50ні
is_activeboolні
counterparty_external_idstringніЗвʼязок з контрагентом; невідомий — ігнорується.

delete: is_active=false; немає — 422.

supplier_point

Точка постачання (адреса відвантаження) постачальника. Ключ: external_id.

ПолеТипОбовʼязковеОпис
supplier_external_idstringтакexternal_id постачальника. Невідомий → 422 «push the supplier first».
namestring ≤500так при створенні
codestring ≤100ні
addressstring ≤500ні
is_activeboolні

delete: is_active=false; немає — 422.

price_type

Тип ціни. Його code збігається з кодом прайсу (price_list_code) у price_list_item і client — з нього береться назва автоматично створеного прайсу.

Ключ: external_id.

ПолеТипОбовʼязковеОпис
namestring ≤500так при створенні
codestring ≤100ні (рекомендовано)Код типу цін = код прайсу.
is_activeboolні

delete: is_active=false; немає — 422.


6. Каталог і ціни

manufacturer

Виробник (бренд-власник), у розрізі якого працюють торгові команди, продажі, борги.

  • Ключ: external_id. Цей самий код передається в інших сутностях як manufacturer_external_id.
  • Запис із ручними правками на порталі: оновлюється лише is_active, details.skipped = "manual_override".
ПолеТипОбовʼязковеОпис
namestring ≤300так при створенні
codestring ≤100ні
tax_numberstring ≤20ніЄДРПОУ / ІПН.
supplier_external_idstringніПостачальник виробника; невідомий → звʼязок скидається в порожній.
is_activeboolні

delete: is_active=false; немає — 422.

product_category

Категорія товарів, дерево.

  • Ключ: external_id.
ПолеТипОбовʼязковеОпис
namestringніПри створенні без name — порожня назва.
parent_code_1cstringніexternal_id батьківської категорії. Невідома → 422 (спершу батьки). Ключ відсутній — батько не змінюється.
slug, code, description, image_urlstringні
sort_orderintні
is_activeboolні

delete: мʼяке видалення; немає — 422.

product

Товар основного каталогу (КПК, B2B, звіти).

  • Ключ: external_id.
  • Повтор: upsert, поля з payload перезаписуються.
  • Ручні правки на порталі: оновлюються лише is_active та is_in_stock, details.skipped = "manual_override".
  • Назва: name завжди пишеться в «назву з обліку»; видима назва змінюється, лише якщо джерелом назви товару обрано облік (на порталі можна обрати інше джерело).
  • Артикул і штрихкод: порожні → null; довші за 50 символів або вже зайняті іншим товаром — поле пропускається (товар приймається, у лозі попередження).
  • Новий штрихкод у товару без фото ставить товар у чергу фонового збагачення (фото, вага, бренд з відкритих каталогів).
ПолеТипОбовʼязковеОпис
namestring ≤300рекомендованоПри створенні без нього — порожня назва.
base_pricenumber/string з крапкоюніБазова ціна; при створенні за замовчуванням 0.
unitstring ≤20ніОдиниця; за замовчуванням шт.
skustring ≤50ніАртикул.
barcodestring ≤50ніШтрихкод.
brandstring ≤100ні
manufacturerstring ≤200ніНазва виробника текстом (показується, поки не встановлено звʼязок).
manufacturer_external_idstringніЗвʼязок з manufacturer (мʼякий). Порожнє значення — розвʼязати.
category_code_1cstringніЗвʼязок з product_category (мʼякий). Не застосовується, якщо категорію перевизначено на порталі.
descriptionstringні
currencystring(3)ніЗа замовчуванням UAH.
vat_ratenumberніСтавка ПДВ, %. За замовчуванням 20.
is_activeboolні
is_in_stockboolніДовідково; наявність визначається залишками (product_stock).
category_1cstring ≤200ніКатегорія з обліку текстом (довідково).
kind_1cstring ≤100ніВид номенклатури (довідково).
is_excisableboolніПідакцизний товар.
pack_sizeintніФасовка (штук в упаковці), мінімум 1; 0/порожнє ігнорується.
weight_kgdecimalні
volume_litersdecimalні
units_per_pallet, units_per_euro_pallet, units_per_block, units_per_box, package_type, pallet_type, uktved, uktved_code, shelf_life_days, unit_barcode, consumer_barcode, height_mm, length_mm, width_mmбудь-якініЛогістичний паспорт товару; зберігається блоком і показується в картці. Порожні й нульові значення ігноруються, решта доливається до вже збережених.

delete: мʼяке видалення; немає — 422.

price_list_item

Ціна товару в прайсі (типі цін).

  • Ключ: пара (прайс за price_list_code, товар за product_code_1c). external_id рекомендовано у вигляді "<price_list_code>:<product_code_1c>" — якщо полів у payload немає, вони беруться з двох половин external_id.
  • Прайс з таким кодом створюється автоматично, якщо його ще немає.
  • Товар має існувати → інакше 422 «create it first».
ПолеТипОбовʼязковеОпис
price_list_codestringтак (або в external_id)Код прайсу = code типу цін.
product_code_1cstringтак (або в external_id)external_id товару.
pricenumber/string з крапкоютак при створенніЦіна.
discount_percentdecimalніЗа замовчуванням 0.
min_quantityintніЗа замовчуванням 1.

delete: запис фізично видаляється; немає — 422.

product_external_code

Артикул товару в мережі (код, під яким товар фігурує в замовленнях мережі). Портал використовує його для розпізнавання файлів замовлень.

  • Ключ: (товар за product_code_1c, sync_kind_external_id). external_id — довільний унікальний ідентифікатор рядка (не використовується для пошуку).
  • Товару немає на порталі → 200, details.skipped = "product not on portal" (не помилка).
ПолеТипОбовʼязковеОпис
product_code_1cstringтакexternal_id товару.
sync_kind_external_idstring ≤200такІдентифікатор виду коду (мережі).
codestring ≤200так (крім delete)Код товару в мережі.
sync_kind_namestring ≤300ніНазва виду коду.

delete: рядок видаляється; немає — 200 без помилки.

manufacturer_price_type

Тип цін, за яким точка купує товари конкретного виробника (перекриває загальний прайс точки).

  • Ключ: (точка client_code_1c, виробник manufacturer_external_id). external_id зберігається; рекомендований формат "<GUID точки>-<код виробника>".
  • Невідома точка → 200, details = {"skipped": "client_not_found", "client_code_1c": "…"}.
  • Невідомий виробник → 422.
  • Відповідь: details.price_list_resolved — чи знайдено прайс з таким кодом (код зберігається завжди; прайс може прийти пізніше).
  • Мʼяко видалений рядок оживає при наступному upsert.
ПолеТипОбовʼязковеОпис
client_code_1cstringтакexternal_id точки.
manufacturer_external_idstringтак
price_list_codestring ≤50так при створенніКод типу цін.

delete: якщо передано обидва ключі — пошук за парою; інакше — за external_id. Мʼяке видалення; немає — 422.


7. Контрагенти, точки, привʼязки

counterparty

Контрагент — юридична особа (власник точок, постачальник).

  • Ключ: external_id.
  • Ручні правки на порталі: оновлюється лише is_active, details.skipped = "manual_override".
  • Нова відстрочка (payment_terms_days) перераховує терміни оплати відкритих боргів точок цього контрагента, у яких немає власної відстрочки (лише документи, де облік не дав пізнішого терміну сам).
ПолеТипОбовʼязковеОпис
namestring ≤500так при створенні
kindbuyer | supplier | bothніЗа замовчуванням buyer. Інше значення → 422.
codestring ≤100ні
tax_numberstring ≤50ніІПН.
edrpoustring ≤20ні
contact_person, director, bank_namestring ≤200ні
bank_ibanstring ≤34ні
legal_address, addressstring ≤2000ні
phonestring ≤20ні
emailstring ≤255ні
external_codesarrayніКоди контрагента в мережах: [{"kind": "…", "code": "…"}] (або масив рядків). Пробіли в коді прибираються, дублі відкидаються. Коди, додані вручну на порталі, зберігаються.
payment_terms_daysintніВідстрочка платежу, днів. Некоректне значення — поле пропускається.
is_groupboolніПапка довідника.
parent_external_idstringніБатьківська папка. Ще не прийшла → звʼязок допишеться після батчу, у якому вона прийде (лише через /inbound/batch). Порожнє — відвʼязати.
is_activeboolні

delete: is_active=false; немає — 422.

client

Торгова точка — адреса, куди ходить торговий і везуть товар.

  • Ключ: external_id. Цей же код передається як client_code_1c в інших сутностях.
  • При створенні точки портал допривʼязує до неї документи руху товару, що прийшли раніше з цим кодом.
  • Точка завжди належить філії тенанта.
ПолеТипОбовʼязковеОпис
namestring ≤300рекомендованоПри створенні без нього — порожня назва.
addressstringрекомендованоЗміна адреси або міста ставить точку в чергу геокодування (крім точок з координатами, виставленими вручну).
legal_namestring ≤300ні
codestring ≤50ніВнутрішній код точки.
tax_numberstring ≤20ні
contact_personstring ≤200ні
contact_positionstring ≤100ні
phone, phone_secondarystring ≤20ні
emailstring ≤255ні
city, regionstring ≤100ні
directionstring ≤150ніНапрямок доставки (фільтр рейсів).
postal_codestring ≤10ні
countrystring(2)ніЗа замовчуванням UA.
category, channel, typestring ≤50ніКатегорія, канал збуту, тип точки.
notesstringні
external_codesarrayніКоди точки в мережах [{"kind","code"}] — для розпізнавання файлів замовлень. Ручні коди порталу зберігаються.
payment_terms_daysintніВідстрочка, днів. Приймає 7, "7,0". Зміна перераховує терміни відкритих боргів точки.
credit_limitdecimal з крапкоюніnull/"" — без ліміту.
geofence_radius_metersintніРадіус геозони чек-іну.
business_hoursobjectніГрафік роботи (довільний JSON-обʼєкт, зберігається як є).
counterparty_external_idstringніВласник точки. Невідомий або порожній → точка без контрагента.
price_list_codestringніПрайс точки. Прайс із таким кодом створюється, якщо його немає. Порожнє значення — відвʼязати (точка працює за прайсом за замовчуванням).
latitude, longitudenumber/string (кома допустима)ніЗаписуються лише один раз — у точку без координат, і лише якщо координати в зоні роботи філії. Поза зоною — координати визначаються за адресою. Далі обмін координати не змінює (виправляють на порталі).
branch_code, branch_external_id, filial_code—ніПриймаються, не читаються.

delete: мʼяке видалення; немає — 422.

client_assignment

Привʼязка точки до торгового (хто обслуговує точку).

  • Ключ: пара (точка, торговий). external_id для пошуку не використовується.
  • Якщо торгового на порталі обʼєднано з іншим (дубль), привʼязка йде на основного.
  • На точці може бути лише одна основна (primary) привʼязка: якщо вже є основний торговий іншого виробника, нова привʼязка стає secondary.
  • Ручна привʼязка порталу не змінюється: details.skipped = "manual_override".
ПолеТипОбовʼязковеОпис
client_code_1cstringтакexternal_id точки (не видаленої). Невідома → 422.
agent_external_idstringтакexternal_id торгового. Невідомий → 422.
rolestring ≤20ніprimary (за замовчуванням) або secondary.

delete: привʼязка видаляється (ручна — ні). Точка й торговий мусять існувати навіть для delete, інакше 422.


8. Люди й транспорт

agent

Торговий. Створюється як користувач порталу з роллю «торговий».

  • Ключ: external_id.
  • Новий торговий створюється неактивним і без пароля. Якщо agent_kind = "mobile" (або торговий за ознаками «для КПК»), картка одразу активується й отримує запрошення на встановлення пароля (посилання — у картці торгового на порталі). accounting — довідковий запис без доступу.
  • Email: якщо передана пошта вже зайнята, ставиться службова технічна адреса.
  • Відповідь при створенні: details.created = true.
  • Користувач, позначений на видалення на порталі, обміном не оживає й дубль не створюється.
  • Існуючий торговий: ПІБ і телефон оновлюються, якщо їх не виправляли в картці на порталі; роль змінюється лише між «торговий» і «супервайзер»; email не змінюється.
  • Порожній елемент (немає ні імені, ні прізвища) для нового торгового → 200, details.skipped = "no name"; для існуючого → 422.
ПолеТипОбовʼязковеОпис
last_name, first_namestring ≤100так (або name)
namestring ≤200якщо немає last_name/first_nameПовне ПІБ; перше слово — прізвище.
phonestring ≤100ні
emailstring ≤255ніДля accounting не використовується як логін.
agent_kindmobile | accountingніТорговий для КПК чи довідковий. Перехід mobile → accounting знімає доступ і виводить з команд.
positionstring ≤200ніПосада (довідково).
manufacturer_external_id, manufacturer_namestringніВиробник, під яким торговий працює (накопичується список).
manufacturer_access_idsstringніКоди виробників через ;. Ключ присутній → повна синхронізація доступів торгового до виробників (порожній рядок = зняти всі обмеження). Ключ відсутній → доступи не змінюються.
supervisor_external_idstringніЗберігається довідково; підпорядкування будується на порталі.
org_path_names, org_path_idsstring ≤1000ніЛанцюжок папок оргструктури через ;; (від найближчої до кореня). Довідково.
legacy_external_idsarray of stringніСтарі коди цієї ж людини. Записи порталу зі старими кодами обʼєднуються в одного торгового з новим external_id, документи перепривʼязуються.
branch_external_id—ніНе читається.

delete: торговий позначається довідковим (accounting), доступ знімається, торговий виходить з команд; запис і документи лишаються. Невідомий → 200, details.skipped = "unknown". Керівників (роль не «торговий») не вимикає.

driver

Водій або експедитор. Створюється як користувач з роллю «водій», неактивним — доступ до мобільного застосунку видає адміністратор на порталі.

  • Ключ: external_id. На цей код посилаються vehicle.driver_external_id і trip.driver_external_id.
  • Email: зайнята пошта → службова технічна адреса.
  • Існуючий: оновлюються ПІБ і телефон (якщо не виправлені вручну) та реквізити; роль не змінюється.
ПолеТипОбовʼязковеОпис
last_name, first_name / namestringтакБез імені → 422.
phonestring ≤100ні
emailstring ≤255ні
license (або driver_license)string ≤64ніНомер посвідчення.
license_issued_atstring ≤30ніДата видачі посвідчення (текстом).
vehiclestring ≤200ніАвто водія рядком.
rolestring ≤20ніdriver | forwarder (довідково).
codestring ≤50ніТабельний код.
innstring ≤20ні
passport_seriesstring ≤20ні
passport_numberstring ≤30ні

delete: не використовуйте — щоб вивести водія з обміну, передайте transport_list без нього.

vehicle

Автомобіль.

  • Ключ: external_id.
  • Кожен upsert вмикає авто (is_active=true), якщо в payload немає явного is_active.
ПолеТипОбовʼязковеОпис
namestring ≤300так при створенніДержномер / назва.
codestring ≤100ні
brand, modelstring ≤200ні
capacitydecimal з крапкоюніВантажопідйомність. Некоректне — пропускається.
is_hiredboolніНайманий транспорт.
is_accountedboolніОбліковий/необліковий.
driver_external_idstringніОсновний водій. Невідомий → звʼязок порожній, допишеться наступним обміном.
length, width, heightnumber (кома допустима)ніГабарити. Одиниця визначається за величиною: >1000 — мм, >100 — см, інакше — м. Зберігаються в метрах. 0 = не заповнено.
unladen_weight, gross_weightnumber (кома допустима)ніМаса без вантажу / повна. >1000 — кг, інакше — т. Зберігається в тоннах.
is_activeboolні

delete: is_active=false; немає — 422.

transport_list

Повний список авто й водіїв, що беруть участь в обміні. Хто поза списком — неактивне авто й водій «поза списком»; у рейсі з ними буде «Не визначено».

  • Ключ: немає (снапшот). external_id — довільний, operation не впливає.
  • Відповідь: details = {"vehicles_active", "vehicles_off", "drivers_active", "drivers_off"}.
ПолеТипОбовʼязковеОпис
vehiclesarray of string | nullніexternal_id авто, які лишаються активними. null — список порожній, активні всі. Ключ відсутній — авто не змінюються.
driversarray of string | nullніТак само для водіїв і експедиторів.

9. Обладнання

equipment_type

Тип обладнання (модель холодильника, вітрини тощо). Ключ: external_id.

ПолеТипОбовʼязковеОпис
namestring ≤200так при створенні
code, categorystring ≤50ні
brand, modelstring ≤100ні
manufacturerstring ≤200ні
is_activeboolні

delete: is_active=false; немає — 422.

equipment_unit

Конкретна одиниця обладнання та її розміщення на точці.

  • Ключ: external_id.
  • Тип задається лише при створенні; пізніше type_external_id ігнорується.
  • Якщо серійний та інвентарний номери не передано, портал шукає їх у назві типу за шаблонами сер. № … та інв. № … / инв. № ….
  • Зміна точки створює запис в історії переміщень (встановлення / зняття / переміщення) з датою installed_at.
ПолеТипОбовʼязковеОпис
type_external_idstringтак при створенніНевідомий тип → 422.
qr_codestring ≤64ніЗа замовчуванням формується з external_id.
serial_number, inventory_numberstring ≤100ні
client_code_1cstringніТочка, де стоїть обладнання → статус «встановлено». Невідома точка → 422. Порожнє значення — зняти з точки (статус «на складі», якщо був «встановлено»; ремонт/списання не скидаються). Ключ відсутній — розміщення не змінюється.
installed_atISO дата-часніДата встановлення на точку; без зони — Europe/Kyiv. Некоректне — ігнорується. Якщо не передано, а точка змінилась — поточний момент.

delete: мʼяке видалення; немає — 422.


10. Залишки, WMS, акциз

product_stock

Знімок поточних залишків складу без партій — для КПК, B2B і звіту «Залишки».

  • Ключ: склад warehouse_code_1c (external_id конверта не використовується для пошуку).
  • Повна заміна (REPLACE): товари складу, яких немає в знімку, обнуляються (рядок не видаляється).
  • Склад має існувати й бути активним, інакше 422. Склад, що веде залишки у WMS (залишки ведуться у WMS), → 200 з details.skipped (знімок пропущено, не помилка).
  • Невідомі товари пропускаються, їхні коди (до 50) — у details.skipped_unknown_products.
  • Дублікат коду в items — діє останній.
  • Відʼємний залишок записується як 0.
  • Одночасно оновлюється денний зріз за сьогодні (для історії залишків).
  • Відповідь: details = {"upserted", "depleted", "touched", "skipped_unknown_products"}.
ПолеТипОбовʼязковеОпис
warehouse_code_1cstringтакexternal_id складу.
itemsarrayтакПорожній масив = обнулити весь склад.
items[].product_code_1cstringтакexternal_id товару.
items[].qtynumber/string з крапкоюні""/null = 0. Кома → 422.
items[].amountdecimalніСобівартість залишку; некоректне → null.

delete: 422 (не підтримується).

product_stock_snapshot

Залишок складу на кінець конкретного дня — для історії залишків і днів запасу. Поточний залишок не змінює.

  • Ключ: (склад, on_date). Повтор за той самий день перезаписує зріз.
  • День вважається вигруженим повністю: товари зрізу цього складу за цю дату, яких немає в конверті, обнуляються.
  • Склад шукається без перевірки активності; невідомий → 422. Невідомі товари пропускаються (details.unknown_products — кількість).
  • Відповідь: details = {"on_date", "rows", "unknown_products"}.
ПолеТипОбовʼязковеОпис
warehouse_code_1cstringтак
on_dateYYYY-MM-DDтакНе в майбутньому, інакше 422.
items[].product_code_1cstringтакРядки без коду або не-обʼєкти пропускаються.
items[].qtynumber/string з крапкоюні
items[].amountdecimalні

wms_stock

Повний знімок партій WMS-складу.

  • Ключ: склад warehouse_code_1c; партія — за batches[].external_id.
  • Склад має існувати й бути активним (WMS-модуль на складі вмикати не обовʼязково — партії лягають заздалегідь).
  • Вхідна партія спершу «усиновлює» тимчасову партію порталу з тим самим товаром і номером партії (створену при прийманні до обміну) — дубля не буде.
  • Партія з GUID, який уже належить іншому товару, пропускається (batches_skipped_conflict).
  • Повна заміна: партії складу, яких немає в знімку, обнуляються (не видаляються). Дублікати партії в знімку — кількості сумуються.
  • Невідомі товари пропускаються (details.skipped_unknown_products).
  • Ліміт: 10 000 партій у конверті, понад — 422.
  • Відповідь: details = {"batches_upserted", "batches_adopted", "batches_created", "batches_skipped_conflict", "stocks_updated", "stocks_depleted", "skipped_unknown_products"}.
ПолеТипОбовʼязковеОпис
warehouse_code_1cstringтак
products[].product_codestringтакexternal_id товару.
products[].batches[].external_idstringтакІдентифікатор партії.
products[].batches[].batch_numberstringтакНомер партії.
products[].batches[].manufacture_dateYYYY-MM-DDніНекоректна дата → 422.
products[].batches[].expiry_dateYYYY-MM-DDні
products[].batches[].qtynumber/string з крапкоюніВідʼємне → 0.

delete: 422.

stock_document

Документ інвентаризації, який облік передає на портал для перерахунку (ревізії) комірником або аудитором.

  • Ключ: external_id.
  • Повтор: рядки повністю замінюються, але лише поки документ у статусі new. Якщо його вже взяли в роботу — 422.
  • Ліміт: 5000 рядків.
  • Відповідь: details = {"doc_status", "lines_count", "lines_replaced"}.
ПолеТипОбовʼязковеОпис
inventory_dateYYYY-MM-DDтак
kinddetailed | simpleніЗа замовчуванням detailed (до партій), simple — поштучно.
warehouse_code_1cstringніНевідомий склад → 422.
doc_numberstring ≤100ні
doc_typestring ≤200ні
lines[].product_namestring ≤500так
lines[].product_codestring ≤200так
lines[].quantitynumber/string з крапкоютак (ключ)
lines[].line_numberintніЗа замовчуванням — позиція. Дубль → 422.
lines[].product_article, lines[].barcode, lines[].batch_idstring ≤200ні
lines[].batch_documentstring ≤300ні
lines[].batch_dateYYYY-MM-DDні
lines[].pricenumber/string з крапкоюні

delete: 422.

excise_marks

Пакет акцизних марок (УІ).

  • Ключ: УІ марки (GTIN + серійний номер). Повтор — ідемпотентний.
  • Зі складом (warehouse_code_1c; склад має бути активним і з excise_enabled) — марки приймаються на склад (in_stock); вже продана марка пропускається. Без складу — нова марка створюється як «видана» (issued), існуюча не змінюється.
  • Некоректні рядки не валять пакет — потрапляють у skipped_details (до 50) з причиною.
  • Товар визначається за GTIN; невідомий GTIN — рядок пропускається.
  • Ліміт: 5000 марок.
  • Відповідь: details = {"received", "created", "updated", "skipped", "skipped_details"}.
ПолеТипОбовʼязковеОпис
marksarrayтак
marks[].rawstring ≤200так (або gtin+serial)Сирий вміст DataMatrix.
marks[].gtinstring ≤14так, якщо немає raw
marks[].serialstring ≤40так, якщо немає raw
marks[].originstringніreceived (за замовчуванням), local_prod, import, manual.
warehouse_code_1cstringніНевідомий / без акцизу → 422.

delete: 422.


11. Продажі й документи руху товару

sale

Факт відвантаження по заявці, створеній на порталі: облік провів реалізацію.

  • Пошук заявки (по черзі): external_id як UUID заявки порталу → order_number (з payload, інакше external_id) → external_id як ключ заявки, що прийшла з обліку (logistics_order). Не знайдено → 422.
  • Заявка переходить у статус «відвантажено» (скасовані й відхилені — ні), фіксується фактична кількість по рядках.
  • Клієнт B2B отримує сповіщення лише при першому переході у «відвантажено» — повтор не дублює листи.
  • Відповідь: details = {"lines_matched", "shipped_total"}.
ПолеТипОбовʼязковеОпис
order_numberstringніНомер заявки порталу, якщо external_id — не UUID.
sale_number_1cstring ≤64ніНомер реалізації в обліку.
shipped_atISO дата-часніПорожнє — поточний момент.
shipped_total_amountdecimal з крапкоюніЯкщо не передано — рахується як Σ(факт × ціна рядка).
lines[].line_numberintніНомер рядка заявки (пріоритетний спосіб зіставлення).
lines[].product_code_1cstringніАбо код товару / артикул / штрихкод.
lines[].shipped_quantitydecimal з крапкоютак для рядкаРядок без нього пропускається. Незіставлені рядки ігноруються.

goods_document

Документ руху товару: реалізація, повернення, надходження, переміщення, оприходування, списання, відповідальне зберігання. На порталі — розділ «Продажі» і «Документи обліку».

  • Ключ: external_id.
  • Повтор: шапка оновлюється, рядки повністю замінюються.
  • Закритий місяць: документ з датою (новою або вже збереженою) у закритому періоді не змінюється — 200, details.skipped = "period closed".
  • Посилання (склад, контрагент, точка, торговий, виробник, товар) шукаються мʼяко: не знайдено — зберігаються код і назва з payload. Точка: спершу серед торгових точок, потім серед точок логістики. Документ без торгового зовсім (ні коду, ні ПІБ) ставиться на службового «Віртуального торгового».
  • Звʼязок із заявкою порталу — за order_number.
  • Ліміт: 2000 рядків.
  • Відповідь: details = {"lines", "unmatched_products"}.

Шапка:

ПолеТипОбовʼязковеОпис
doc_typestringтакsale, sale_return, commission_sale, purchase, custody_withdrawal, purchase_return, transfer, surplus, writeoff, custody_receipt, custody_return_supplier, custody_transfer, custody_return. Інше → 422.
doc_dateISO дата-часрекомендованоБез зони — Europe/Kyiv. Порожнє — поточний момент. Некоректне → 422.
doc_numberstring ≤32ні
operation_kindstring ≤80ніВид операції.
is_postedboolніЗа замовчуванням true.
warehouse_code, warehouse_to_codestringніexternal_id складу / складу-отримувача.
warehouse_name, warehouse_to_namestring ≤200ні
counterparty_codestring ≤64ніexternal_id контрагента.
counterparty_namestring ≤300ні
client_code_1cstring ≤64ніexternal_id точки.
client_namestring ≤300ні
manufacturer_external_idstring ≤64ніЯкщо порожній, а всі рядки одного виробника — виробник підіймається в шапку.
manufacturer_namestring ≤200ні
agent_external_idstring ≤64ні
agent_namestring ≤200ні
trade_kindstringніВид торгівлі: cash / noncash / cheque або текст («За готівку», «Безготівковий розрахунок», «Чек»…).
price_type_codestring ≤32ні
source_systemstring ≤64ні
base_doc_external_idstring ≤64ніДокумент-підстава.
base_doc_numberstring ≤32ні
order_numberstring ≤64ніНомер заявки порталу.
from_pdaboolніДокумент із КПК.
commentstring ≤2000ні
doc_barcodestring ≤64ніПорожнє не затирає збережений.
delivery_intervalstring ≤64ні
trip.numberstring ≤32ніХодка, у яку потрапив документ.
trip.date, trip.shipping_dateYYYY-MM-DDніЗа номером і датою відвантаження документ привʼязується до рейсу.
trip.driver, trip.forwarderstring ≤200ні
trip.vehiclestring ≤100ні
trip.router_numberstring ≤64ні
total_amountdecimalніЯкщо немає — Σ amount рядків.
total_no_discount, total_vatdecimalні
total_weightdecimalніЯкщо немає — Σ weight рядків.

Рядки lines[]:

ПолеТипОбовʼязковеОпис
product_code_1cstring ≤64рекомендованоexternal_id товару (основного каталогу або каталогу логістики). Незнайдений — рядок зберігається з кодом, рахується в unmatched_products.
quantitydecimalніЗа замовчуванням 0.
amountdecimalніСума рядка, за замовчуванням 0.
line_nointніЗа замовчуванням — позиція.
product_sku, barcodestring ≤50ніЯкщо немає — з картки товару.
product_namestring ≤300ні
manufacturer_external_idstring ≤64ніВиробник рядка (якщо відрізняється від шапки).
packs, pack_coef, price, amount_no_discount, discount_pct, vat_amount, weight, costdecimalні
price_type_codestring ≤32ні
batch_doc_external_idstring ≤64ні
agent_external_id, agent_namestringніТорговий рядка, якщо відрізняється від шапки.

delete: документ знімається з обліку (is_posted=false). Невідомий → 200, details.skipped = "unknown document". Закритий період → details.skipped = "period closed".

goods_period

Завершення вигрузки вікна документів руху товару: документи вікна, яких у цій вигрузці не було, знімаються з обліку. Плюс звірка контрольних сум «облік / портал».

  • Надсилати останнім, після всіх goods_document вікна.
  • Ключ: немає — кожен конверт створює новий запис звірки. external_id — довільний.
  • Знімаються (is_posted=false) документи вікна з видами doc_types, які портал востаннє отримував раніше за started_at. Закритий місяць не чіпається.
  • Звірка рахується по всьому вікну (разом із закритою частиною).
  • Відповідь: details = {"unposted", "closed_until", "run_id"}.
ПолеТипОбовʼязковеОпис
date_from, date_toYYYY-MM-DDтакВікно (включно), дні за Europe/Kyiv.
started_atISO дата-частакМомент початку вигрузки; без зони — Europe/Kyiv.
doc_typesarray of stringніВиди документів у вигрузці. Порожній — усі види.
totals[]arrayніКонтрольні суми облікової системи по видах: {"doc_type", "docs", "quantity", "amount"}.

Порада. Тримайте годинник облікової системи синхронізованим (NTP) і передавайте started_at на кілька хвилин раніше реального старту вигрузки.


12. Борги

debt_reset

Скидання всіх боргів тенанта перед повною вигрузкою відкритих документів: усе, що не прийде після скидання, вважається закритим.

  • Видаляє всі документи заборгованості тенанта і обнуляє борг усіх точок. external_id і payload не читаються.
  • Відповідь: details.cleared — кількість видалених документів.

Увага. Між скиданням і приходом нових документів борги на порталі нульові. Надсилайте debt_reset першим конвертом у тому самому пакеті, що й документи боргу, з partial: false (атомарно).

debt_document

Відкритий (або закритий) документ заборгованості точки.

  • Ключ: external_id.
  • Точка (client_code_1c) потрібна лише при створенні. Якщо точки немає, вона створюється з полів client_* (і контрагент із полів counterparty_*, якщо є counterparty_external_id і counterparty_name) — тими самими правилами, що client і counterparty. Без client_name → 422.
  • Статус: status з payload, інакше open, якщо remaining_amount > 0, інакше closed.
  • Термін оплати: якщо облік передав due_date пізніше за doc_date — він головний. Інакше портал рахує doc_date + відстрочка, де відстрочка — з регістру «контрагент × виробник» (manufacturer_payment_term), інакше точки, інакше контрагента.
  • Поля client_payment_terms_days / counterparty_payment_terms_days (> 0) оновлюють відстрочку вже існуючих точки / контрагента.
  • Борг точки на порталі перераховується один раз наприкінці пакета.
  • Відповідь: details = {"status", "remaining"}.
ПолеТипОбовʼязковеОпис
client_code_1cstringтак при створенніexternal_id точки.
doc_numberstring ≤64ніЗа замовчуванням = external_id.
doc_typestring ≤30ніЗа замовчуванням realization.
doc_date, due_dateYYYY-MM-DD (або ISO дата-час)ніНекоректне значення мовчки стає null.
amountdecimal з крапкоюніСума документа.
remaining_amountdecimal з крапкоютак при створенніЗалишок боргу.
statusopen | closedні
currencystring(3)ніЗа замовчуванням UAH.
payment_formstring ≤20ніНал / безнал.
notesstringні
manufacturer_external_idstringніБорг у розрізі виробника.
agent_external_idstringніТорговий.
warehouse_external_idstringніСклад.
accounting_numberstring ≤64ніБухгалтерський номер.
warehouse_name, agent_namestring ≤200ніНазви для показу, коли довідник не вивантажено.
doc_branch_name (або branch_name)string ≤200ніНазва філії документа.
client_namestringдля створення точки
client_address, client_city, client_phonestringніДля створення точки.
client_payment_terms_days, client_credit_limit, client_price_list_code, client_latitude, client_longitude—ніДля створення точки / оновлення відстрочки.
counterparty_external_id, counterparty_name, counterparty_legal_name, counterparty_tax_number, counterparty_edrpou, counterparty_phone, counterparty_email, counterparty_legal_address, counterparty_payment_terms_days—ніДля створення контрагента / оновлення відстрочки.

delete: документ закривається (status=closed, залишок 0), запис лишається. Немає — 422.

manufacturer_payment_term

Відстрочка платежу контрагента по конкретному виробнику (перекриває загальну відстрочку при розрахунку терміну боргу).

  • Ключ: (контрагент counterparty_external_id, виробник manufacturer_external_id). external_id зберігається; рекомендований формат "<GUID контрагента>-<код виробника>".
  • Невідомий контрагент → 200, details.skipped = "counterparty_not_found". Невідомий виробник → 422.
  • Без виробника (all_manufacturers: true або порожній manufacturer_external_id) — це одна відстрочка на всіх виробників: записується як відстрочка контрагента; details.counterparty_payment_terms_days.
  • Мʼяко видалений рядок оживає при наступному upsert.
  • Відповідь: details.days.
ПолеТипОбовʼязковеОпис
counterparty_external_idstringтак
manufacturer_external_idstringтак (або all_manufacturers)
all_manufacturersboolні
daysint ≥0так при створенні7, "7,0". Відʼємне або некоректне → 422.

delete: за парою ключів або (без ключів) за external_id; мʼяке видалення; немає — 422. Для all_manufacturers — details.skipped = "all_manufacturers_delete_ignored".


13. Каса

cash_document

Грошовий документ: прибутковий / видатковий касовий ордер, банківська виписка.

  • Ключ: external_id. Повтор — upsert.
  • Напрям визначається видом: cash_in, bank_in — надходження; cash_out, bank_out — витрата. Сума зберігається за модулем.
  • Посилання (контрагент, точка, торговий, виробник) — мʼякі, як у goods_document.
  • Закритого місяця для каси немає.
  • Відповідь: details = {"doc_type", "direction"}.
ПолеТипОбовʼязковеОпис
doc_typestringтакcash_in, cash_out, bank_in, bank_out. Інше → 422.
doc_dateISO дата-часрекомендованоБез зони — Europe/Kyiv.
doc_numberstring ≤32ні
amountdecimal (кома допустима)ні
is_postedboolніЗа замовчуванням true.
operation_kindstring ≤80ні
cash_kindstringніcash/noncash або «Наличные»/«Готівка»/«Безготівкові»; за замовчуванням з виду документа.
account_codestring ≤64ніКаса / рахунок.
account_namestring ≤200ні
account_kindbank | cashboxніЗа замовчуванням з виду документа.
cashflow_itemstring ≤200ніСтаття руху коштів.
branch_namestring ≤200ні
counterparty_code, counterparty_namestringні
client_code_1c, client_namestringні
agent_external_id, agent_namestringні
manufacturer_external_id, manufacturer_namestringні
responsiblestring ≤200ні
base_doc_numberstring ≤64ні
commentstring ≤2000ні

delete: is_posted=false; невідомий → 200, details.skipped = "unknown document".

cash_balance

Залишок коштів по касі / рахунку на дату вигрузки.

  • Ключ: (account_code, вид коштів). external_id не використовується.
  • Відповідь: details.balance.
ПолеТипОбовʼязковеОпис
account_codestring ≤64так
account_namestring ≤200ні
account_kindbank | cashboxні
cash_kindstringніЯк у cash_document.
branch_namestring ≤200ні
balancedecimal (кома допустима)ніЗа замовчуванням 0.
as_ofYYYY-MM-DDніЗа замовчуванням — сьогодні за Europe/Kyiv.

delete: рядок видаляється; details.deleted.

cash_period

Завершення вигрузки вікна каси: документи вікна, не отримані в цій вигрузці (востаннє отримані раніше за started_at), знімаються з обліку. Надсилати останнім.

ПолеТипОбовʼязковеОпис
date_from, date_toYYYY-MM-DDтакВікно включно, за Europe/Kyiv.
started_atISO дата-частакБез зони — Europe/Kyiv.

Відповідь: details.unposted. На відміну від goods_period, фільтра за видами документів і захисту закритого місяця немає.


14. Стан заявок порталу в обліку

Заявка порталу потрапляє в облік як непроведений документ. Облік повідомляє про його стан; видалення документа в обліку скасовує заявку на порталі (з повідомленням торговому, керівникам і клієнту B2B). Назад в облік скасування не передається.

order_state

  • Пошук заявки: external_id → ідентифікатор документа в обліку, отриманий порталом при підтвердженні заявки; або order_number. Заявки логістики не розглядаються. Не знайдено → 200, details.skipped = "unknown order".
  • deleted: true → заявку скасовано (якщо вона в статусі, який можна скасувати). Розпроведення без видалення заявку не скасовує — стан лише запамʼятовується.
  • Відповідь: details.cancelled.
ПолеТипОбовʼязковеОпис
order_numberstring ≤32ніНомер заявки порталу.
postedboolніДокумент проведено.
deletedboolніДокумент видалено / позначено на видалення.
reason, reason_commentstringніПричина видалення; разом ≤200 символів, потрапляє в причину скасування.

order_state_period

Кінець списку станів: заявки, передані в облік у вікні, по яких у цій вигрузці не прийшло order_state, вважаються видаленими повністю й скасовуються.

  • Розглядаються заявки, підтверджені обліком у проміжку від date_from + 1 день до started_at − 2 години, які не отримували order_state після started_at.
  • count <= 0 → нічого не скасовується (details.skipped = "empty list") — захист від збою запиту в обліку.
  • У батчі: якщо хоча б один order_state у цьому ж батчі не прийнято, order_state_period відхиляється (щоб не скасувати заявки, чий стан не записався).
  • Відповідь: details.cancelled.
ПолеТипОбовʼязковеОпис
date_fromISO дата / дата-частакПочаток вікна; без зони — Europe/Kyiv.
started_atISO дата-частакПочаток вигрузки списку.
countintтакКількість order_state у списку.

15. Рейси (ходки)

trip

Ходка обліку. Має два режими залежно від наявності payload.number.

Режим «рейс» (є number, а також для будь-якого delete) — ходка стає рейсом на порталі.

  • Ключ: external_id. Якщо рейс не знайдено, але передано router_number — шукається рейс, створений на порталі й переданий в облік (щоб не завести дубль).
  • Повтор: рейс з обліку перебудовується: водій, авто, статус, склад документів і заявок — за payload. Рейс, зібраний на порталі, облік лише доповнює (порожні поля, статус тільки вперед, точки додаються).
  • Номер рейсу на порталі унікальний: при збігу додається суфікс з датою.
  • Статус: дата в минулому — «завершено»; сьогодні — «в дорозі» (shipped) або «завантажено»; майбутня — «збирається» (за Europe/Kyiv).
  • Водій / експедитор поза списком обміну (transport_list) або невідомий → «Не визначено»; pickup: true без авто → «Самовивіз».
  • Документи (document_external_id) і заявки (order_number) привʼязуються до рейсу; ті, що вже в іншому рейсі, не забираються. Документи, що прийдуть пізніше, допривʼяжуться за номером ходки й датою відвантаження (goods_document.trip).
  • Кілометраж рахується дорогами по точках; distance_km з обліку зберігається для звірки й використовується, лише якщо маршрут побудувати не вдалося.
  • Відповідь: details = {"created", "distance_km", "trip_number", "documents", "documents_pending", "orders"} (+ driver: "not_found").
ПолеТипОбовʼязковеОпис
numberstring ≤30так (ознака режиму)Номер ходки.
dateYYYY-MM-DD / ISOтак (або doc_date)Дата відвантаження. Без дати → 422.
doc_dateдатаніДата документа.
driver_external_id, forwarder_external_idstringні
vehicle_external_idstringніЛише активне авто.
driver, vehicle, forwarderstring ≤200ніНазви рядком (для показу).
shippedboolніВідвантажено.
pickupboolніСамовивіз.
weightanyніДовідково.
commentstring ≤2000ні
router_numberstringніНомер рейсу порталу, переданого в облік.
distance_kmnumberніКілометраж з обліку.
points[].document_external_idstringніexternal_id документа руху товару.
points[].order_numberstringніНомер заявки порталу.
points[].positionintніПорядок обʼїзду; за замовчуванням — позиція.
points[].weightdecimalніВага накладної, якщо документ прийшов без ваги.

delete: рейс скасовується, документи й заявки відчіплюються. Не знайдено → 200, details.skipped = "trip_not_found".

Режим «призначення водія» (немає number) — лише проставляє водія заявкам порталу, статуси не змінює.

ПолеТипОбовʼязковеОпис
driver_external_idstringтакНевідомий водій → 422.
vehiclestring ≤200ніАвто водія рядком.
dateдатаніІнформативно.
points[].order_numberstringтак для рядкаНенайдені номери — у details.orders_not_found (до 50), не помилка.

Відповідь: details = {"assigned", "orders_not_found"}.


16. Модуль логістики

Модуль логістики (3PL-доставка для виробників) має власні довідники й каталог, незалежні від торгового контуру.

logistics_order

Заявка на доставку, створена в обліку: на порталі одразу підтверджена й видима на дошці рейсів. Відвантаження по ній — звичайний sale з тим самим external_id.

  • Ключ: external_id серед заявок, що прийшли з облікової системи.
  • Повтор: заявка не перестворюється (details.skipped = "already imported"); заявка вже в рейсі чи далі — details.skipped = "status=…".
  • Заявка оформлюється на віртуального B2B-торгового філії, інакше — на першого активного адміністратора; немає жодного → 422.
  • Відповідь: details = {"order_number", "lines", "missed_products"}.
ПолеТипОбовʼязковеОпис
client_code_1c (або client_code)stringтакНевідома точка → 422.
lines[]arrayтакПорожній → 422.
lines[].product_code_1c / sku / barcodestringтакТовар шукається за кодом, артикулом або штрихкодом. Нерозпізнані — у missed_products; жодного не розпізнано → 422.
lines[].quantitydecimal з крапкоютак≤0 — рядок пропускається.
lines[].unit_pricedecimal з крапкоюні
requested_delivery_dateYYYY-MM-DDні
currencystringніЗа замовчуванням UAH.
notesstringні

delete: скасування, якщо заявка ще в статусі «нова» / «підтверджена» і не в рейсі; інакше details.skipped. Немає — 422.

logistics_manufacturer

Виробник торгового довідника з позначкою «логістика». Поля, ключ і delete — як у manufacturer; при upsert додатково ставиться позначка логістики.

logistics_own_manufacturer

Виробник модуля логістики. Ключ: external_id (спільний довідник виробників).

ПолеТипОбовʼязковеОпис
namestring ≤300так при створенні
codestring ≤100ні
tax_numberstring ≤20ні
edrpoustringніЯкщо немає tax_number — пишеться в нього (за ним розпізнаються файли замовлень).
ship_warehouse_external_idstringніСклад відвантаження.
import_template_keystring ≤40ніШаблон імпорту файлів замовлень.
is_activeboolні

delete: is_active=false; немає — 422.

logistics_counterparty

Контрагент логістики. Ключ: external_id.

ПолеТипОбовʼязковеОпис
namestring ≤500так при створенні
codestring ≤100ні
tax_numberstring ≤50ні
edrpoustring ≤20ні
phonestring ≤100ні
emailstring ≤200ні
legal_addressstring ≤500ні
external_codesarrayніЯк у counterparty.
price_list_codestringніПрайс; створюється, якщо немає.
is_activeboolні

delete: is_active=false; немає — 422.

logistics_point

Точка доставки логістики. Ключ: external_id. При створенні допривʼязує документи руху товару, що прийшли раніше з цим кодом точки.

ПолеТипОбовʼязковеОпис
counterparty_external_idstringтакlogistics_counterparty; невідомий → 422.
namestring ≤500так при створенні
codestring ≤100ні
glnstring ≤64ніGLN — за ним розпізнаються файли замовлень.
phonestring ≤100ні
addressstring ≤500ні
citystring ≤200ні
directionstring ≤150ніНапрямок; також копіюється в торгову точку з тим самим кодом, якщо вона є.
external_codesarrayніЯк у client.
latitude, longitudenumber з крапкоюніЯкщо передано (і точку не виправляли вручну) — перезаписують координати. Лише крапка як десятковий роздільник.
price_list_codestringні
is_activeboolні

delete: is_active=false; немає — 422.

logistics_warehouse

Склад модуля логістики (той самий довідник складів, з позначкою «логістика»). Ключ: external_id.

ПолеТипОбовʼязковеОпис
namestring ≤300так при створенні
addressstring ≤1000ні
is_activeboolні

delete: is_active=false; немає — 422. Спершу передайте branch.

logistics_product_category

Категорія каталогу логістики. Ключ: external_id.

ПолеТипОбовʼязковеОпис
namestring ≤200так при створенні
codestring ≤50ні
descriptionstring ≤2000ні
image_urlstring ≤1000ні
parent_external_idstringніНевідомий батько → звʼязок порожній (без помилки).
is_activeboolні

delete: is_active=false; немає — 422.

logistics_product

Товар каталогу логістики. Ключ: external_id. Новий штрихкод без фото — у чергу збагачення.

ПолеТипОбовʼязковеОпис
namestring ≤300так при створенні
code_1cstring ≤50ніКод товару (запасний ключ для logistics_stock).
sku, manufacturer_code, barcode, unit_barcodestring ≤50ні
unitstring ≤20ні
brandstring ≤100ні
category_1cstring ≤200ні
kind_1cstring ≤100ні
descriptionstring ≤4000ні
image_url, image_thumbnail_urlstring ≤1000ні
pack_sizeintніМінімум 1.
weight_kg, volume_liters, base_pricedecimal (кома допустима)ні
vat_ratedecimalніПорожнє — 20.
is_excisableboolні
dimensions, attributesobjectніЗберігаються як є.
category_external_idstringніlogistics_product_category.
manufacturer_external_idstringніВиробник.
is_activeboolні

delete: is_active=false; немає — 422.

logistics_product_code

Код товару логістики в мережі.

  • Ключ: (товар product_external_id — за замовчуванням external_id конверта; kind_external_id).
  • Товару немає → 422.
ПолеТипОбовʼязковеОпис
product_external_idstringніЗа замовчуванням — external_id.
kind_external_idstring ≤200так
codestring ≤200такНавіть для delete.
kind_namestring ≤300ні

delete: рядок видаляється.

logistics_stock

Знімок залишків складу логістики. Аналог product_stock над каталогом логістики.

  • Склад має бути активним і саме складом логістики, інакше 422.
  • Товар шукається за external_id товару логістики, запасний варіант — його code_1c.
  • Частина невідомих кодів — допустимо (details.unknown_products); жодного знайденого → 422 (захист від обнулення складу через неправильне поле).
  • Повна заміна з обнуленням відсутніх + денний зріз за сьогодні.
  • Відповідь: details = {"upserted", "depleted", "unknown_products", "unknown_sample"}.
ПолеТипОбовʼязковеОпис
warehouse_code_1cstringтак
items[].product_code_1cstringтак
items[].qtynumber/string з крапкоюні

delete: 422.


17. Приклади конвертів

Готові батчі: examples/exchange-inbound-batch-catalog.json, examples/exchange-inbound-batch-stock.json, examples/exchange-inbound-batch-sales.json.

client

JSON
{
  "entity_type": "client",
  "operation": "upsert",
  "external_id": "5c1e8a20-4b7f-11ee-9d3c-0050569a1b2c",
  "payload": {
    "name": "Маркет «Колосок»",
    "legal_name": "ФОП Петренко О. В.",
    "address": "вул. Шевченка, 12",
    "city": "Полтава",
    "region": "Полтавська",
    "phone": "+380671234567",
    "channel": "Традиційна торгівля",
    "counterparty_external_id": "7a2d4f10-4b7f-11ee-9d3c-0050569a1b2c",
    "price_list_code": "000000002",
    "payment_terms_days": "14",
    "credit_limit": "25000.00",
    "external_codes": [{"kind": "GLN", "code": "4820000123456"}],
    "latitude": "49.5883",
    "longitude": "34.5514"
  }
}

product

JSON
{
  "entity_type": "product",
  "operation": "upsert",
  "external_id": "b3f61c42-4b7f-11ee-9d3c-0050569a1b2c",
  "payload": {
    "name": "Сік яблучний 1 л",
    "sku": "JA-1000",
    "barcode": "4820017000123",
    "unit": "шт",
    "base_price": "18.50",
    "vat_rate": 20,
    "manufacturer_external_id": "000000017",
    "manufacturer": "ТОВ «Сади Приклад»",
    "category_code_1c": "c9d02e11-4b7f-11ee-9d3c-0050569a1b2c",
    "pack_size": 6,
    "weight_kg": "1.1",
    "is_active": true
  }
}

price_list_item

JSON
{
  "entity_type": "price_list_item",
  "operation": "upsert",
  "external_id": "000000002:b3f61c42-4b7f-11ee-9d3c-0050569a1b2c",
  "payload": {
    "price_list_code": "000000002",
    "product_code_1c": "b3f61c42-4b7f-11ee-9d3c-0050569a1b2c",
    "price": "17.90"
  }
}

counterparty

JSON
{
  "entity_type": "counterparty",
  "operation": "upsert",
  "external_id": "7a2d4f10-4b7f-11ee-9d3c-0050569a1b2c",
  "payload": {
    "name": "ФОП Петренко Олена Василівна",
    "kind": "buyer",
    "edrpou": "3012345678",
    "tax_number": "3012345678",
    "legal_address": "м. Полтава, вул. Шевченка, 12",
    "payment_terms_days": 7,
    "is_group": false,
    "parent_external_id": "1e44a9b0-4b7f-11ee-9d3c-0050569a1b2c",
    "is_active": true
  }
}

goods_document

JSON
{
  "entity_type": "goods_document",
  "operation": "upsert",
  "external_id": "e7a1c3d5-6f80-11ef-8a1b-0050569a1b2c",
  "payload": {
    "doc_type": "sale",
    "doc_number": "РН-0004512",
    "doc_date": "2026-10-26T14:35:00",
    "warehouse_code": "2f6c9e30-4b7f-11ee-9d3c-0050569a1b2c",
    "client_code_1c": "5c1e8a20-4b7f-11ee-9d3c-0050569a1b2c",
    "client_name": "Маркет «Колосок»",
    "counterparty_code": "7a2d4f10-4b7f-11ee-9d3c-0050569a1b2c",
    "agent_external_id": "a8b9c0d1-4b7f-11ee-9d3c-0050569a1b2c",
    "agent_name": "Іваненко Ігор",
    "manufacturer_external_id": "000000017",
    "trade_kind": "Безготівковий розрахунок",
    "order_number": "ORD-20261026-0042",
    "lines": [
      {"line_no": 1, "product_code_1c": "b3f61c42-4b7f-11ee-9d3c-0050569a1b2c", "quantity": "24", "price": "17,90", "amount": "429,60"}
    ]
  }
}

product_stock

JSON
{
  "entity_type": "product_stock",
  "operation": "upsert",
  "external_id": "2f6c9e30-4b7f-11ee-9d3c-0050569a1b2c",
  "payload": {
    "warehouse_code_1c": "2f6c9e30-4b7f-11ee-9d3c-0050569a1b2c",
    "items": [
      {"product_code_1c": "b3f61c42-4b7f-11ee-9d3c-0050569a1b2c", "qty": "1320", "amount": "19140.00"},
      {"product_code_1c": "b3f61c43-4b7f-11ee-9d3c-0050569a1b2c", "qty": "0"}
    ]
  }
}

debt_document

JSON
{
  "entity_type": "debt_document",
  "operation": "upsert",
  "external_id": "d2c4e6f8-6f80-11ef-8a1b-0050569a1b2c",
  "payload": {
    "client_code_1c": "5c1e8a20-4b7f-11ee-9d3c-0050569a1b2c",
    "client_name": "Маркет «Колосок»",
    "doc_number": "РН-0004512",
    "doc_type": "realization",
    "doc_date": "2026-10-26",
    "due_date": "2026-10-26",
    "amount": "429.60",
    "remaining_amount": "429.60",
    "payment_form": "безнал",
    "manufacturer_external_id": "000000017",
    "agent_external_id": "a8b9c0d1-4b7f-11ee-9d3c-0050569a1b2c"
  }
}

order_state

JSON
{
  "entity_type": "order_state",
  "operation": "upsert",
  "external_id": "f1e2d3c4-6f80-11ef-8a1b-0050569a1b2c",
  "payload": {
    "order_number": "ORD-20261026-0042",
    "posted": false,
    "deleted": true,
    "reason": "Клієнт відмовився"
  }
}