Надходження
Надходження — це приймання: оператор ТСД зіставляє привезений постачальником товар із накладною. Повний цикл на одній сторінці: ви надсилаєте завдання одним запитом, стежите за перебігом приймання і забираєте результат назад.
Завдання — документ надходження з вашої облікової системи: список товарів із кількостями за накладною та іменем постачальника. Для інвентаризацій є окремий вид документа — Перерахунок, влаштований точно так само.
Основи взаємодії
Базова адреса API: https://combopocket.online/v2/exchange.
Усі операції виконуються методом POST з JSON-тілом.
Кожен запит несе заголовок X-API-Token — входу в систему
й сесій немає, система перевіряє дані за токеном.
Відповідь завжди несе поле ok у тілі: true —
успіх, false — відмова з причиною в error.
HTTP-код — рівень транспорту: 200 — запит дійшов
і оброблений (результат — в ok), 4xx — запит
до обробки не дійшов, 5xx — збій на нашому боці.
Докладно конверт відповіді, таблиця кодів і авторизація розібрані в розділі «З чого почати» — тут вони працюють точно так само.
Ключові поняття
Зовнішній ідентифікатор (external_id) —
ідентифікатор документа у вашій обліковій системі. Це головний ключ
усього обміну: за ним ви оновлюєте завдання, опитуєте статус, забираєте
результат і видаляєте документ.
Ідентифікатор унікальний у межах вашої бази — другого документа з таким
самим external_id не буде.
Виконавець (assignee_token) — токен
оператора, якому призначається приймання. Кожен оператор ТСД має власний
токен, і завдання з'явиться на терміналі саме того оператора, чий токен
ви вказали.
Токен виконавця потрібен лише під час надсилання — решта операцій
працює за external_id.
Версія документа (docversion) — ваша мітка
версії, будь-який рядок. Вона захищає від зайвої роботи: якщо ви повторно
надішлете документ із тією самою версією, сервер відповість
unchanged і нічого не перезапише.
Змінюєте вміст (наприклад, постачальник надіслав виправлену накладну) — змінюйте версію, і сервер замінить завдання цілком.
Життєвий цикл
NotStartedInProgressDoneDone — фінальний стан: виконане приймання не відновлюється
Поки завдання у статусі NotStarted, його можна вільно
перезаписувати повторними upload — сервер замінить
вміст цілком.
Щойно оператор почав приймання (InProgress) або завершив
його (Done), перезапис заборонено: сервер відповість
відмовою conflict, щоб робота оператора не була втрачена.
Надсилання завдання
Створює нове завдання або цілком замінює наявне (поки воно
NotStarted).
Операція виконується атомарно: або завдання записано повністю, або не записано взагалі — часткових станів не буває.
| Поле | Тип | Призначення | |
|---|---|---|---|
| external_id | string ≤100 | обов. | Ідентифікатор документа у вашій системі — ключ усіх подальших операцій. |
| assignee_token | string ≤36 | обов. | Токен оператора-виконавця. Завдання з'явиться на його терміналі. |
| name | string ≤200 | обов. | Назва завдання — її бачить оператор у списку на ТСД. |
| date | datetime | обов. | Дата документа у форматі ISO 8601 зі зсувом часового поясу:
2026-07-10T12:00:00+03:00. Форма без зсуву теж
приймається й означає київський час. |
| vendor | string ≤200 | Постачальник. Оператор бачить, чиє постачання приймає; поле повернеться й під час вивантаження результату. | |
| docversion | string ≤100 | Ваша мітка версії. Збіглася зі збереженою — повтор ігнорується
(unchanged). | |
| comment | string ≤500 | Коментар-інструкція оператору. | |
| store_name | string ≤200 | Назва магазину. Допомагає оператору відрізняти завдання, коли на ТСД вивантажені документи кількох магазинів. | |
| settings | object | Налаштування поведінки завдання на терміналі — див. нижче. Не є обов'язковими цілком. | |
| rows | array | обов. | Рядки накладної. Може бути порожнім [] — завдання
«прийми все, що привезли»: оператор сканує вільно,
результат повернеться в extra_rows. |
Налаштування поведінки на терміналі settings
Необов'язковий об'єкт — задає, що оператор бачить на екрані завдання і що йому дозволено.
Передавати settings цілком не обов'язково; будь-яке відсутнє
поле (як і весь об'єкт) трактується як true.
Налаштування зберігаються в документі й завжди повертаються назад
у status і download — навіть якщо ви їх
не надсилали.
| Поле | Тип | Призначення (типово — увімкнено) | |
|---|---|---|---|
| show_fact_qty | bool | Показувати оператору фактичну кількість за позицією. | |
| show_progress | bool | Показувати прогрес-бари перебігу приймання. | |
| allow_add_unlisted | bool | Дозволяти додавати товари поза завданням — знайдені в базі
штрих-кодів, але відсутні в рядках документа. За
false оператор працює строго за накладною. | |
| show_book_qty | bool | Показувати облікову кількість (заявлену за накладною) за позицією. |
Кожен рядок rows[] — одна позиція накладної:
| Поле | Тип | Призначення | |
|---|---|---|---|
| item_id | string ≤100 | обов. | Ідентифікатор товару у вашій системі. Унікальний у межах документа.
Якщо товар обліковується з характеристиками (колір, розмір), включіть
характеристику в ідентифікатор — наприклад, склейте коди номенклатури
й характеристики: кожна характеристика стає окремою позицією
зі своїм item_id і своїми штрих-кодами. |
| name | string ≤150 | Назва товару — її бачить оператор. | |
| char | string ≤150 | Характеристика (колір, розмір, об'єм). | |
| qty_plan | number ≥ 0 | обов. | Кількість за накладною: скільки заявлено постачальником. |
| qty_fact | number | Стартовий факт. Зазвичай не передається (0) — його наповнює оператор; потрібен для переносу частково виконаних приймань. | |
| line_num | int | Номер рядка в накладній — у цьому порядку рядки повернуться під час вивантаження результату. | |
| qty_int_only | bool | Товар вважається лише цілими числами (штучний). | |
| bc_array | array | Штрих-коди позиції: {"code": "…", "is_sku": false}.
Формат коду єдиний у всьому API: is_sku: true —
ваговий код (СКЮ). Позиція без штрих-кодів припустима. |
POST /v2/exchange/receipts/upload{
"external_id": "TTN-2026-0778",
"assignee_token": "22222222-3333-4444-5555-666666666666",
"name": "Постачання за накладною №778",
"date": "2026-07-10T08:30:00+03:00",
"vendor": "ТОВ Постачальник",
"docversion": "v1",
"store_name": "Магазин на Хрещатику",
"settings": { "show_fact_qty": true, "show_progress": true,
"allow_add_unlisted": false, "show_book_qty": true },
"rows": [
{ "item_id": "MLK-001", "name": "Молоко 2,5%", "char": "0,9 л",
"qty_plan": 120, "line_num": 1, "qty_int_only": true,
"bc_array": [ { "code": "4820000001234", "is_sku": false } ] },
{ "item_id": "SYR-40", "name": "Сир Гауда",
"qty_plan": 12.6, "line_num": 2,
"bc_array": [ { "code": "210", "is_sku": true } ] }
]
}
{ "ok": true, "doc_status": "created" }
Поле doc_status каже, що саме сталося: created —
завдання створено, updated — наявне замінено цілком,
unchanged — версія збіглася, нічого не змінювалося.
{ "ok": false, "error": "conflict", "status": "InProgress" }
{
"ok": false,
"error": "validation_failed",
"recommendation": "повтор item_id у документі: MLK-001"
}
Перевірка даних
Сервер перевіряє завдання до запису — або приймається все, або ніщо:
| Правило | Навіщо |
|---|---|
item_id унікальний у документі |
Один рядок — одна позиція; повтор — майже завжди помилка вивантаження. |
| Один штрих-код — один товар | Код, прив'язаний до двох різних item_id, зробив би
сканування неоднозначним. |
item_id ≤ 100, code ≤ 50 символів |
Ключові поля не обрізаються мовчки — перевищення це відмова. |
name, char ≤ 150 |
Представницькі поля м'яко усікаються — відмова не потрібна. |
| Кількість рядків ≤ ліміту бази | Захист від аномально великих завдань; ліміт налаштовується для вашої бази (типово 1000 рядків). |
date у форматі ISO 8601 |
Рекомендовано зі зсувом поясу (+03:00); приймається
також Z і форма без зсуву (= київський час). |
Отримання результату
Далі працюють три читальні операції та видалення. Токен виконавця їм
не потрібен — тільки external_id.
Повертає всі надходження вашої бази — тіло запиту не потрібне
(порожній {}). Зручний як огляд: що вивантажено, що в роботі,
що готове до забирання.
POST /v2/exchange/receipts/list{
"ok": true,
"truncated": false,
"docs": [
{ "name": "Постачання за накладною №778",
"external_id": "TTN-2026-0778",
"status": "Done",
"docversion": "v1",
"assignee_token": "22222222-3333-4444-5555-666666666666",
"created_on_tsd": false,
"started_at": "2026-07-10T09:05:00+03:00",
"completed_at": "2026-07-10T10:20:00+03:00" }
]
}
Зверніть увагу на два поля.
created_on_tsd: true позначає надходження, які оператор
створив просто на терміналі — наприклад, прийшло незаплановане
постачання, і його почали приймати до появи накладної в системі.
Вашій системі такі документи поки невідомі, і ви самі вирішуєте,
чи забирати їх.
truncated: true означає, що список уперся в запобіжний
ліміт (налаштовується для бази, типово 1000) і показано лише його
частину — ознака того, що виконані документи пора видаляти.
Легка операція для опитування перебігу приймання: замість вивантаження всіх рядків сервер віддає готові лічильники. Саме її варто викликати за розкладом.
{ "external_id": "TTN-2026-0778" }
{
"ok": true,
"status": "InProgress",
"started_at": "2026-07-10T09:05:00+03:00",
"completed_at": null,
"items_total": 45,
"items_counted": 30,
"items_extra": 1,
"progress_percent": 66,
"discrepancy_count": 2,
"settings": { "show_fact_qty": true, "show_progress": true,
"allow_add_unlisted": false, "show_book_qty": true }
}
| Поле | Що означає |
|---|---|
| status | NotStarted — оператор ще не почав,
InProgress — приймає, Done — приймання завершено. |
| items_total | Усього позицій у накладній. |
| items_counted | Позиції, які оператор уже обробив. Враховується й «порахований нуль» — коли оператор підтвердив, що позицію не привезли взагалі. |
| items_extra | Позиції, додані оператором понад накладну. |
| progress_percent | Відсоток виконання: counted / total. |
| discrepancy_count | Позиції, де прийняте не збіглося із заявленим, — заздалегідь видно обсяг недовозу й пересорту. |
| settings | Налаштування поведінки на терміналі — рівно ті, що ви надіслали під час надсилання, або типові значення. Склад полів — у розділі «Надсилання завдання». |
Повний результат приймання. Рядки повертаються в порядку
line_num — тому самому, у якому ви їх надсилали, тому
зіставлення з накладною тривіальне.
Поля рядків симетричні надсиланню: що ви надіслали в upload,
під тими самими іменами повернеться тут.
У шапці відповіді є й vendor — постачальник із завдання, —
і налаштування документа (settings).
{ "external_id": "TTN-2026-0778" }
{
"ok": true,
"external_id": "TTN-2026-0778",
"status": "Done",
"docversion": "v1",
"vendor": "ТОВ Постачальник",
"created_at": "2026-07-10T08:30:00+03:00",
"started_at": "2026-07-10T09:05:00+03:00",
"completed_at": "2026-07-10T10:20:00+03:00",
"comment_initial": "Прийняти до 11:00, машина під розвантаженням",
"comment_user": "Дві коробки молока пошкоджені, не прийняв",
"settings": { "show_fact_qty": true, "show_progress": true,
"allow_add_unlisted": false, "show_book_qty": true },
"rows": [
{ "item_id": "MLK-001", "name": "Молоко 2,5%", "char": "0,9 л",
"qty_plan": 120, "qty_fact": 118, "line_num": 1, "is_counted": true,
"bc_array": [ { "code": "4820000001234", "is_sku": false } ] }
],
"extra_rows": [
{ "item_id": "manual-3f2a…", "name": "Кефір 1%",
"qty_plan": 0, "qty_fact": 6, "line_num": -1, "is_counted": true,
"bc_array": [ { "code": "4820000007777", "is_sku": false } ] }
],
"photos": [
{ "name": "da75cf11-a672-4965-a545-3556ba4f1c4e",
"comment": "Пошкоджена коробка, вид збоку" }
]
}
Поділ rows / extra_rows відповідає на головне
питання приймання.
rows — доля позицій накладної: за різницею
qty_plan і qty_fact видно недовіз.
extra_rows — товар, який привезли, хоча в накладній
його не було: пересорт або незаявлена позиція.
Прапорець is_counted вирішує класичну неоднозначність нуля:
qty_fact: 0 з is_counted: true означає
«оператор перевірив — позицію не привезли», а з
is_counted: false — «до позиції не дійшли».
Без цього прапорця недовіз неможливо відрізнити від неперевіреного рядка.
Масив photos — метадані фотографій, знятих оператором:
name (ідентифікатор знімка) і comment (підпис).
Самі зображення в документ не вкладаються — download
залишається легким.
Показати знімки можна, взагалі не вивантажуючи документ
(photos_thumbnails), а отримати оригінал — за іменем
(download_photo).
Обидві операції нижче; усе про фото зібрано й на окремій сторінці «Фотографії».
Повертає за external_id масив мініатюр — для прев'ю
без вивантаження документа.
У кожного знімка: ім'я оригіналу, ім'я мініатюри, підпис і сама мініатюра в base64.
{ "external_id": "TTN-2026-0778" }
{
"ok": true,
"photos": [
{ "name": "da75cf11-a672-4965-a545-3556ba4f1c4e",
"thumb_name": "da75cf11-a672-4965-a545-3556ba4f1c4e.thumb",
"comment": "Пошкоджена коробка, вид збоку",
"thumb_b64": "/9j/4AAQSkZJRgABAQ…" }
]
}
Повертає оригінал однієї фотографії в base64. Ім'я беріть із відповіді
photos_thumbnails або з масиву photos
в download.
Фото віддається по одному — так відповідь не розростається, і ви тягнете тільки те, що справді потрібно.
{ "name": "da75cf11-a672-4965-a545-3556ba4f1c4e" }
{
"ok": true,
"name": "da75cf11-a672-4965-a545-3556ba4f1c4e",
"comment": "Пошкоджена коробка, вид збоку",
"size": 148213,
"data_b64": "/9j/4AAQSkZJRgABAQ…"
}
{ "ok": false, "error": "not_found" }
/receipts/download_photo.
Те саме ім'я, подане в /recounts/download_photo, поверне
not_found — як і документ чужого виду. Той самий
not_found приходить, якщо знімок уже видалено з сервера.
Видаляє документ і всі його дані. Викликайте після того, як результат успішно забрано й проведено у вашій системі, — так список на терміналі не заростає виконаними прийманнями.
Операція ідемпотентна: видалення неіснуючого документа — теж успіх, повтор запиту безпечний.
і для наявного, і для вже видаленого{ "ok": true, "doc_status": "deleted" }
Час у відповідях
Усі дати й час (created_at, started_at,
completed_at) сервер віддає зі зсувом часового поясу:
2026-07-10T08:30:00+03:00. Незаповнений час — null.
Надсилаючи date, вказуйте власний зсув — момент буде
зрозуміло однозначно, навіть якщо ваша система працює в іншому поясі.
Форма без зсуву теж приймається й означає київський час.
Подробиці контракту часу — на сторінці «З чого почати».
Довідник відмов
| Помилка | Коли виникає | Що робити |
|---|---|---|
| conflict | upload: оператор уже приймає постачання
(у відповіді status: InProgress або Done) |
Дочекайтеся завершення й заберіть результат; змінити документ у роботі не можна. |
| validation_failed | Помилка в даних запиту | Виправте за текстом recommendation і повторіть. |
| not_found | download/status: документа з таким
external_id немає |
Перевірте ідентифікатор; можливо, документ уже видалено. |
| unauthorized | Токен бази не передано або він невідомий | Перевірте заголовок X-API-Token. |
Рекомендований алгоритм
- Отримали накладну — сформуйте завдання й надішліть його
upload-ом із новимdocversion. Повтор запиту безпечний: завдяки версії сервер не зробить подвійної роботи. - Отримали
createdабоupdated— завдання на терміналі оператора. Отрималиvalidation_failed— виправте дані за текстомrecommendationі повторіть. - За розкладом опитуйте
status(або оглядово —list). - Статус став
Done— викличтеdownloadі проведіть результат:rows— по рядках накладної (розбіжності — в акт),extra_rows— як незаявлений товар. - Результат проведено — викличте
delete, щоб убрати виконане приймання з термінала. - Періодично проглядайте
listна предметcreated_on_tsd: true— приймань, створених оператором вручну.