API v2 Elbuz — це REST-доступ до каталогу, прайсів, клієнтів, документів, угод, органайзера й довідників за адресою https://<ваш-домен>/api/v2/. Ключ передається заголовком Authorization: Bearer і діє від імені співробітника: запит бачить і змінює рівно те, що цей співробітник бачить і змінює у вікнах програми. Стаття для розробника інтеграції: як видати ключ, як читати списки, що відбувається із запитом на зміну і які відповіді чекати.
- Вікно
- «API та токени доступу»
- Право доступу
- доступ до вікна ключів; обрати іншого співробітника — доступ до вікна користувачів; режим «Робити самому» — «Управління»
- Підготувати
- співробітника з тими правами, які має отримати інтеграція
Видати ключ
- Налаштування системи
- розділ «Інші налаштування» → плитка «API та токени доступу»
- У вікні «API та токени доступу» натисніть «+». Відкриється картка нового ключа.
- У полі «Від імені співробітника» оберіть, чиї права отримає ключ. Список співробітників видно лише тому, у кого є доступ до вікна користувачів; решта видає ключ тільки на себе.
- Поле «Користувач» — назва ключа. Вона стоїть у заголовках заявок «Пульсу» («Ключ «site_sync»: змінити товар…»), тож назвіть ключ так, щоб було зрозуміло, чия це інтеграція.
- Новий ключ створюється з позначкою «Тільки для читання». Якщо інтеграція має щось змінювати — зніміть її.
- Натисніть «Створити ключ» і скопіюйте значення з поля «Новий ключ» кнопкою «Копіювати».
1
Від імені співробітника2
Зміни даних3
Запобіжник: змін на годину4
Новий ключ5
Тільки для читання- Від імені співробітника — чиї права й «Чиї дані» отримає ключ. Інших співробітників тут бачить лише той, у кого є доступ до вікна користувачів.
- Зміни даних — «Питати» (кожна зміна чекає в «Пульсі») або «Робити самому». Перемикає лише «Управління».
- Запобіжник — після стількох виконаних змін за годину ключ сам повертається в «Питати».
- Новий ключ показується один раз: скопіюйте його кнопкою «Копіювати» до закриття вікна.
- Тільки для читання — у нового ключа ввімкнено; зніміть, якщо ключу треба щось змінювати.
Ключ показується один раз. У базі зберігається тільки його відбиток (SHA-256) і перші вісім символів після elbz_ — за ними ви впізнаєте ключ у списку («elbz_6caef5fd_…»). Загубили — натисніть «Створити новий ключ»: старий перестане діяти в ту ж секунду, тож оновіть його в інтеграції одразу.
Решта полів картки діють на кожному запиті, без перевидачі ключа: зняли «Активність» — наступний запит отримає 401; «Дата закінчення доступу» — ключ працює по цю дату включно; «IP-адреси для доступу» — перелік через кому, пробіл або з нового рядка, порожньо — звідусіль.
Перший запит
curl -s "https://<ваш-домен>/api/v2/products?limit=2&fields=product_id,name,price,quantity" \
-H "Authorization: Bearer elbz_xxxxxxxx_…"
Відповідь (демо-акаунт, 14.10.2026):
{"data":[
{"product_id":1,"price":"4536","quantity":100,"name":"Marshall Willen Black and Brass (1006059)"},
{"product_id":2,"price":"0","quantity":0,"name":"ADATA 16 GB DDR4 3600 MHz XPG Spectrix D41 RGB Tungsten Gray (AX4U360016G18I-ST41)"}],
"has_more":true,
"next_cursor":"eyJrIjoiMiIsImgiOiJiZTExNWY1MSJ9"}
Формат однаковий для всіх ресурсів: список — {"data":[…],"has_more":…,"next_cursor":…}, один запис — {"data":{…}}. Id, посилання на інші записи, кількості й лічильники приходять числами, позначки на кшталт flag_export — true/false, гроші й міри — десятковим рядком ("4536"), зовнішні коди (sku, uuid, штрихкоди) — рядком, дати — у форматі RFC 3339 зі зміщенням часового поясу ("2026-10-14T12:42:59+02:00"). Параметр fields= працює і для списку, і для одного запису (GET /products/2?fields=product_id,sku,price). Заголовок Accept-Language: uk перемикає мову назв полів у описі ресурсів.
Повний опис усіх ресурсів, полів і методів — GET /api/v2/openapi.json (OpenAPI 3.1) з тим самим ключем; без ключа — 401. Опис будується під права власника ключа: ресурсів і полів, яких співробітник не бачить, у ньому немає. Короткий перелік — GET /api/v2/: для кожного ресурсу операції, дії й поля з позначками filter, sort, write.
Що бачить ключ
Запит виконується так, ніби співробітник відкрив відповідне вікно. Тому:
- Ресурс доступний, якщо співробітнику відкрите його вікно: товари — вікно товарів, документи — будь-яке з вікон документів. Немає вікна — ресурсу немає ні в описі, ні в списках (404).
- Поле, закрите групі співробітника на перегляд (наприклад, «Ціна собівартість»
price_cost), у відповіді відсутнє зовсім, фільтрувати за ним не можна. Поле без права «Зміна» — 422 при записі. - «Чиї дані» діють так само, як у вікні: менеджер із «Тільки свої» отримає лише своїх клієнтів і свої документи; чужий запис за id — 404.
- Кнопки вікна: створення, видалення, проведення документа перевіряються за правами на відповідні кнопки.
Окремих «скоупів» у ключа немає. Щоб звузити інтеграцію, видайте ключ співробітнику з вужчими правами — наприклад, заведіть користувача у відділі, якому відкрите лише вікно замовлень.
Списки: фільтри, сортування, курсор
| Параметр | Що робить |
|---|---|
limit | розмір сторінки, за замовчуванням 50, найбільше 200 |
fields=product_id,name | залишити у відповіді лише ці поля списку |
filter[поле]=значення | дорівнює |
filter[поле][оператор]=значення | оператори ne, gt, gte, lt, lte, like (містить) |
filter[updated_since]=2026-10-01 | змінені від дати — те саме, що filter[date_modified][gte] |
sort=-quantity | сортування за одним полем; мінус — за спаданням. Друге поле через кому ігнорується |
q= | швидкий текстовий пошук (товари) |
cursor= | значення next_cursor з попередньої сторінки |
Фільтрувати й сортувати можна лише за полями з позначкою filter / sort в описі ресурсу. Невідоме поле — 400 з поясненням: {"errors":{"nosuch":"not filterable"}}.
Як працює курсор. Без sort записи йдуть за зростанням id, і курсор запам'ятовує останній id: нові записи, що з'явилися під час обходу, не зсувають сторінки. З sort курсор запам'ятовує номер сторінки, і запис, який під час обходу змінив позицію в сортуванні, може трапитися двічі або випасти. Для синхронізації беріть варіант без sort. Курсор прив'язаний до фільтрів і сортування запиту: змінили їх і передали старий курсор — 400 cursor does not match the query. Кінець списку — "has_more":false і "next_cursor":null.
Довідники (currencies, warehouses, document_statuses та інші) віддаються цілком, до 500 рядків, без курсора. Рядки документа — лише разом із документом: GET /api/v2/document_items?filter[document_id]=123; без фільтра — 400.
curl -s -g "https://<ваш-домен>/api/v2/products?filter[quantity][gt]=5&fields=product_id,name,quantity&limit=100" \
-H "Authorization: Bearer elbz_…"
Зміни: 202 і заявка в «Пульсі»
| Запит | Що робить |
|---|---|
POST /api/v2/{ресурс} | створити запис |
PATCH /api/v2/{ресурс}/{id} | змінити передані поля (решта не чіпаються) |
DELETE /api/v2/{ресурс}/{id} | перемістити в кошик — тільки там, де в ресурсу є кошик |
POST /api/v2/{ресурс}/{id}/{дія} | дія: провести документ, об'єднати дублі, запустити вивантаження тощо |
Що станеться із запитом, вирішує поле «Зміни даних» у картці ключа.
«Питати (через «Пульс»)» — значення за замовчуванням. Elbuz перевіряє запит правами власника ключа (ресурс, поле, кнопку, «Чиї дані») і, якщо все гаразд, нічого не змінює, а ставить заявку в «Пульс». Інтеграція отримує 202 Accepted і адресу, де стежити за рішенням:
HTTP/1.1 202 Accepted
Location: /api/v2/approvals/3629
{"data":{"status":"pending","approval_id":3629}}
Заявку бачать співробітники з доступом до вікна ключів API. У заголовку — назва ключа й що він хоче зробити, під ним — «Ціна: 0 → 1890»: старе й нове значення кожного поля.
1
Зміна через API / MCP2
Що саме зміниться3
Прийняти4
Відхилити5
Прийняти всі від цього ключа6
Прийняти й надалі робити самому- Зміна через API / MCP — заявка ключа; у заголовку — імʼя ключа і що він хоче зробити.
- Рядки під заголовком — поле: було → стане (при створенні — заповнені поля).
- Прийняти — зміна виконується одразу, а ключ отримає результат у GET /api/v2/approvals/{id}.
- Відхилити — нічого не змінюється, заявка отримує статус rejected.
- Прийняти всі від цього ключа — по черзі виконує всі заявки, що чекають від цього ключа; режим ключа не змінюється.
- Прийняти й надалі робити самому — виконує заявку й перемикає ключ у «Робити самому» (лише «Управління»).
GET /api/v2/approvals/3629 повертає status: pending — чекає, approved — прийнято й виконано (у result — запис після зміни), auto — виконано без людини в режимі «Робити самому», rejected — відхилено, нічого не змінено, error — прийнято, але виконати не вдалося, undone — зміну скасовано у «Що зробив AI». Ключ бачить лише свої заявки.
«Робити самому» — зміна виконується одразу: створення відповідає 201 із заголовком Location, правка — 200 із записом після зміни (в обох — ще й approval_id), видалення — 204 без тіла. Кожна зміна все одно записується в «Пульс» зі статусом «AI зробив сам» і видна у вкладці «Що зробив AI», звідки її можна скасувати. Увімкнути «Робити самому» може лише «Управління».
Запобіжник. Якщо ключ у «Робити самому» за годину виконав стільки змін, скільки вказано в полі «Запобіжник: змін на годину» (за замовчуванням 500), наступна зміна вже не виконується: ключ сам перемикається на «Питати», а в «Пульсі» з'являється пропозиція «Ключ «…» зробив N змін за годину й поставлений на паузу — продовжити без підтвердження?». Поки її не прийняли, усі зміни ключа йдуть заявками (202).
Незалежно від режиму ключа: відповідь клієнту на лист (/mail_messages/{id}/reply) і повідомлення в чат (/chats/{id}/send) стають заявкою «Пульсу» свого типу — як листи, які готує сам AI Elbuz. Вони чекають людину, доки «Управління» не ввімкнуло для цього типу «Робити самому» у вкладці «Довіра» і лист пропустив AI-«Контролер»; ключ із «Тільки для читання» на будь-який запис отримує 403; власні підписки на вебхуки ключ змінює сам, без заявок.
Що можна скасувати
Кнопка скасування в «Що зробив AI» є для: правки полів будь-якого ресурсу (повертає попередні значення), створення й видалення контрагента, документа, угоди, задачі, нотатки, проєкту, статті (через кошик), проведення й скасування проведення, позначки «виконано» в задачі. Правку полів скасування не поверне, якщо ці поля вже змінили після API, — відповідь «скасуйте вручну». Кнопки немає для створення товару, категорії, виробника, атрибута, групи атрибутів, групи контрагентів і дотику (у них немає кошика), для об'єднання дублів, переміщення угоди на етап і запуску фонових задач.
Особливості PATCH
У товарів, виробників, контрагентів, документів і угод поля записуються по одному тим самим шляхом, що й правка клітинки в сітці вікна; у решти ресурсів — одним викликом функції збереження. Поле, якого немає в описі ресурсу, службове або закрите правами, відхиляється до запису всього запиту — 422 з переліком полів. Якщо ж у ресурсу з правкою по полю одне поле відхилила перевірка самої програми (наприклад, недопустиме значення), відповідь теж 422, але інші поля з того самого запиту вже записані: перечитайте запис GET, перш ніж повторювати.
Idempotency-Key
Кожен POST (створення й дії) зобов'язаний мати заголовок Idempotency-Key — будь-який унікальний рядок до 255 символів, наприклад UUID. Без нього — 400. Відповідь зберігається 24 години: повтор із тим самим ключем і тим самим тілом не створює дубль, а повертає збережену відповідь із заголовком Idempotent-Replayed: true. Той самий ключ з іншим тілом — 422.
curl -s -X POST "https://<ваш-домен>/api/v2/contractors" \
-H "Authorization: Bearer elbz_…" -H "Content-Type: application/json" \
-H "Idempotency-Key: order-sync-2026-10-14-0001" \
-d '{"name":"ТОВ «Тест API»","email":"test-api@example.com"}'
Помилкова відповідь (400, 422) теж запам'ятовується під цим ключем. Виправили тіло — беріть новий Idempotency-Key, інакше отримаєте 422 «Idempotency-Key was used with another request». Не зберігаються лише 429 і помилки сервера.
Помилки й ліміти
Помилки приходять у форматі RFC 9457 (application/problem+json) зі справжнім кодом HTTP:
{"type":"https://elbuz.com/problems/unprocessable","title":"Unprocessable","status":422,
"detail":"some fields cannot be written","errors":{"date_modified":"not writable"}}
| Код | type | Коли |
|---|---|---|
| 400 | bad_request | немає Idempotency-Key, тіло не JSON-об'єкт, фільтр за невідомим полем, чужий курсор |
| 401 | unauthorized | немає заголовка, ключ неправильний, вимкнений або прострочений, співробітник-власник неактивний |
| 403 | forbidden | адреса не в «IP-адреси для доступу», ключ «Тільки для читання», немає права на кнопку |
| 404 | not_found | ресурсу немає або його вікно закрите, запис не видно за «Чиї дані» |
| 405 | method_not_allowed | операції в ресурсу немає — наприклад, DELETE /products/2 |
| 409 | conflict | такий запис уже існує (наприклад, контрагент із тими самими даними) — у errors його id |
| 422 | unprocessable | поле не можна записати, посилання на невидимий запис, повтор Idempotency-Key з іншим тілом |
| 429 | rate_limited | перевищено ліміт запитів |
Кожна відповідь має заголовок X-Request-Id — назвіть його підтримці, і запит знайдуть у журналі.
Ліміт — 120 запитів за ковзну хвилину на ключ (більше — лише якщо підтримка підняла ліміт цьому ключу); запити MCP-асистента тим самим ключем рахуються в той самий ліміт. Залишок видно в заголовках кожної відповіді: RateLimit-Policy: "default";q=120;w=60 і RateLimit: "default";r=119;t=60 (r — скільки лишилося, t — секунд до звільнення). На 429 прийде Retry-After — зачекайте вказані секунди.
Ресурси
Набір нижче — для співробітника з повним доступом; ключ отримує лише ті, чиї вікна відкриті власнику.
| Ресурс | Операції | Дії |
|---|---|---|
products | список, запис, створення, правка | — |
categories, manufacturers | список, запис, створення, правка | merge |
attributes | список, запис, створення | merge |
attribute_groups | список, запис, створення | — |
supplier_products (рядки прайсів) | список, запис | — |
contractors | усе, видалення — у кошик | merge |
companies, contractor_groups | список, запис (групи — ще створення й правка) | — |
documents (+ document_items) | усе, видалення — у кошик | sign, unsign |
deals, pipelines | угоди — усе, видалення в кошик; воронки — список | move_stage |
tasks, notes, projects | усе, видалення — у кошик | done, reopen |
touches (дотики в календарі) | список, запис, створення, правка | — |
mail_messages, chats, chat_messages, calls | лише читання | reply, send — завжди через «Пульс» |
pulse_items | список, запис | accept, reject, accept_trust, undo |
users | лише читання, без паролів і ключів входу | — |
articles | усе, видалення — у кошик | — |
price_lists, export_templates, flows | список, запис | import / run — фонова задача |
import_templates, jobs, sales_report | лише читання | — |
webhooks, webhook_deliveries | вебхуки цього ключа | — |
довідники: document_types, document_statuses, payment_statuses, delivery_statuses, payment_types, delivery_types, stock_statuses, warehouses, stores, currencies, languages | лише читання, цілим списком | — |
Дії з фоновою задачею (/price_lists/{id}/import, /export_templates/{id}/run, /flows/{id}/run) відповідають {"data":{"status":"queued","job_id":…}}, у режимі «Питати» — спершу 202 і заявкою в «Пульсі»; хід роботи — GET /api/v2/jobs/{id}. Агрегати («скільки замовлень за статусами», «сума продажів по менеджерах») — GET /api/v2/query?spec={…}; перелік сутностей і полів — ?spec={"describe":true}.
Сценарії
Сайт забирає залишки й ціни
Ключ від імені співробітника, якому відкрите лише вікно товарів, з «Тільки для читання». Раз на 10 хвилин — GET /products?filter[updated_since]=…&fields=product_id,sku,price,quantity без sort, обхід курсором. Закупівельна ціна не потрапить у відповідь, якщо її поле закрите групі цього співробітника.
Замовлення з сайту без дублів
Ключ із режимом «Робити самому» від менеджера відділу продажів. Кожне замовлення — POST /documents з Idempotency-Key = номер замовлення на сайті; обрив зв'язку й повтор не створять другий документ. Провести — POST /documents/{id}/sign.
Підрядник править описи, а ви перевіряєте
Ключ у режимі «Питати» від співробітника з правом на вікно товарів. Кожен PATCH приходить у «Пульс» рядком «Опис повний: … → …». Якщо правки добрі — «Прийняти всі від цього ключа»; якщо довіряєте — «Прийняти й надалі робити самому».
Чого API v2 не робить
- Не видаляє безповоротно.
DELETEє лише там, де є кошик; товари, категорії, виробники, атрибути видаляються тільки у вікні програми. - Не надсилає листів і повідомлень клієнтам у обхід «Пульсу». Режим ключа на них не діє: відповідь клієнту — заявка «Пульсу» з довірою свого типу.
- Не приймає SQL і довільних полів. Фільтри й запис — лише за полями з опису ресурсу; решта — 400 або 422.
- Не має пакетного запису. Кожен запис — окремий запит; на 120 запитів за хвилину розраховуйте обсяг.
- Не приймає старий токен.
api_tokenі вхідapi/loginдо v2 не підходять; як перейти — у статті API Elbuz (v1).
Розбір частих проблем
| Що ви бачите | Чому так | Що зробити |
|---|---|---|
| 401 «invalid, disabled or expired key» | ключ перевипущено, вимкнено «Активність» або минула дата закінчення | перевірте картку ключа (видати ключ) |
| На PATCH приходить 202, а дані не змінились | ключ у режимі «Питати» | прийміть заявку в «Пульсі» або перемкніть ключ (зміни) |
| 403 «read-only key» | у нового ключа ввімкнено «Тільки для читання» | зніміть позначку в картці ключа |
| У відповіді немає поля, яке є у вікні | поле закрите групі власника ключа | відкрийте поле в правах групи або видайте ключ іншому співробітнику |
| 422 «Idempotency-Key was used with another request» | той самий ключ ідемпотентності з іншим тілом | новий Idempotency-Key (докладно) |
| 400 «cursor does not match the query» | курсор від запиту з іншими фільтрами | почніть обхід без cursor |
Часті питання
Де взяти ключ API v2?
Налаштування системи → «Інші налаштування» → «API та токени доступу» → «+» → «Створити ключ». Ключ показується один раз.
Чи можна дати ключу доступ лише до замовлень?
Так: видайте ключ від імені співробітника, якому відкрите лише вікно замовлень. Ключ отримує права окремо взятого співробітника — вікна, поля й «Чиї дані».
Чому зміна через API повертає 202?
Ключ у режимі «Питати»: зміна чекає підтвердження в «Пульсі». Статус — GET /api/v2/approvals/{id}. Щоб змінювати одразу, «Управління» перемикає ключ на «Робити самому».
Скільки запитів на хвилину дозволено?
120 за ковзну хвилину на ключ, разом із запитами MCP цим самим ключем. Залишок — у заголовку RateLimit, на 429 — Retry-After.
Де опис усіх методів?
GET https://<ваш-домен>/api/v2/openapi.json з ключем у заголовку. Опис складено під права власника ключа.
Чи можна видалити товар через API?
Ні. Через API в кошик видаляються лише контрагенти, документи, угоди, задачі, нотатки, проєкти й статті. Дублі контрагентів, категорій, виробників і атрибутів об'єднуються дією merge.
Суміжні теми
- Підключити AI-асистента через MCP — той самий ключ для Claude, ChatGPT, Codex, Cursor.
- Вебхуки API v2 — Elbuz сам повідомляє про зміни.
- API Elbuz (v1) — старий API і перехід на v2.
- Користувачі й права — від них залежить, що бачить ключ.
- «Пульс» — де приймати заявки ключа й що робить «Що зробив AI».
- AI-«Контролер» — хто перевіряє листи клієнтам перед відправкою без людини.

