API ERPJS
API (інтерфейс програмування застосунків) — набір інструментів для автоматизації роботи із системою ERPJS. Дозволяє створювати, читати, оновлювати та видаляти записи в будь-якому реєстрі, виконувати звіти, працювати з файлами та отримувати оновлення в реальному часі через WebSocket.
Адреса
Усі шляхи нижче відлічуються від адреси вашої системи — тієї, за якою ви відкриваєте ERPJS у браузері (вигляд https://s.erpjs.biz/ваша-система). Окремого префікса на кшталт /v1 немає.
Автентифікація
Отримання токена
Для роботи з API потрібен JWT-токен. Його видає вхід у систему:
curl -X POST https://s.erpjs.biz/ваша-система/public/login \
-H "Content-Type: application/json" \
-d '{"login": "your_login", "password": "your_password"}'
jwt — це і є токен для подальших запитів. Компанію в запиті не передають: сервер визначає її сам і записує в токен. Токен діє 8 годин.
Замість пароля можна входити MCP-токеном користувача (його створює пункт «Згенерувати MCP-токен» у картці користувача): POST /public/mcp-login з тілом {"token": "<MCP-токен>"} повертає такий самий jwt.
Кожен вхід завершує попередні сесії цього користувача. Інтеграція й людина під одним логіном вибивають одне одного — заведіть інтеграції окремого користувача. «Токен API» з кабінету erpjs.biz — для іншого сервісу, до
/records/*системи він не підходить.
Передача токена
Токен передається в заголовку HTTP: Authorization: Bearer <токен>. Cookie сервер для перевірки токена не читає.
Приклад
export TOKEN="<ваш_токен>"
export BASE_URL="https://s.erpjs.biz/ваша-система"
curl -X POST $BASE_URL/records/list \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"datadef": "Contacts", "query": {"limit": 10}}'
Робота з записами
Всі операції з записами виконуються через POST-запити до ендпоінтів /records/*.
Список записів
POST /records/list — отримати записи з реєстру з фільтрацією, сортуванням та пагінацією.
{
"datadef": "Invoices",
"query": {
"where": { "fOKFlag": 1 },
"order": [["fInvDate", "DESC"]],
"limit": 50,
"offset": 0,
"search": "пошуковий текст"
}
}
Відповідь — масив записів (без загальної кількості). У query допустимі лише ключі where, order, limit, offset, search. Понад 10 000 записів за один запит сервер не віддає — відповідь 400; беріть порціями через limit і offset.
POST /records/sqlList — розширений список з вибором конкретних полів та групуванням (query.groupBy). Перелік полів fields обов'язковий.
{
"datadef": "Invoices",
"fields": ["fSerNr", "fCustCode", "fSum4", "fInvDate"],
"query": {
"where": { "fOKFlag": 1, "fInvDate": { "$gte": "2026-01-01" } },
"order": [["fInvDate", "DESC"]],
"limit": 100,
"offset": 0,
"search": { "search": "Клієнт", "column": "fCustCode" }
}
}
Відповідь: {"res": [...], "qty": "1234"} — масив записів та загальна кількість (qty приходить рядком).
Умову where задають об'єктом: значення порівнюються як є, оператори — з $ ($in, $gte, $like тощо); голі in, gt — помилка 400. Рядок SQL сервер поки теж приймає, але це застаріла форма: її можуть вимкнути, і вона має починатися зі слова WHERE.
Перегляд запису
POST /records/show — отримати повні дані запису, включаючи матриці, файли та зв'язки.
{
"datadef": "Invoices",
"id": 123
}
Відповідь містить:
- Всі поля запису
- кожну матрицю — окремим ключем зі своїм ім'ям, наприклад "InvoicesMatrix": {"headers": [...], "payload": [...]} (рядки товарів у рахунку-фактурі)
- __files — кількість прикріплених файлів
- __links — кількість зв'язаних документів
- __lock — є, лише якщо запис заблокований: true — вашим блокуванням, логін — чужим
- __lastUpdated — час останнього оновлення
- а також __permissions (права на запис і поля) та __revision
Значення за замовчуванням
POST /records/defaults — отримати значення за замовчуванням для нового запису.
{
"datadef": "Invoices"
}
Створення запису
POST /records/create — створити новий запис. Матриці передаються в тому ж запиті.
{
"datadef": "Contacts",
"data": {
"fCode": "C-001",
"fName": "Нова компанія",
"fCUType": 1,
"fPhone": "+380501234567"
}
}
Приклад створення запису з матрицею (поля рядків матриці теж починаються з f):
{
"datadef": "Invoices",
"data": {
"fCustCode": "C-001",
"fInvDate": "2026-03-28",
"fCurncyCode": "UAH",
"InvoicesMatrix": {
"payload": [
{
"fArtCode": "ITEM-001",
"fQuant": 5,
"fPrice": 100
}
]
}
}
}
Оновлення запису
POST /records/update — оновити існуючий запис.
{
"datadef": "Contacts",
"id": 123,
"data": {
"fPhone": "+380509876543"
}
}
Спочатку заблокуйте запис.
updateприймає лише запис, який ви відкрили на редагування викликомsetLock(див. «Блокування записів»); без блокування відповідь — 423 «запис не відкрито для редагування», під чужим блокуванням — теж 423.Надсилайте лише ті поля, які міняєте. Поле, якого немає в
data, система вважає незайманим і зберігає таким, яким воно записане в документі; матриця, якої немає вdata, теж не зачіпається. Надіслане поле пишеться як є і може затерти зміну, яку хтось зробив між вашим читанням і записом. Надіслана матриця замінює попередню цілком.
Дати
Дата з часом приходить у відповіді records/show з міткою Z (наприклад, 2026-09-15T07:05:00Z). Якщо ви
надсилаєте її назад без змін, система впізнає незмінене значення і зберігає його як було (так ядро працює з 26.09.2026).
Зсув можливий, лише якщо значення встиг змінити хтось інший між вашим читанням і записом, — тож головне правило
те саме: не надсилайте дату, яку не міняли.
MCP-конектор ERPJS (інструмент update_record) теж впізнає дату, яку ви прочитали й надсилаєте назад без змін;
у режимі applyWactions: false тіло йде в систему дослівно.
Нове значення:
- у формі відповіді (
2026-09-15T07:05:00Z) читається як справжній момент часу — для Києва це 10:05; - з явним поясом:
2026-09-16T08:45:00+03:00запишеться як 08:45 за Києвом; - у форматі
ДД/ММ/РРРР("17/09/2026") абоРРРР-ММ-ДД— як календарний день без зсуву; у поля «дата з часом» час стане 00:00. Час задають так:ДД/ММ/РРРР ГГ:ххабоРРРР-ММ-ДД ГГ:хх:сс— це місцевий час сервера.
Поля «дата без часу» (ДД/ММ/РРРР у вікні, у відповіді show — теж ДД/ММ/РРРР) зсув не зачіпає.
Видалення запису
POST /records/delete — видалити запис.
{
"datadef": "Contacts",
"id": 123
}
Увага: запис з прикріпленими файлами не може бути видалений. Спочатку видаліть файли (
softDeleteAttachment).
Метадані та модель даних
POST /system/model — отримати структуру (схему) реєстру: список полів, типи, валідації.
{
"datadef": "Invoices"
}
POST /system/meta — отримати метадані запису: __lock, __files, __links, __actions, __lastUpdated, __revision, __permissions.
{
"datadef": "Invoices",
"id": 123
}
Звіти
POST /reports/<Звіт>/<вид> — виконати звіт з параметрами. Вид у більшості звітів — simple (наприклад, /reports/SalesReport/simple).
{
"fFrom": "2026-01-01",
"fTo": "2026-03-31",
"fCustCode": "C-001",
"_meta": {
"htmlFast": true
}
}
Параметр _meta задає спосіб відповіді:
- htmlFast: true — відповідь одразу HTML-рядком; разом із getContext: true — дані звіту в JSON;
- без htmlFast відповідь — лише ключ {key}: результат приходить подіями WebSocket, а файли забирають через GET /system/download-report;
- disableHtml: true, disableXlsx: true — пропустити збирання HTML чи Excel-файлу в такому повному звіті.
Параметри звіту сервер перевіряє так само, як вікно звіту: період, у якому початок пізніше за кінець, код, якого немає в
довіднику, номер документа не числом. Тоді звіт не будується, а відповідь — помилка валідації з кодом 400, ім'я поля — у data.field.
Файли
Завантаження файлу (upload)
POST /system/upload — завантажити файл і прикріпити до запису. Використовуйте multipart/form-data.
Поля форми:
- file — файл
- data — JSON з параметрами: Register, RecordId, FileRealName, FileSize, CHECKSUM (sha256 у hex)
Потрібне право на реєстр запису; розмір файлу — до 10 МБ.
Скачування файлу (download)
GET /system/download/<uuid> — скачати файл за його UUID.
Видалення файлу
POST /system/softDeleteAttachment — позначити файл як видалений. Тіло: {"datadef": "Attachments", "id": <id файлу>}; потрібне право редагування запису, до якого файл прикріплено.
Блокування записів
Система блокувань запобігає одночасному редагуванню запису кількома користувачами. Для records/update блокування обов'язкове.
POST /system/setLock— заблокувати запис для редагуванняPOST /system/checkLock— перевірити чи запис заблокований та кимPOST /system/removeLock— зняти блокуванняGET /system/lockList— список усіх активних блокувань
Блокування живе 5 хвилин. Повторний setLock того самого користувача продовжує його ще на 5 хвилин — так робить вікно
редагування (кожні 10 секунд). Якщо робота з записом триває довше, повторюйте setLock; не зняте вчасно блокування
(інтеграція впала, вкладку закрили) минає само.
Права доступу
У тілі передається перелік імен — без нього відповідь 400.
POST /system/getPermissionsRegisters{"registers": [...]}— права на реєстри (list,read,create,edit,removeта ін.)POST /system/getPermissionsModules{"modules": [...]}— права на модуліPOST /system/getPermissionsReports{"reports": [...]}— права на звітиPOST /system/getPermissionsMaintenances{"maintenances": [...]}— права на процедури обслуговування
WebSocket (реальний час)
ERPJS підтримує WebSocket-з'єднання через Socket.IO для отримання оновлень у реальному часі.
Підключення: Socket.IO за шляхом <адреса системи>/socket.io, токен — у рукостисканні: auth: {token: "<токен>"}.
Події від сервера:
- system_version — версія сервера (при підключенні)
- push:<login> — непрочитані сповіщення користувача (відповідь на :live:)
- update-tasks — оновлення списку задач
Події від клієнта:
- :live: — підтвердження активності й запит непрочитаних сповіщень
- push:success — підтвердження отримання сповіщень (масив їхніх id)
- get:activeUsers — запит списку активних користувачів (відповідь — через callback)
Процедури та обслуговування
POST /maintenances/<назва>/<задача> — виконати процедуру обслуговування (імпорт, експорт, масові операції); у більшості служб задача — first. Сервер перевіряє права ролі на службу.
POST /custom/<назва> — виконати серверну процедуру; маршрутами стають лише процедури, оголошені в системі.
Публічні ендпоінти (без токена)
Деякі ендпоінти доступні без автентифікації:
POST /public/login— вхід у системуPOST /public/mcp-login— вхід MCP-токеномGET /public/qrDownloadFiles— завантаження файлів за QR-кодом/openserver/<маршрут>(GETабоPOST) — відкриті API-ендпоінти
На все під /public і /openserver, включно із входом, діє обмеження частоти: 10 запитів за 30 секунд з однієї IP на один шлях, далі — відповідь 429.
Коди відповідей
| Код | Опис |
|---|---|
| 200 | Успішний запит |
| 400 | Помилка валідації (деталі в тілі відповіді: message, data) |
| 401 | Невалідний або відсутній токен, сесію замінено новим входом |
| 403 | Недостатньо прав доступу |
| 404 | Реєстр або запис не знайдено |
| 423 | Запис не заблоковано вами (немає setLock) або його тримає інший |
| 429 | Перевищено обмеження частоти запитів |
| 500 | Внутрішня помилка сервера |
Поради з інтеграції
-
Пагінація: використовуйте
limitтаoffsetдля великих обсягів даних. ЕндпоінтsqlListповертаєqty— загальну кількість записів;listвіддає не більше 10 000 записів за запит. -
Матриці: при створенні або оновленні документа з товарами (рахунок-фактура, замовлення) передавайте матрицю в полі з відповідною назвою (наприклад,
InvoicesMatrix) у вигляді{"payload": [...]}. -
Валідація: сервер виконує бізнес-логіку валідації (recordCheck). Помилки валідації повертаються з кодом 400; ім'я поля з помилкою — у
data.field. -
Блокування: перед оновленням запису встановіть блокування (
setLock) — без ньогоupdateвідповість 423, — а після зніміть його (removeLock). -
Транзакції: створення та оновлення записів виконуються в транзакціях. При помилці всі зміни в базі відкатуються автоматично.
-
Окремий користувач: вхід інтеграції розлогінює людину з тим самим логіном, і навпаки.