ERPNext REST API: подключение n8n, сайта и внешних сервисов
АйТи Фреш
Linux, Docker и DevOps

ERPNext по REST API: как подключить n8n, сайт и внешние сервисы и не нарваться на дубли

Автор: , директор ООО «АйТи-Фреш» · · ~13 мин чтения
Две шестерни, связанные лентой-конвертом со скобками JSON и штампом-ключом, интеграция ERPNext и n8n по REST API
Ключ-штамп на ленте не пропускает дубли между системами.

У ERPNext REST API есть из коробки: /api/resource/<DocType> даёт CRUD по любому документу, /api/method/<путь> вызывает вашу логику. n8n подключается узлом HTTP Request с токеном API-пользователя. Ниже: примеры запросов, вебхуки, защита от дублей, разбор бетонного поставщика и проверки до запуска.

REST API ERPNext: что это такое и чем отличаются /api/resource и /api/method

Для каждого DocType Frappe автоматически создаёт набор операций создания, чтения, изменения и удаления по адресу /api/resource/:doctype. Писать для этого код не нужно: клиент, заказ, счёт, заявка получают API в момент создания типа документа, а права доступа применяются как для обычного пользователя. Это главное свойство, о котором стоит помнить: API не обходит права, и пользователь API видит только то, что разрешено его роли.

Второй путь — /api/method/<модуль.функция>. Через него вызывают серверные методы, помеченные как доступные извне (whitelisted). По документации Frappe, чтение отдают GET-запросом, изменения базы — POST, ответ приходит в ключе message, а ошибка в ключе exc. Если вам нужна не запись документа, а бизнес-действие, например «рассчитать остаток по объекту», пишете метод и вызываете его через /api/method.

Таблица CRUD-операций по документации: | Операция | Метод | Адрес | |---|---|---| | Создать | POST | /api/resource/:doctype | | Прочитать | GET | /api/resource/:doctype/:name | | Изменить | PUT | /api/resource/:doctype/:name | | Удалить | DELETE | /api/resource/:doctype/:name | | Список | GET | /api/resource/:doctype |

Для списка есть параметры: fields (какие поля вернуть), filters (условия, объединяются по И), or_filters (по ИЛИ), order_by, limit_start и limit_page_length для постраничной выборки. По умолчанию список возвращает 20 записей и только поле name, поэтому «пустой» ответ с одним полем — не ошибка, а умолчание. Это частая причина обращений: интегратор ждёт все поля, а получает одно. Как мы настраиваем ERPNext под ключ и интеграции, описано на странице ERPNext под ключ.

Что в ответе: успех возвращает JSON с ключом data при работе с документами, ошибка — ключи exc и exc_type с текстом исключения. Не логируйте тело ответа об ошибке в открытые каналы: оно может содержать имена полей и служебные детали.

Версию Frappe и полные параметры API сверяйте с документацией вашей версии: ключи и поведение между v15 и v16 могут отличаться.

Как подключить n8n к ERPNext: аутентификация, запрос и обработка ответа

Аутентификация. Основной способ для интеграций — токен: пара api_key и api_secret, которую генерируют для пользователя. По документации Frappe, в заголовке Authorization передаётся строка вида token api_key:api_secret. Ключи создают в карточке пользователя на вкладке настроек, в разделе API Access, кнопкой Generate Keys. Секрет показывается один раз, и действует только последний выданный, поэтому его сразу кладут в менеджер паролей, а не в таблицу.

В n8n подходит узел HTTP Request. По документации n8n, у него есть методы GET, POST, PUT, PATCH, DELETE, тело запроса в JSON, пагинация и пакетная отправка, а для авторизации — общий тип учётных данных Header Auth: вы задаёте имя заголовка Authorization и значение с токеном. Секрет хранится в учётных данных n8n, а не в тексте узла. Если токен вы вставите в узел, он попадёт в экспорт сценария, и в репозиторий уйдёт секрет.

Пример запроса на создание лида. Адрес и ключи подставьте свои; имена полей Lead проверьте в своей версии:

curl -s -X POST "https://erp.example.com/api/resource/Lead" \
  -H "Authorization: token $API_KEY:$API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"first_name":"Иван","email_id":"ivan@example.com"}'

Ответ вернёт созданный документ с его именем, и это имя n8n сохраняет дальше в цепочке.

Схема сценария. Триггер: форма сайта или письмо. Узел HTTP Request: POST в /api/resource/Lead. Ответ: имя созданного документа. Следующий узел записывает ответ и уведомляет менеджера в Telegram. Для своей бизнес-логики добавляется второй узел с вызовом /api/method. Проверка соединения перед запуском: вызовите под токеном GET /api/method/frappe.auth.get_logged_user и убедитесь, что вернулся именно API-пользователь, а не администратор.

Про связку с ИИ и мессенджерами. В обсуждениях на форуме встречается связка ERPNext, n8n и ChatGPT с WhatsApp, но готового проверенного сценария, который можно взять как есть, я не видел. Поэтому любой сценарий вы собираете и проверяете сами на тестовой базе, а не копируете из чужого примера. Про сам n8n у нас есть материалы: автоматизация процессов без программиста и n8n для отдела продаж на своём сервере.

Webhook и события документа: когда ERPNext сам сообщает о событии

Опрашивать систему по расписанию дорого и поздно. Если нужно, чтобы n8n узнал о проведённой отгрузке сразу, ERPNext отправляет событие сам. По документации Frappe, для этого есть тип документа Webhook: вы выбираете событие документа (например, on_update или on_submit), добавляете необязательное условие, адрес получателя, метод (по умолчанию POST), заголовки и структуру данных: форма или JSON с шаблонами Jinja. Настройка делается в интерфейсе, а не в коде приложения.

Две вещи стоит включить сразу. Первая: секрет вебхука. Тогда ERPNext добавляет заголовок X-Frappe-Webhook-Signature с подписью (base64 от HMAC-SHA256 тела), и n8n может проверить, что запрос пришёл от вашей системы, а не от случайного отправителя. Вторая: журнал. Для каждой попытки отправки, и успешной, и с ошибкой, создаётся запись Webhook Request Log, где видно, что, когда и с каким ответом ушло.

Для разработки на уровне приложения есть события документа в hooks.py (on_submit, on_update) и, начиная с Frappe v15, транзакционные хуки frappe.db.after_commit.add(функция): их используют, когда отправка должна случиться только после успешной фиксации транзакции. Это уже работа разработчика, а для типовых задач хватает Webhook в интерфейсе.

Сравнение трёх способов получить данные: | Способ | Кто инициирует | Задержка | Если получатель недоступен | Нагрузка на базу | |---|---|---|---|---| | REST /api/resource | вы, по запросу | по запросу | вы повторите запрос | зависит от выборки | | Webhook | ERPNext, по событию | по событию | 3 попытки подряд, затем событие теряется | малая | | Опрос из n8n | вы, по расписанию | по расписанию | вы повторите опрос | растёт с частотой |

Какой выбрать: если нужна реакция на событие, вебхук; если нужна выборка по условию, REST; опрос оставляйте на случай, когда вебхук невозможен. Про повторы важно знать точно. По исходному коду Frappe v15 (webhook.py, функция enqueue_webhook) фоновая задача делает до трёх попыток подряд с паузами в несколько секунд и таймаутом запроса 5 секунд по умолчанию; если получатель лежит дольше, событие больше не досылается, остаются только записи в журнале. Поэтому для критичных событий нужен либо периодический добор по REST, либо очередь на стороне получателя.

Как не создавать дубли при повторной отправке: идемпотентность и внешний ключ

Дубли — главный враг интеграции. Форма сайта отправляется дважды, n8n повторяет запрос после таймаута, оператор запускает сценарий вручную. Если каждое такое действие создаёт новый документ, через неделю в базе пять одинаковых заявок. Защита называется идемпотентностью: повторная отправка того же события не должна создавать второй документ, а должна обновить существующий.

Рецепт, который я использую во всех интеграциях: каждая внешняя сущность хранит пару source_system и source_id, то есть откуда пришла и под каким номером. Эти два поля заводятся в ERPNext как пользовательские (Custom Field) на нужном типе документа. Перед созданием n8n ищет документ по этому ключу. Нашли — обновляем, не нашли — создаём и записываем ключ. Проверка простая: отправили один и тот же счёт дважды, а в базе одна запись.

Поиск по ключу делается списком с фильтром:

curl -s -G "https://erp.example.com/api/resource/Lead" \
  -H "Authorization: token $API_KEY:$API_SECRET" \
  --data-urlencode 'filters=[["source_id","=","site-10345"]]' \
  --data-urlencode 'fields=["name","source_id"]'

Пустой список значит «такого нет, создайте»; непустой — «обновляйте по name методом PUT». Имена полей source_id и source_system выбираются вами, это не стандартные поля, а пользовательские.

Для обмена с бухгалтерией правило то же: обмен с 1С строят через REST или файловый обмен, и каждый документ должен нести внешний ключ. Про интеграцию с учётной системой у нас есть материал про n8n и счета в 1С. Там описан другой ракурс: состав обмена, а не работа с API.

И про очереди сообщений. Асинхронная очередь между системами защищает от потерь, когда одна из сторон недоступна. Если интеграция критична, например заявки на бетон нельзя потерять, ставьте очередь или хотя бы журнал необработанных событий с повторной отправкой.

«Бетон-Онлайн Сервис»: заявки с сайта в ERPNext и статус отгрузки обратно

Условный пример, цифры вымышленные. «Бетон-Онлайн Сервис» поставляет бетон строительным компаниям и частникам, в штате 27 человек: диспетчеры, менеджеры, водители, лаборатория, бухгалтерия. Заявки приходят с сайта и по телефону. Задача: заявка с сайта сразу попадает в ERPNext как лид, менеджер получает уведомление, а когда отгрузка проведена, клиент получает сообщение о статусе.

Первый поток: форма сайта вызывает сценарий n8n, который создаёт Lead через POST в /api/resource/Lead. Ответ с именем документа n8n сохраняет в своей таблице соответствий и отправляет менеджеру уведомление в Telegram. Ключ заявки сайта пишется в поле source_id, а источник в source_system. Второй поток: после проведения отгрузочного документа ERPNext отправляет вебхук на событие on_submit в n8n, тот находит клиента по ключу и отправляет сообщение.

Что пошло не так при первых тестах: заявка с сайта дублировалась, потому что форма повторно отправляла запрос при медленном ответе. После введения поиска по source_id перед созданием дубли исчезли. Вторая проблема — подпись вебхука: сначала её не проверяли, и в тестовой среде любой мог отправить поддельное событие. Включили секрет и проверку в n8n.

Итог для примера: поток работает, ручной ввод заявок диспетчером заметно сократился, но никаких обещаний по срокам и эффекту я не даю: цифры вымышленные, а у вас всё зависит от качества форм и дисциплины. Что осталось вне интеграции: расчёт цены по маркам бетона и логистика. Их решают внутри ERPNext или отдельным методом, а не потоком n8n.

Что проверить до запуска: нагрузка, очереди и права API-пользователя

Права API-пользователя. Заведите для интеграции отдельного пользователя с минимальным набором ролей, а не используйте администратора. Тогда токен, попав в чужие руки, сможет создавать лиды, но не читать финансы. Права на документы такие же, как у обычного пользователя, и проверяются на каждый запрос. Если запрос отдаёт ошибку доступа, ищите причину в роли, а не в сети.

Нагрузка. Массовая параллельная синхронизация через REST по складским и финансовым документам может вызвать взаимные блокировки (deadlock) в базе: проведение складских и финансовых документов пишет в общие таблицы Stock Ledger Entry и GL Entry и пересчитывает остатки, и параллельные транзакции начинают ждать друг друга. Загрузку номенклатуры и документов пускайте последовательно или небольшими пачками. В n8n для этого есть пакетная отправка: задайте число элементов в пачке и интервал между пачками.

Очереди. Сохранение тяжёлых документов и вебхуки могут уходить в фоновые задачи. Если очередь забита, событие приходит с задержкой. Проверьте в Desk страницу фоновых заданий (RQ Job) и убедитесь, что воркеры работают. Для производственной установки проверка включена в регламент мониторинга.

Ограничения подхода, о которых я прошу помнить. REST API работает на правах пользователя, а не «в обход»: это безопасно, но требует настройки ролей. Документация не называет лимитов частоты запросов, поэтому нагрузочное поведение вы проверяете сами. Секрет API показывается один раз, и при утере его перевыпускают, что обрывает работающие сценарии. И последнее: интеграция — это код, который надо поддерживать; сценарий n8n без владельца ломается тихо.

Перед запуском пройдите короткий чек-лист: токен лежит в учётных данных, а не в тексте сценария; вебхук с секретом; есть поиск по внешнему ключу; пакетная отправка настроена; повторная отправка того же события проверена; журнал вебхуков виден. Если нужна общая картина систем учёта на Linux, смотрите какую систему учёта выбрать и обзор ERPNext для производства.

Частые вопросы

Есть ли в ERPNext REST API и где он находится?

Да. Для каждого DocType Frappe автоматически создаёт CRUD-API по адресу /api/resource/:doctype без написания кода. Для вызова своей бизнес-логики используется /api/method/<путь.к.функции>. Права применяются как для обычного пользователя, поэтому интеграции нужен отдельный пользователь с нужными ролями.

Как подключить n8n к ERPNext?

Через узел HTTP Request: адрес вашей установки, путь /api/resource/<DocType>, метод и JSON-тело. Авторизация — общий тип Header Auth с заголовком Authorization и значением token api_key:api_secret, как указано в документации Frappe. Ключи создаются в карточке пользователя, раздел API Access, кнопка Generate Keys.

Как не создать дубль документа при повторной отправке из внешней системы?

Храните во внешнем ключе пару source_system и source_id в пользовательских полях и перед созданием ищите документ по этому ключу списком с фильтром. Нашли — обновляйте по имени, не нашли — создайте. Проверка: отправьте один и тот же счёт дважды и убедитесь, что запись одна.

Может ли ERPNext сам отправлять данные наружу?

Да, через тип документа Webhook: выбираете событие (например, on_update или on_submit), условие и адрес получателя, формат — форма или JSON с Jinja. Секрет даёт подпись в заголовке X-Frappe-Webhook-Signature, а журнал Webhook Request Log показывает отправленные запросы. При недоступном получателе v15 делает до трёх попыток подряд, потом событие не досылается.

Не положит ли массовая загрузка через API систему?

Параллельные запросы к складским и финансовым документам могут вызвать взаимные блокировки (deadlock) в базе. Загрузку номенклатуры и документов пускайте последовательно или небольшими пачками, в n8n задайте размер пачки и интервал. Дополнительно проверьте фоновые очереди и работу воркеров.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи