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). -
Транзакции: создание и обновление записей выполняются в транзакциях. При ошибке все изменения в базе откатываются автоматически.
-
Отдельный пользователь: вход интеграции разлогинивает человека с тем же логином, и наоборот.