API v2: ключі, права, формат

15 хв

API v2 Elbuz — це REST-доступ до каталогу, прайсів, клієнтів, документів, угод, органайзера й довідників за адресою https://<ваш-домен>/api/v2/. Ключ передається заголовком Authorization: Bearer і діє від імені співробітника: запит бачить і змінює рівно те, що цей співробітник бачить і змінює у вікнах програми. Стаття для розробника інтеграції: як видати ключ, як читати списки, що відбувається із запитом на зміну і які відповіді чекати.

Вікно
«API та токени доступу»
Право доступу
доступ до вікна ключів; обрати іншого співробітника — доступ до вікна користувачів; режим «Робити самому» — «Управління»
Підготувати
співробітника з тими правами, які має отримати інтеграція

Видати ключ

Налаштування системи
розділ «Інші налаштування» → плитка «API та токени доступу»
  1. У вікні «API та токени доступу» натисніть «+». Відкриється картка нового ключа.
  2. У полі «Від імені співробітника» оберіть, чиї права отримає ключ. Список співробітників видно лише тому, у кого є доступ до вікна користувачів; решта видає ключ тільки на себе.
  3. Поле «Користувач» — назва ключа. Вона стоїть у заголовках заявок «Пульсу» («Ключ «site_sync»: змінити товар…»), тож назвіть ключ так, щоб було зрозуміло, чия це інтеграція.
  4. Новий ключ створюється з позначкою «Тільки для читання». Якщо інтеграція має щось змінювати — зніміть її.
  5. Натисніть «Створити ключ» і скопіюйте значення з поля «Новий ключ» кнопкою «Копіювати».
Картка ключа API v2: від імені співробітника, режим змін, запобіжник і новий ключ
1Від імені співробітника
2Зміни даних
3Запобіжник: змін на годину
4Новий ключ
5Тільки для читання
  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»: старе й нове значення кожного поля.

Заявки ключа API в «Пульсі»: створити контрагента і змінити ціну товару
1Зміна через API / MCP
2Що саме зміниться
3Прийняти
4Відхилити
5Прийняти всі від цього ключа
6Прийняти й надалі робити самому
  1. Зміна через API / MCP — заявка ключа; у заголовку — імʼя ключа і що він хоче зробити.
  2. Рядки під заголовком — поле: було → стане (при створенні — заповнені поля).
  3. Прийняти — зміна виконується одразу, а ключ отримає результат у GET /api/v2/approvals/{id}.
  4. Відхилити — нічого не змінюється, заявка отримує статус rejected.
  5. Прийняти всі від цього ключа — по черзі виконує всі заявки, що чекають від цього ключа; режим ключа не змінюється.
  6. Прийняти й надалі робити самому — виконує заявку й перемикає ключ у «Робити самому» (лише «Управління»).

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; власні підписки на вебхуки ключ змінює сам, без заявок.

такнінітактакніПитатиРобити самомутакніЗапит POST, PATCH абоDELETEКлюч «Тільки длячитання»?403, нічого не зміненоПрава власника ключадозволяють?403, 404 або 422 зпричиноюЛист або повідомленняклієнту?Заявка в «Пульсі»,відповідь 202Режим ключаЗапобіжник за годинувичерпано?Ключ переходить у«Питати», у «Пульсі»пропозиція продовжитиВиконано одразу: 200, 201або 204, запис у «Щозробив AI»
Шлях запиту на зміну: перевірка правами — завжди; далі режим ключа вирішує, виконати зараз чи поставити заявку

Що можна скасувати

Кнопка скасування в «Що зробив 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Коли
400bad_requestнемає Idempotency-Key, тіло не JSON-об'єкт, фільтр за невідомим полем, чужий курсор
401unauthorizedнемає заголовка, ключ неправильний, вимкнений або прострочений, співробітник-власник неактивний
403forbiddenадреса не в «IP-адреси для доступу», ключ «Тільки для читання», немає права на кнопку
404not_foundресурсу немає або його вікно закрите, запис не видно за «Чиї дані»
405method_not_allowedоперації в ресурсу немає — наприклад, DELETE /products/2
409conflictтакий запис уже існує (наприклад, контрагент із тими самими даними) — у errors його id
422unprocessableполе не можна записати, посилання на невидимий запис, повтор Idempotency-Key з іншим тілом
429rate_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.

Суміжні теми

Чи була стаття корисною?