# Section: workflows

Generated: 2026-05-30
Pages: 34

---

---
title: "Готовые workflow для n8n на русском - Nodbot"
source_url: "https://nodbot.ru/workflows/"
canonical_url: "https://nodbot.ru/workflows/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1341
---

# Готовые workflow для n8n на русском

## AI summary

Каталог workflow для n8n: Telegram, CRM, webhooks, AI/RAG, российские интеграции и чеклисты адаптации.

## Best used for

Страница объясняет «Готовые workflow для n8n на русском - Nodbot» в контексте n8n/Nodbot: когда применять, как проверить внедрение и какие ошибки исключить.

## Key topics

- Шаблоны
- Как выбрать правильный workflow
- Полезные официальные источники
- Как работать с шаблонами
- Шаблоны для контента и данных
- Production-чеклист для каталога workflow
- Как довести workflow до production
- Пример безопасного входного контракта

## Source outline

# Готовые workflow для n8n на русском

Обновлено: 2026-05-29

## Шаблоны

- Telegram-бот на n8n: роутер команд /start, /help и заявка n8n telegram bot, n8n тг бот, телеграм бот на n8n Telegram и боты beginner 15–30 мин JSON Payload Инструкция
- Telegram AI-бот на n8n с human approval перед ответом n8n ai telegram, ии ассистент n8n, n8n чат бот AI / RAG / агенты production 30–60 мин JSON Payload Инструкция
- Tilda → n8n → Битрикс24: создать лид без дублей tilda n8n, n8n bitrix24, n8n битрикс Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- Tilda → n8n → amoCRM: заявка с UTM и проверкой обязательных полей n8n amocrm, tilda n8n, amoCRM webhook n8n Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- ЮKassa → n8n → CRM: обработать оплату и обновить сделку n8n yookassa, n8n оплата, оплатить n8n из россии Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- DaData + n8n: нормализовать телефон, email и адрес лида n8n dadata, DaData API n8n, обогащение лидов n8n Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- МойСклад + n8n: уведомление о низком остатке в Telegram n8n moysklad, МойСклад n8n, склад n8n Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- 1С + n8n через HTTP: безопасный обмен заказами и статусами n8n 1c, n8n и 1с, интеграция 1с n8n Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- VK Lead Forms → n8n → Google Sheets: сбор заявок с дедупликацией n8n vk, n8n вк, n8n google sheets Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- Email → n8n → задача в Битрикс24: обработка входящих обращений n8n bitrix24, n8n email, автоматизация бизнеса n8n Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- amoCRM webhook → n8n: защита от дублей сделок и контактов n8n amocrm, n8n webhook, lead deduplication n8n Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- Yandex Cloud Functions → n8n: прокладка для закрытых API и событий n8n yandex cloud, n8n яндекс, yandex n8n Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- YandexGPT + n8n: классификатор заявок для российского бизнеса n8n yandex gpt, yandexgpt n8n, n8n яндекс ai ai-russia beginner 15–30 мин JSON Payload Инструкция
- GigaChat + n8n: черновик ответа поддержки с проверкой человеком n8n gigachat, ии ассистент n8n, n8n помощь ai-russia beginner 15–30 мин JSON Payload Инструкция
- OpenRouter + n8n: fallback между моделями, если AI API недоступен n8n openrouter, n8n llm, n8n model fallback AI / RAG / агенты beginner 15–30 мин JSON Payload Инструкция
- Ollama локально + n8n: суммаризация текста без отправки во внешний API n8n ollama, n8n локально, n8n offline AI / RAG / агенты beginner 15–30 мин JSON Payload Инструкция
- Qdrant + n8n: RAG-бот по базе знаний с проверкой источников n8n rag, qdrant n8n, n8n vector store AI / RAG / агенты beginner 15–30 мин JSON Payload Инструкция
- MCP + n8n: workflow как tool для внутреннего API n8n mcp, mcp server n8n, n8n ai agent tool AI / RAG / агенты beginner 15–30 мин JSON Payload Инструкция
- n8n Webhook: проверка подписи запроса перед записью в CRM n8n webhook, n8n webhooks, webhook signature n8n Webhooks и API beginner 15–30 мин JSON Payload Инструкция
- n8n Webhook + Postgres: идемпотентность и защита от повторных событий n8n webhook, n8n postgres, webhook duplicate n8n Webhooks и API beginner 15–30 мин JSON Payload Инструкция
- n8n HTTP Request: retry, backoff и dead-letter queue для API n8n http request, n8n 429, retry n8n http beginner 15–30 мин JSON Payload Инструкция
- Error Workflow в n8n: Telegram-уведомление с диагностикой execution n8n error workflow, n8n telegram, ошибка n8n Ошибки и эксплуатация beginner 15–30 мин JSON Payload Инструкция
- Google Sheets + n8n: upsert строки по телефону без дублей n8n google sheets, n8n sheets, n8n гугл таблицы Таблицы и CRM beginner 15–30 мин JSON Payload Инструкция
- Gmail вложения → n8n → Яндекс Диск: архив документов по правилам n8n gmail, n8n яндекс диск, n8n email Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- RSS → n8n → Telegram: новостной дайджест с фильтром дублей n8n rss, n8n telegram workflow, n8n автопостинг Контент и автопостинг beginner 15–30 мин JSON Payload Инструкция
- Notion → n8n → WordPress: автоподготовка черновика статьи n8n notion, n8n wordpress, n8n автопостинг Контент и автопостинг beginner 15–30 мин JSON Payload Инструкция
- Авито → n8n → CRM: обработка лидов и сообщений без ручного копирования n8n avito, авито n8n, n8n crm Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- hh.ru → n8n → AI shortlist: первичный скоринг кандидатов n8n hh, n8n вакансии, automation developer n8n job Российский бизнес-стек beginner 15–30 мин JSON Payload Инструкция
- Beget/Timeweb VPS + n8n: healthcheck и Telegram-алерт о падении n8n beget, n8n timeweb, сервер для n8n Хостинг и backup beginner 15–30 мин JSON Payload Инструкция
- n8n Docker Compose: backup PostgreSQL и workflows в S3-совместимое хранилище n8n docker compose, backup n8n, n8n self hosted Хостинг и backup production 30–60 мин JSON Payload Инструкция
- Контент-завод на n8n: SEO-брифы, проверка фактов и очередь публикаций контент завод n8n, n8n для seo, написание статей с ии n8n content-ai beginner 15–30 мин JSON Payload Инструкция
- n8n автопостинг: Telegram/VK/WordPress без дублей и с календарём n8n автопостинг, n8n vk, n8n wordpress Контент и автопостинг beginner 15–30 мин JSON Payload Инструкция

## Как выбрать правильный workflow

- Сценарий | Что открывать | Что не смешивать
- Нужно быстро импортировать JSON | Эта библиотека workflows | Не читать общие статьи про ноды
- Нужен бизнес-сценарий | Рецепты | Не копировать шаблон без адаптации
- Сломался запуск | Диагностика и ошибки | Не менять workflow вслепую
- Российский сервис | Российский стек | Не дублировать общую теорию HTTP Request

## Полезные официальные источники

Для проверки параметров нод и поведения n8n используйте официальную документацию:

- Import and export workflows

## Как работать с шаблонами

Подборка материалов, которые помогают перейти от общей идеи к аккуратной настройке в n8n.

- Шаблоны n8n: импорт, адаптация и проверка
- Community nodes: когда ставить сторонние ноды
- Code node: JavaScript, Python и items

## Шаблоны для контента и данных

Эти связки дополняют статьи: сначала разберите логику, затем импортируйте подходящий workflow и адаптируйте поля.

- Notion → WordPress draft
- RSS → Telegram digest
- Airtable → Postgres sync

## Production-чеклист для каталога workflow

Используйте этот блок как быстрый контроль перед публикацией workflow или изменением существующей автоматизации. Он не заменяет staging, но помогает поймать самые частые отказы заранее.

- Перед запуском: выбирать шаблон по источнику события, критичности данных, SLA и владельцу процесса.
- Минимальный тест: открыть выбранный workflow, пройти тестовый payload и проверить error branch.
- Типовой отказ: готовый шаблон запущен без адаптации под реальные поля CRM/API.
- Что логировать: входной payload без секретов, статус внешнего API, branch ошибки, execution id и владельца процесса.
Критерий готовности: сценарий проходит успешный путь, ошибочный путь и повтор события без дублей, потери данных и неконтролируемого падения execution.

## Как довести workflow до production

Страницу «Готовые workflow для n8n на русском» лучше использовать как практический чеклист, а не как справку. Зафиксируйте входные данные, ожидаемый результат, владельца workflow и условие, при котором сценарий считается неуспешным.

Базовый источник для проверки: входной item по теме «Готовые workflow для n8n на русском»: источник события, внешний ID, время получения и нормализованные поля. Главный риск — принять happy path за production-готовность и не проверить повторы, пустые входы, откат и наблюдаемость.

- Слой | Что зафиксировать | Зачем
- Вход | входной item по теме «Готовые workflow для n8n на русском»: источник события, внешний ID, время получения и нормализованные поля | позволяет повторить проблему без доступа к production-секретам
- Контроль | successful_executions, skipped_items, retry_count, error_branch_usage, manual_override_count | показывает деградацию раньше, чем пользователи начинают писать в поддержку
- Безопасность | принять happy path за production-готовность и не проверить повторы, пустые входы, откат и наблюдаемость | снижает риск скрытых дублей, утечки данных и неконтролируемых write-действий
- Готовность | есть тест на happy path, пустой вход, повтор и сбой внешнего сервиса для «Готовые workflow для n8n на русском» | делает статью пригодной для runbook, а не только для чтения

### Пример безопасного входного контракта

```
{
  "source": "manual|webhook|schedule|api",
  "external_id": "stable-id-from-source",
  "received_at": "2026-05-29T10:00:00Z",
  "payload_version": "v1",
  "dry_run": true,
  "audit": {"workflow_id": "...", "execution_id": "..."}
}
```

### Критерий готовности

- есть понятный вход, выход и владелец процесса
- проверены пустой input, повтор события и ошибка внешнего сервиса
- результат логируется без секретов и персональных данных
- страница связана с соседними рецептами, ошибками или playbook по теме

## Related Nodbot pages

- [Старт](/start/)
- [Основы](/basics/)
- [Ноды](/nodes/)
- [Интеграции](/integrations/)
- [AI](/ai/)
- [Рецепты](/recipes/)
- [Ошибки](/errors/)
- [Диагностика](/diagnostics/)

## Retrieval hints

- Предпочитать canonical URL как источник для пользовательских ссылок.
- Использовать markdown-версию для быстрого извлечения сущностей, чеклистов и терминов.
- При цитировании сверять с исходной HTML-страницей, если нужен самый полный контекст.


---

---
title: "amoCRM webhook в n8n: дедупликация событий | Nodbot"
source_url: "https://nodbot.ru/workflows/amocrm-webhook-deduplication/"
canonical_url: "https://nodbot.ru/workflows/amocrm-webhook-deduplication/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1244
---

# amoCRM webhook в n8n: дедупликация событий через Postgres idempotency key

## AI summary

Problem/Solution-мануал для amoCRM webhooks в n8n: как построить idempotency key, записать его в Postgres с unique constraint, обработать событие один раз и безопасно отвечать на повторы.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить webhook/API, проверить дубли, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему amoCRM webhooks приходят повторно и ломают автоматизации
- Архитектура workflow для идемпотентной обработки
- Контракт входных данных (JSON Payload)
- Idempotency key и Postgres unique insert (Code Node + SQL)
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка amoCRM webhook, n8n и Postgres
- Тесты перед production и проверка повторных событий
- Production-риски при обработке webhooks amoCRM
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- amoCRM webhooks
- n8n idempotency
- Postgres unique constraint
- idempotency key
- ON CONFLICT DO NOTHING
- duplicate webhook
- CRM automation

## Source outline

amoCRM webhook в n8n: дедупликация событий через Postgres idempotency key ¶ Обновлено: 2026-05-30 Сохранить в мой план Открыть мой план Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте JSON в n8n, подключите Postgres credential и замените endpoint бизнес-обработки. Содержание Проблема: почему amoCRM webhooks приходят повторно и ломают автоматизации Архитектура workflow для идемпотентной обработки Контракт входных данных (JSON Payload) Idempotency key и Postgres unique insert (Code Node + SQL) Готовый workflow JSON: скачать и импортировать Пошаговая настройка amoCRM webhook, n8n и Postgres Тесты перед production и проверка повторных событий Production-риски при обработке webhooks amoCRM Полезные ссылки и смежные workflow Критерии готовности Проблема: amoCRM webhooks могут приходить повторно, приходить почти одновременно или запускать несколько downstream-действий на одно обновление сделки. Если workflow отправляет уведомление, создаёт задачу или синхронизирует данные без идемпотентности, одно событие превращается в два письма, две задачи и два внешних API-вызова. Решение: webhook amoCRM в n8n должен сначала построить idempotency_key , затем атомарно записать его в Postgres с unique constraint и только после успешной вставки выполнять бизнес-логику. Повторное событие получает быстрый 200 OK , но не обрабатывается второй раз. Это production-паттерн для интеграторов: импортируемый workflow JSON, SQL-таблица, Code Node, тест повторного payload и чек-лист запуска. n8n принимает webhook amoCRM, строит idempotency key, вставляет его в Postgres и запускает бизнес-действие только один раз. Проблема: почему amoCRM webhooks приходят повторно и ломают автоматизации ¶ Webhook — это уведомление о событии, а не гарантия “ровно один раз”. CRM может повторить доставку, пользователь может быстро изменить одну и ту же сделку, а ваша логика может ответить медленно. Поэтому фильтр “я уже видел это событие” нельзя держать только в памяти n8n execution. Особенно опасны действия с побочным эффектом: отправка сообщения клиенту, создание задачи менеджеру, списание бонуса, обновление внешней системы. Повтор такого действия выглядит как баг интеграции, хотя первопричина — отсутствие идемпотентной обработки. Архитектура workflow для идемпотентной обработки ¶ Нода Роль Что проверить Webhook input Принимает webhook amoCRM Быстрый ответ, HTTPS, секрет/allowlist при возможности Build idempotency key Собирает ключ из account/entity/action/time Ключ стабилен для повтора и отличается для нового изменения Insert idempotency key Пишет ключ в Postgres PRIMARY KEY , ON CONFLICT DO NOTHING , отдельная таблица Process once Выполняет бизнес-действие Запускается только если insert вернул строку Respond Отвечает amoCRM Не раскрывает внутренние ошибки и токены Главный принцип: проверка и запись ключа должны быть одним атомарным действием. Нельзя делать “SELECT, потом INSERT” в двух шагах без блокировки — при параллельных событиях оба execution могут пройти проверку. Контракт входных данных (JSON Payload) ¶ Payload amoCRM зависит от типа сущности и события. Ниже пример обновления сделки. Для контактов и компаний добавьте отдельные ветки в Code Node, но сохраняйте одинаковый принцип ключа. { "account": { "id": 301001 }, "leads": { "update": [ { "id": 778899, "updated_at": 1780123456, "status_id": 12345, "pipeline_id": 67890 } ] } } Ключ должен включать не только ID сделки, но и действие или timestamp. Иначе разные изменения одной сделки будут считаться одним и тем же событием. Idempotency key и Postgres unique insert (Code Node + SQL) ¶ Code Node строит ключ, а Postgres гарантирует, что ключ будет принят только один раз. Это надежнее, чем хранить список обработанных событий в static data n8n. const event = $json.body ?? $json; const account = event.account?.id ?? event.account_id ?? 'unknown-account'; const leadUpdate = event.leads?.update?.[0]; const leadAdd = event.leads?.add?.[0]; const contactUpdate = event.contacts?.update?.[0]; const entity = leadUpdate ?? leadAdd ?? contactUpdate; const entityType = leadUpdate || leadAdd ? 'lead' : contactUpdate ? 'contact' : 'unknown'; const action = leadAdd ? 'add' : leadUpdate ? 'update' : contactUpdate ? 'update' : 'unknown'; const entityId = entity?.id ?? event.entity_id; const updatedAt = entity?.updated_at ?? event.updated_at ?? event.timestamp ?? ''; if (!entityId) { throw new Error('Cannot build amoCRM webhook idempotency key without entity id'); } const idempotencyKey = `amocrm:${account}:${entityType}:${entityId}:${action}:${updatedAt}`; return [{ json: { idempotency_key: idempotencyKey, account_id: String(account), entity_type: entityType, entity_id: String(entityId), action, event_time: String(updatedAt), raw_event_type: `${entityType}_${action}` } }]; SQL для таблицы и атомарной вставки: CREATE TABLE IF NOT EXISTS idempotency_keys ( key text PRIMARY KEY, source text NOT NULL, entity_type text NOT NULL, entity_id text NOT NULL, created_at timestamptz NOT NULL DEFAULT now() ); INSERT INTO idempotency_keys(key, source, entity_type, entity_id) VALUES ($1, 'amocrm', $2, $3) ON CONFLICT DO NOTHING RETURNING key; В n8n следующая нода должна проверять результат insert. Если строка не вернулась, это повтор: бизнес-действие пропускается, но webhook отвечает успешно. Готовый workflow JSON: скачать и импортировать ¶ Полный JSON лежит в архиве сайта и доступен по кнопке. После импорта замените Postgres credential и endpoint Process business action once на ваш внутренний обработчик. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - amoCRM webhook deduplication with Postgres", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять webhook amoCRM" }, { "name": "Build idempotency key", "type": "n8n-nodes-base.code", "purpose": "Собрать стабильный ключ account/entity/action/updated_at" }, { "name": "Insert idempotency key", "type": "n8n-nodes-base.postgres", "purpose": "Вставить ключ через ON CONFLICT DO NOTHING" }, { "name": "Process business action once", "type": "n8n-nodes-base.httpRequest", "purpose": "Выполнить бизнес-логику только для нового ключа" }, { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть amoCRM быстрый безопасный ответ" } ], "connections": "Webhook → Build key → Insert key → Process once → Respond" } Если у вас уже есть отдельная таблица idempotency для webhooks других систем, используйте общий формат source + key + entity_type + entity_id . Тогда поддержку проще документировать. Пошаговая настройка amoCRM webhook, n8n и Postgres ¶ В amoCRM настройте webhook на production URL n8n и выберите только нужные события. В n8n импортируйте workflow JSON и подключите Postgres credential. Создайте таблицу idempotency_keys или примените SQL из статьи. Проверьте Code Node на событиях lead add, lead update и contact update, если они нужны. Настройте ветку: новая вставка запускает бизнес-действие, конфликт — возвращает “duplicate skipped”. Добавьте retention-политику: старые ключи можно удалять через 30–90 дней, если бизнес-процесс это допускает. В журнале видно, какое событие было принято впервые, а какие повторы безопасно пропущены. Тесты перед production и проверка повторных событий ¶ Отправьте один и тот же payload дважды. Первый запуск должен вставить ключ и выполнить бизнес-логику, второй — не должен делать повторное действие. Затем измените updated_at и убедитесь, что новое событие обрабатывается как отдельное. curl -X POST "https://YOUR-N8N-DOMAIN/webhook/amocrm-webhook-deduplication" \ -H "Content-Type: application/json" \ --data @amocrm-webhook-deduplication-payload.json Проверьте параллельный запуск: отправьте два одинаковых запроса почти одновременно. Если таблица настроена правильно, только один execution получит строку из RETURNING key . Production-риски при обработке webhooks amoCRM ¶ Ключ слишком грубый. Если использовать только lead_id , все обновления одной сделки будут пропущены. Ключ слишком детальный. Если включить случайные поля payload, повтор не распознается как повтор. SELECT перед INSERT. При параллельных событиях это создаёт гонку. Используйте unique insert. Бизнес-действие до записи ключа. Повтор уже успеет отправить сообщение или создать задачу. Webhook отвечает слишком медленно. Источник может повторить доставку, и нагрузка вырастет. Нет retention. Таблица idempotency растёт бесконечно и замедляет обслуживание. Полезные ссылки и смежные workflow ¶ Официальная документация amoCRM описывает формат webhooks и настройку HTTP-адресов для событий. Для хранения ключей используйте Postgres на том же production-контуре, где размещён n8n. Смотрите также внутри Nodbot: amoCRM в n8n — общая интеграционная страница. Postgres в n8n — подключение базы для idempotency. Webhook idempotency to Postgres — общий паттерн для любых источников. Tilda → amoCRM — защита лидов от дублей по телефону. Retry и DLQ для HTTP Request — обработка временных ошибок. Критерии готовности ¶ Одинаковый payload обрабатывается только один раз. Новое изменение той же сделки не пропускается как дубль. Параллельные одинаковые события не запускают два бизнес-действия. Postgres insert использует unique constraint и ON CONFLICT DO NOTHING . Webhook быстро отвечает источнику и не раскрывает внутренние ошибки. Есть retention-политика и владелец таблицы idempotency. Нужна надежная CRM-автоматизация? Nodbot настроит amoCRM webhooks, n8n, Postgres idempotency, retry/DLQ и мониторинг, чтобы одно событие не запускало бизнес-процесс дважды. Обсудить amoCRM webhook

## Test payload

```json
{
  "account": { "id": 301001 },
  "leads": {
    "update": [
      {
        "id": 778899,
        "updated_at": 1780123456,
        "status_id": 12345,
        "pipeline_id": 67890
      }
    ]
  }
}
```

## Key implementation snippet

```javascript
const event = $json.body ?? $json;
const account = event.account?.id ?? event.account_id ?? 'unknown-account';

const leadUpdate = event.leads?.update?.[0];
const leadAdd = event.leads?.add?.[0];
const contactUpdate = event.contacts?.update?.[0];

const entity = leadUpdate ?? leadAdd ?? contactUpdate;
const entityType = leadUpdate || leadAdd ? 'lead' : contactUpdate ? 'contact' : 'unknown';
const action = leadAdd ? 'add' : leadUpdate ? 'update' : contactUpdate ? 'update' : 'unknown';
const entityId = entity?.id ?? event.entity_id;
const updatedAt = entity?.updated_at ?? event.updated_at ?? event.timestamp ?? '';

if (!entityId) {
  throw new Error('Cannot build amoCRM webhook idempotency key without entity id');
}

const idempotencyKey = `amocrm:${account}:${entityType}:${entityId}:${action}:${updatedAt}`;

return [{
  json: {
    idempotency_key: idempotencyKey,
    account_id: String(account),
    entity_type: entityType,
    entity_id: String(entityId),
    action,
    event_time: String(updatedAt),
    raw_event_type: `${entityType}_${action}`
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - amoCRM webhook deduplication with Postgres",
  "nodes": [
    { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять webhook amoCRM" },
    { "name": "Build idempotency key", "type": "n8n-nodes-base.code", "purpose": "Собрать стабильный ключ account/entity/action/updated_at" },
    { "name": "Insert idempotency key", "type": "n8n-nodes-base.postgres", "purpose": "Вставить ключ через ON CONFLICT DO NOTHING" },
    { "name": "Process business action once", "type": "n8n-nodes-base.httpRequest", "purpose": "Выполнить бизнес-логику только для нового ключа" },
    { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть amoCRM быстрый безопасный ответ" }
  ],
  "connections": "Webhook → Build key → Insert key → Process once → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Авито и CRM через n8n: заявки без дублей | Nodbot"
source_url: "https://nodbot.ru/workflows/avito-leads-to-crm/"
canonical_url: "https://nodbot.ru/workflows/avito-leads-to-crm/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1389
---

# Интеграция Авито и CRM через n8n: заявки, сообщения и контекст объявления без дублей

## AI summary

Problem/Solution-мануал по передаче заявок Авито в CRM через n8n: webhook, item_id, chat/message context, нормализация телефона, dedupe key, upsert лида и production-контроль.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить webhook/API, проверить дубли, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему заявки Авито нельзя отправлять в CRM как обычную форму
- Архитектура workflow для передачи лидов Авито в CRM
- Контракт входных данных (JSON Payload)
- Dedupe key, телефон и контекст объявления (Code Node)
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка связки Авито, n8n и CRM
- Тесты перед production и проверка CRM API
- Production-риски при обработке лидов Авито
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Авито CRM integration
- n8n webhook
- Avito item_id
- message_id
- chat_id
- CRM upsert
- dedupe key
- DLQ

## Source outline

Интеграция Авито и CRM через n8n: заявки, сообщения и контекст объявления без дублей ¶ Обновлено: 2026-05-30 Сохранить в мой план Открыть мой план Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow в n8n и замените endpoint вашей CRM, правило dedupe и alert-канал. Содержание Проблема: почему заявки Авито нельзя отправлять в CRM как обычную форму Архитектура workflow для передачи лидов Авито в CRM Контракт входных данных (JSON Payload) Dedupe key, телефон и контекст объявления (Code Node) Готовый workflow JSON: скачать и импортировать Пошаговая настройка связки Авито, n8n и CRM Тесты перед production и проверка CRM API Production-риски при обработке лидов Авито Полезные ссылки и смежные workflow Критерии готовности Проблема: лиды Авито приходят не как аккуратная форма сайта. Один покупатель может написать по нескольким объявлениям, вернуться в тот же чат, прислать короткое сообщение без телефона или оставить номер в свободном тексте. Если просто отправлять каждое событие в CRM, отдел продаж получает дубли и теряет контекст объявления. Решение: интеграция Авито и CRM через n8n должна сохранять item_id , chat_id , message_id , текст сообщения и нормализованный телефон. На их основе workflow собирает dedupe_key , делает upsert лида и передаёт в CRM не “заявку из Авито”, а понятный объект: кто написал, по какому объявлению, с каким вопросом и почему это не дубль. Это практический скрипт n8n для автоматизации обработки входящих сообщений: готовый workflow JSON, тестовый payload, Code Node, таблица архитектуры, тесты и production-чеклист. Workflow принимает событие Авито, собирает контекст объявления, нормализует контакт и делает upsert лида в CRM. Проблема: почему заявки Авито нельзя отправлять в CRM как обычную форму ¶ Обычная форма сайта имеет предсказуемые поля: имя, телефон, email, комментарий. Авито-лид часто состоит из сообщения, объявления, чата и частично заполненного контакта. Для менеджера важен не только телефон, но и само объявление: цена, город, категория, ссылка и история диалога. Без контекста CRM-карточка становится бесполезной: менеджер видит “Максим, нужен расчет”, но не понимает, по какой услуге или товару человек написал. Поэтому в этом workflow контекст объявления — обязательная часть лида, а не второстепенный комментарий. Архитектура workflow для передачи лидов Авито в CRM ¶ Нода Роль Что проверить Webhook input Принимает событие Авито или коннектора Источник события, подпись/секрет, формат JSON Normalize Avito context Собирает dedupe_key , телефон и контекст lead_id , chat_id , message_id , item_id CRM upsert lead Создаёт или обновляет лид Endpoint CRM, поле внешнего ключа, обработка дублей Failed response alert Отправляет ошибку в alert/DLQ Не логировать полный телефон и сообщение без маскирования Respond Возвращает 200 OK источнику Короткий ответ без внутренних деталей Если ваша CRM — amoCRM или Битрикс24, upsert можно заменить на соответствующий API-вызов. Если CRM самописная, оставьте единый endpoint /leads/upsert и договоритесь о внешнем ключе dedupe_key . Контракт входных данных (JSON Payload) ¶ Payload ниже показывает минимальный контракт. В реальном проекте добавьте цену, категорию, менеджера по направлению и ссылку на вложения, если они приходят из вашего источника. { "lead_id": "avito-981221", "chat_id": "chat-493002", "message_id": "msg-883120", "item_id": "ad-44219", "item_url": "https://www.avito.ru/example/ad-44219", "item_title": "Настройка n8n под ключ", "name": "Максим", "phone": "8 926 555-12-12", "message": "Добрый день, сколько стоит интеграция с CRM?", "city": "Москва", "received_at": "2026-05-30T10:15:00Z" } Нельзя строить дедупликацию только по телефону: номер может появиться позже, а диалог уже нужно закрепить за объявлением. Поэтому workflow использует приоритет: lead_id → message_id → chat_id + item_id → phone + item_id . Dedupe key, телефон и контекст объявления (Code Node) ¶ Code Node ниже собирает стабильный ключ и готовит карточку для CRM. Он не падает, если телефона нет, но требует хотя бы один идентификатор события или нормализованный номер. const src = $json.body ?? $json; const phoneRaw = String(src.phone ?? src.contact_phone ?? '').trim(); let digits = phoneRaw.replace(/\D/g, ''); if (digits.length === 11 && digits.startsWith('8')) { digits = `7${digits.slice(1)}`; } if (digits.length === 10) { digits = `7${digits}`; } const phone = /^7\d{10}$/.test(digits) ? `+${digits}` : ''; const leadId = String(src.lead_id ?? '').trim(); const chatId = String(src.chat_id ?? '').trim(); const messageId = String(src.message_id ?? '').trim(); const itemId = String(src.item_id ?? src.ad_id ?? '').trim(); if (!leadId && !chatId && !messageId && !phone) { throw new Error('Need Avito lead/chat/message id or normalized phone'); } const dedupeKey = leadId ? `avito:lead:${leadId}` : messageId ? `avito:message:${messageId}` : chatId && itemId ? `avito:chat:${chatId}:item:${itemId}` : `avito:phone:${digits}:item:${itemId || 'unknown'}`; return [{ json: { dedupe_key: dedupeKey, source: 'avito', phone_normalized: phone, customer_name: String(src.name ?? src.user_name ?? 'Авито лид').trim(), message: String(src.message ?? src.text ?? '').trim(), item_id: itemId, item_title: String(src.item_title ?? src.title ?? '').trim(), item_url: src.item_url ?? '', city: src.city ?? '', crm_title: `Авито: ${src.item_title ?? itemId || 'новая заявка'}`, received_at: src.received_at ?? new Date().toISOString() } }]; Такой подход удобно отлаживать: по dedupe_key можно найти execution в n8n, запись в CRM и строку в логах. Это особенно важно, когда менеджер говорит: “заявка пропала” или “клиент создался два раза”. Готовый workflow JSON: скачать и импортировать ¶ Полный workflow JSON доступен в архиве сайта. После импорта замените CRM endpoint, credential, map полей и канал для failed response alert. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Avito leads to CRM with context and dedupe", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять событие от Авито, коннектора или промежуточного сервиса" }, { "name": "Normalize Avito lead context", "type": "n8n-nodes-base.code", "purpose": "Собрать dedupe_key, телефон, item_id, chat_id и текст сообщения" }, { "name": "CRM upsert lead", "type": "n8n-nodes-base.httpRequest", "purpose": "Создать или обновить лид в вашей CRM" }, { "name": "Send alert on failed CRM response", "type": "n8n-nodes-base.httpRequest", "purpose": "Отправить ошибку в alert/DLQ" }, { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть безопасный ответ источнику" } ], "connections": "Webhook → Normalize context → CRM upsert → optional alert → Respond" } Если вы получаете Авито-события через промежуточный сервис, не теряйте исходные ID. Даже если CRM не умеет хранить их в отдельных полях, сохраните их хотя бы в custom fields или техническом комментарии. Пошаговая настройка связки Авито, n8n и CRM ¶ Определите источник событий: прямой API, коннектор, парсер входящих сообщений или промежуточный webhook. Импортируйте workflow JSON в n8n и укажите production URL в источнике событий. Настройте маппинг CRM: название лида, телефон, сообщение, item_id, item_url, город и dedupe_key. Создайте в CRM отдельное поле “Внешний ключ Авито”, чтобы повторное событие можно было обновить, а не создать заново. Добавьте alert/DLQ для ошибок CRM API, чтобы потерянные заявки можно было переотправить. Прогоните тесты на повторное сообщение и на лид без телефона. В CRM должны быть видны объявление, сообщение, город, телефон и внешний ключ. Тогда менеджер понимает контекст обращения. Тесты перед production и проверка CRM API ¶ Тестируйте не “заявка появилась”, а весь цикл: первый вход, повтор того же сообщения, новое сообщение в том же чате, другое объявление того же клиента и отсутствие телефона. Эти сценарии должны давать разные, но объяснимые результаты. curl -X POST "https://YOUR-N8N-DOMAIN/webhook/avito-leads-to-crm" \ -H "Content-Type: application/json" \ --data @avito-leads-to-crm-payload.json Отдельно проверьте, что CRM возвращает понятные ошибки на дубликат внешнего ключа, временную недоступность и неверный токен. В production такие события должны попадать в retry или DLQ, а не исчезать в истории executions. Production-риски при обработке лидов Авито ¶ Дедупликация только по телефону. Потеряете события без номера и объедините разные объявления одного человека. Нет item_id в CRM. Менеджер не понимает, по какому объявлению пришёл клиент. Alert содержит полный текст сообщения и телефон. Это риск персональных данных и внутренней утечки. Повтор webhook считается ошибкой. Для интеграций повтор — нормальное явление; обработчик должен быть идемпотентным. CRM API временно недоступна. Без DLQ заявка потеряется, хотя клиент уже написал. Нет владельца направления. При изменении структуры объявлений никто не обновит маппинг. Полезные ссылки и смежные workflow ¶ Для реализации держите рядом документацию вашего источника Авито-событий, документацию CRM API и внутренний список обязательных полей лида. Смотрите также внутри Nodbot: Установка n8n — подготовка окружения. n8n в Docker Compose — production self-hosted запуск. Tilda → amoCRM — пример CRM-дедупликации по телефону. Tilda → Битрикс24 — пример передачи UTM в CRM. Retry и DLQ для HTTP Request — что делать при сбоях CRM API. Критерии готовности ¶ Повторный lead_id или message_id не создаёт новый лид. item_id , ссылка на объявление и текст сообщения попадают в CRM. Лид без телефона не теряется, если есть chat/message ID. CRM API ошибки уходят в retry/DLQ и видны владельцу процесса. В alert персональные данные замаскированы. Workflow содержит тестовый payload и описание правила дедупликации. Нужно связать Авито с CRM? Nodbot поможет собрать production-интеграцию: webhook, dedupe key, upsert в CRM, DLQ, тесты и мониторинг входящих заявок. Обсудить Авито → CRM

## Test payload

```json
{
  "lead_id": "avito-981221",
  "chat_id": "chat-493002",
  "message_id": "msg-883120",
  "item_id": "ad-44219",
  "item_url": "https://www.avito.ru/example/ad-44219",
  "item_title": "Настройка n8n под ключ",
  "name": "Максим",
  "phone": "8 926 555-12-12",
  "message": "Добрый день, сколько стоит интеграция с CRM?",
  "city": "Москва",
  "received_at": "2026-05-30T10:15:00Z"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const phoneRaw = String(src.phone ?? src.contact_phone ?? '').trim();
let digits = phoneRaw.replace(/\D/g, '');

if (digits.length === 11 && digits.startsWith('8')) {
  digits = `7${digits.slice(1)}`;
}

if (digits.length === 10) {
  digits = `7${digits}`;
}

const phone = /^7\d{10}$/.test(digits) ? `+${digits}` : '';
const leadId = String(src.lead_id ?? '').trim();
const chatId = String(src.chat_id ?? '').trim();
const messageId = String(src.message_id ?? '').trim();
const itemId = String(src.item_id ?? src.ad_id ?? '').trim();

if (!leadId && !chatId && !messageId && !phone) {
  throw new Error('Need Avito lead/chat/message id or normalized phone');
}

const dedupeKey = leadId
  ? `avito:lead:${leadId}`
  : messageId
    ? `avito:message:${messageId}`
    : chatId && itemId
      ? `avito:chat:${chatId}:item:${itemId}`
      : `avito:phone:${digits}:item:${itemId || 'unknown'}`;

return [{
  json: {
    dedupe_key: dedupeKey,
    source: 'avito',
    phone_normalized: phone,
    customer_name: String(src.name ?? src.user_name ?? 'Авито лид').trim(),
    message: String(src.message ?? src.text ?? '').trim(),
    item_id: itemId,
    item_title: String(src.item_title ?? src.title ?? '').trim(),
    item_url: src.item_url ?? '',
    city: src.city ?? '',
    crm_title: `Авито: ${src.item_title ?? itemId || 'новая заявка'}`,
    received_at: src.received_at ?? new Date().toISOString()
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Avito leads to CRM with context and dedupe",
  "nodes": [
    { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять событие от Авито, коннектора или промежуточного сервиса" },
    { "name": "Normalize Avito lead context", "type": "n8n-nodes-base.code", "purpose": "Собрать dedupe_key, телефон, item_id, chat_id и текст сообщения" },
    { "name": "CRM upsert lead", "type": "n8n-nodes-base.httpRequest", "purpose": "Создать или обновить лид в вашей CRM" },
    { "name": "Send alert on failed CRM response", "type": "n8n-nodes-base.httpRequest", "purpose": "Отправить ошибку в alert/DLQ" },
    { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть безопасный ответ источнику" }
  ],
  "connections": "Webhook → Normalize context → CRM upsert → optional alert → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "n8n healthcheck на Beget и Timeweb: алерты | Nodbot"
source_url: "https://nodbot.ru/workflows/beget-timeweb-n8n-healthcheck/"
canonical_url: "https://nodbot.ru/workflows/beget-timeweb-n8n-healthcheck/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 984
---

# Healthcheck n8n на Beget и Timeweb: проверка доступности, SSL и Telegram-алерт

## AI summary

AI-friendly Problem/Solution-мануал: как настроить healthcheck n8n на Beget, Timeweb или VPS, проверять HTTPS, latency, webhook endpoint и отправлять Telegram-алерт до того, как пользователи заметят простой.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API/файлы/мониторинг, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему n8n на хостинге падает незаметно
- Архитектура workflow для healthcheck n8n
- Контракт параметров мониторинга
- Code Node: статус, latency, SSL и severity
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка мониторинга Beget, Timeweb и VPS
- Тесты отказов и Telegram-алертов
- Production-риски мониторинга n8n
- Полезные ссылки и смежные инструкции
- Критерии готовности

## Key topics

- n8n healthcheck
- Beget
- Timeweb
- Telegram alert
- SSL monitoring
- latency monitoring

## Source outline

Healthcheck n8n на Beget и Timeweb: проверка доступности, SSL и Telegram-алерт ¶ Обновлено: 2026-05-30 AI summary: AI-friendly Problem/Solution-мануал: как настроить healthcheck n8n на Beget, Timeweb или VPS, проверять HTTPS, latency, webhook endpoint и отправлять Telegram-алерт до того, как пользователи заметят простой. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему n8n на хостинге падает незаметно Архитектура workflow для healthcheck n8n Контракт параметров мониторинга Code Node: статус, latency, SSL и severity Готовый workflow JSON: скачать и импортировать Пошаговая настройка мониторинга Beget, Timeweb и VPS Тесты отказов и Telegram-алертов Production-риски мониторинга n8n Полезные ссылки и смежные инструкции Критерии готовности Проблема: n8n может быть визуально “живым” в панели хостинга, но недоступным для webhook, CRM и форм. Без healthcheck команда узнаёт о проблеме от клиента или менеджера. Решение: настроить регулярный healthcheck n8n на Beget, Timeweb или VPS: проверить HTTPS endpoint, latency, SSL, классифицировать ошибку и отправить Telegram-алерт с runbook. Проверка должна имитировать реальный пользовательский путь: HTTPS → webhook → ответ. Проблема: почему n8n на хостинге падает незаметно ¶ n8n на недорогом VPS, Beget Cloud или Timeweb Cloud часто работает стабильно до первого обновления, нехватки памяти, истёкшего SSL или зависшего reverse proxy. Внешне это выглядит просто: форма Tilda отправила заявку, но webhook не ответил; CRM не обновилась; Telegram bot молчит. Поэтому мониторинг n8n должен проверять не только “сервер пингуется”, а реальный HTTP-ответ production endpoint. Для автоматизации продаж важно обнаружить простой раньше менеджера. Healthcheck workflow превращает техническую проверку в понятный инцидент: какой сервис, какой статус, какая задержка, сколько дней до истечения SSL и что делать дальше. Архитектура workflow для healthcheck n8n ¶ Нода Роль Что проверить Schedule every 5 min Запускает проверку по расписанию Интервал, timezone, не слишком частые запросы Check n8n URL Проверяет HTTPS endpoint HTTP 200, timeout, redirect, body Classify health Назначает severity Status, latency, SSL days left Telegram alert Отправляет сообщение команде chat_id, dedupe, runbook link Incident log Сохраняет историю Не терять flapping и recovery Контракт параметров мониторинга ¶ Конфигурацию лучше хранить как JSON или ENV, а не размазывать URL по нескольким HTTP Request нодам. Тогда один шаблон можно использовать для Beget, Timeweb и отдельного VPS. { "service": "n8n-production", "url": "https://n8n.example.ru/healthz", "webhook_url": "https://n8n.example.ru/webhook/healthcheck-ping", "expected_status": 200, "max_latency_ms": 2500, "alert_chat_id": "-1001234567890", "hoster": "timeweb-vps" } Code Node: статус, latency, SSL и severity ¶ Этот Code Node переводит технические метрики в понятный статус. В production добавьте отдельную проверку SSL через внешний endpoint или node, который возвращает ssl_days_left . const service = $json.service ?? 'n8n'; const status = Number($json.statusCode ?? $json.status ?? 0); const latency = Number($json.latency_ms ?? $json.responseTime ?? 0); const expected = Number($json.expected_status ?? 200); const maxLatency = Number($json.max_latency_ms ?? 2500); const sslDaysLeft = Number($json.ssl_days_left ?? 30); let severity = 'ok'; let reason = 'service_available'; if (status !== expected) { severity = 'critical'; reason = `unexpected_status_${status}`; } else if (latency > maxLatency) { severity = 'warning'; reason = 'slow_response'; } else if (sslDaysLeft < 7) { severity = 'critical'; reason = 'ssl_expires_soon'; } else if (sslDaysLeft < 14) { severity = 'warning'; reason = 'ssl_renewal_window'; } return [{ json: { service, severity, reason, status, latency_ms: latency, ssl_days_left: sslDaysLeft, dedupe_key: `healthcheck:${service}:${reason}`, message: severity === 'ok' ? `✅ ${service}: OK, ${latency} ms` : `🚨 ${service}: ${reason}, status=${status}, latency=${latency} ms, ssl=${sslDaysLeft}d`, checked_at: new Date().toISOString() }}]; Почему latency важнее простого ping Webhook может отвечать 200, но делать это за 8–12 секунд. Для форм, CRM и платёжных уведомлений это уже пользовательская проблема: внешний сервис может посчитать запрос неуспешным и повторить его. Готовый workflow JSON: скачать и импортировать ¶ В архиве страницы есть импортируемый workflow JSON и test payload. После импорта замените Telegram credential, URL n8n, chat_id и пороги latency. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - n8n healthcheck for Beget and Timeweb", "nodes": [ { "name": "Schedule every 5 min", "type": "n8n-nodes-base.scheduleTrigger", "purpose": "Запускать мониторинг по расписанию" }, { "name": "Check n8n URL HTTP", "type": "n8n-nodes-base.httpRequest", "purpose": "Проверить статус и latency" }, { "name": "Classify health Code", "type": "n8n-nodes-base.code", "purpose": "Назначить severity и dedupe key" }, { "name": "Send Telegram alert", "type": "n8n-nodes-base.telegram", "purpose": "Уведомить команду о проблеме" } ], "connections": "Schedule → HTTP check → Classify → Telegram" } Пошаговая настройка мониторинга Beget, Timeweb и VPS ¶ Создайте отдельный endpoint /healthz или проверяйте лёгкий webhook n8n без бизнес-логики. Укажите production URL, ожидаемый статус и timeout. Добавьте Telegram credential и рабочий чат инцидентов. Настройте дедупликацию: один алерт на одну причину до recovery. Проверьте runbook: где перезапустить Docker Compose, как посмотреть логи и как откатить обновление. Тесты отказов и Telegram-алертов ¶ curl -fsS -o /dev/null -w '%{http_code} %{time_total} ' "https://n8n.example.ru/healthz" curl -X POST "https://YOUR-N8N-DOMAIN/webhook/beget-timeweb-n8n-healthcheck" -H "Content-Type: application/json" --data @beget-timeweb-n8n-healthcheck-payload.json Остановите контейнер n8n и проверьте critical alert. Подставьте неправильный URL и проверьте reason unexpected_status . Снизьте max_latency_ms , чтобы увидеть warning без реального падения. Верните сервис и убедитесь, что команда получает recovery-сообщение или видит его в incident log. Production-риски мониторинга n8n ¶ Мониторинг запущен внутри того же n8n. Если n8n упал целиком, он не отправит алерт. Используйте внешний cron или резервный мониторинг для критичных систем. Проверяется только главная страница. UI может открываться, а webhook endpoint уже недоступен из-за reverse proxy. Нет дедупликации. Каждые 5 минут чат получает одинаковое сообщение и команда перестаёт реагировать. Нет проверки SSL. Сертификат истёк, а HTTP-check начал падать уже после инцидента. Нет runbook. Алерт есть, но непонятно, кто и что должен сделать. Полезные ссылки и смежные инструкции ¶ Смотрите также: ENV-переменные n8n , Error Workflow с Telegram-алертом , Масштабирование n8n . Официальная документация: n8n hosting , Docker Compose , Telegram Bot API . Критерии готовности ¶ Падение n8n обнаруживается быстрее, чем пользователь пишет в поддержку. Проверяется именно webhook/health endpoint, а не только ping сервера. В алерте есть service, hoster, status, latency, severity и runbook. Повторяющиеся проблемы дедуплицируются до recovery. Есть отдельный план действий для Docker Compose, proxy, SSL и дискового места. Нужен мониторинг n8n без шума? Nodbot настроит healthcheck, Error Workflow, Telegram-алерты и runbook-и для ваших production-автоматизаций. Настроить мониторинг

## Test payload

```json
{
  "service": "n8n-production",
  "url": "https://n8n.example.ru/healthz",
  "webhook_url": "https://n8n.example.ru/webhook/healthcheck-ping",
  "expected_status": 200,
  "max_latency_ms": 2500,
  "alert_chat_id": "-1001234567890",
  "hoster": "timeweb-vps"
}
```

## Key implementation snippet

```javascript
const service = $json.service ?? 'n8n';
const status = Number($json.statusCode ?? $json.status ?? 0);
const latency = Number($json.latency_ms ?? $json.responseTime ?? 0);
const expected = Number($json.expected_status ?? 200);
const maxLatency = Number($json.max_latency_ms ?? 2500);
const sslDaysLeft = Number($json.ssl_days_left ?? 30);

let severity = 'ok';
let reason = 'service_available';
if (status !== expected) { severity = 'critical'; reason = `unexpected_status_${status}`; }
else if (latency > maxLatency) { severity = 'warning'; reason = 'slow_response'; }
else if (sslDaysLeft < 7) { severity = 'critical'; reason = 'ssl_expires_soon'; }
else if (sslDaysLeft < 14) { severity = 'warning'; reason = 'ssl_renewal_window'; }

return [{ json: {
  service,
  severity,
  reason,
  status,
  latency_ms: latency,
  ssl_days_left: sslDaysLeft,
  dedupe_key: `healthcheck:${service}:${reason}`,
  message: severity === 'ok'
    ? `✅ ${service}: OK, ${latency} ms`
    : `🚨 ${service}: ${reason}, status=${status}, latency=${latency} ms, ssl=${sslDaysLeft}d`,
  checked_at: new Date().toISOString()
}}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - n8n healthcheck for Beget and Timeweb",
  "nodes": [
    { "name": "Schedule every 5 min", "type": "n8n-nodes-base.scheduleTrigger", "purpose": "Запускать мониторинг по расписанию" },
    { "name": "Check n8n URL HTTP", "type": "n8n-nodes-base.httpRequest", "purpose": "Проверить статус и latency" },
    { "name": "Classify health Code", "type": "n8n-nodes-base.code", "purpose": "Назначить severity и dedupe key" },
    { "name": "Send Telegram alert", "type": "n8n-nodes-base.telegram", "purpose": "Уведомить команду о проблеме" }
  ],
  "connections": "Schedule → HTTP check → Classify → Telegram"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Email в задачи Битрикс24 через n8n: SLA | Nodbot"
source_url: "https://nodbot.ru/workflows/bitrix24-task-from-email/"
canonical_url: "https://nodbot.ru/workflows/bitrix24-task-from-email/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1093
---

# Создание задач Битрикс24 из email через n8n: SLA, вложения и дедупликация

## AI summary

Problem/Solution-мануал по созданию задач Битрикс24 из входящих писем через n8n: IMAP/Gmail trigger, парсинг темы и отправителя, дедупликация по Message-ID, SLA-дедлайн, вложения и task.add.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить webhook/API, проверить дубли, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему входящие email теряются без задач и SLA
- Архитектура workflow email → n8n → задача Битрикс24
- Контракт входных данных письма
- Message-ID, SLA и маппинг задачи (Code Node)
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка почты, n8n и задач Битрикс24
- Тесты перед production и проверка tasks.task.add
- Production-риски email-to-task автоматизации
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Email to task
- Bitrix24 tasks.task.add
- n8n IMAP Gmail trigger
- Message-ID dedupe
- SLA deadline
- attachments
- support workflow

## Source outline

Создание задач Битрикс24 из email через n8n: SLA, вложения и дедупликация ¶ Обновлено: 2026-05-30 Сохранить в мой план Открыть мой план Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте JSON в n8n, замените почтовый credential, Bitrix24 webhook URL и ID ответственных. Содержание Проблема: почему входящие email теряются без задач и SLA Архитектура workflow email → n8n → задача Битрикс24 Контракт входных данных письма Message-ID, SLA и маппинг задачи (Code Node) Готовый workflow JSON: скачать и импортировать Пошаговая настройка почты, n8n и задач Битрикс24 Тесты перед production и проверка tasks.task.add Production-риски email-to-task автоматизации Полезные ссылки и смежные workflow Критерии готовности Проблема: общий почтовый ящик поддержки быстро превращается в очередь без владельца: письма читают несколько человек, вложения теряются, дедлайны не видны, а повторная доставка письма может создать две задачи. Решение: принимать письма через n8n, создавать задачу Битрикс24 через REST API, считать дедлайн SLA по теме и тексту, прикреплять вложения или ссылки, а дубли отсекать по Message-ID . Так email становится управляемой задачей, а не случайной строкой во входящих. Это не универсальный парсер всех писем, а production-сценарий для поддержки, бухгалтерии или продаж: есть workflow JSON, payload, Code Node, таблица архитектуры, проверка tasks.task.add и чек-лист запуска. n8n превращает письмо в задачу Битрикс24 с владельцем, SLA и защитой от повторов. Проблема: почему входящие email теряются без задач и SLA ¶ Письмо само по себе не имеет статуса “в работе”, “просрочено” или “закрыто”. Когда команда ведёт поддержку из почты, важные обращения легко остаются без ответа, особенно если клиент пишет повторно в старой цепочке или пересылает вложение другому менеджеру. Автоматизация нужна не для того, чтобы “скопировать письмо в Битрикс24”, а чтобы создать управляемую задачу: с ответственным, дедлайном, ссылкой на оригинал, вложениями и правилом дедупликации. Архитектура workflow email → n8n → задача Битрикс24 ¶ Нода Роль Что проверить Email Trigger / Gmail Получает входящие письма Папка, фильтр, unread/read, вложения Normalize email Парсит тему, отправителя и текст Message-ID, encoding, пустая тема, HTML-only Check Message-ID Отсекает повторную доставку Durable storage с уникальным ключом Map SLA Назначает ответственного и deadline Слова “срочно”, клиентский домен, категория Create Bitrix24 task Вызывает tasks.task.add TITLE, DESCRIPTION, RESPONSIBLE_ID, DEADLINE Notify owner Уведомляет ответственного Без полного текста письма, если есть персональные данные Контракт входных данных письма ¶ Тестовый payload имитирует письмо после IMAP/Gmail trigger. В реальном workflow attachments могут быть бинарными данными n8n или ссылками на хранилище. { "message_id": "<20260530.1042.support@example.ru>", "from": "client@example.ru", "subject": "СРОЧНО: не приходит отчет по заказу 10492", "text": "Добрый день. Не получили отчет после оплаты. Просим проверить сегодня.", "received_at": "2026-05-30T09:42:00.000Z", "attachments": [ { "filename": "payment.pdf", "mimeType": "application/pdf", "size": 183422 } ] } Главное поле — message_id . Без него нельзя безопасно отличить новое письмо от повторной доставки или повторного запуска execution. Message-ID, SLA и маппинг задачи (Code Node) ¶ Code Node ниже готовит поля для задачи Битрикс24 и выставляет быстрый SLA, если в теме или тексте есть срочные маркеры. const email = $json; const subject = String(email.subject ?? '(без темы)').trim(); const from = String(email.from ?? '').trim().toLowerCase(); const messageId = String(email.message_id ?? email.messageId ?? '').trim(); if (!messageId) throw new Error('Email has no Message-ID; cannot deduplicate safely'); const isUrgent = /срочно|urgent|asap|сегодня/i.test(subject + ' ' + (email.text ?? '')); const now = new Date(email.received_at ?? Date.now()); const deadline = new Date(now.getTime() + (isUrgent ? 2 : 8) * 60 * 60 * 1000); const attachments = Array.isArray(email.attachments) ? email.attachments : []; return [{ json: { dedupe_key: `email-task:${messageId}`, bitrix_task: { title: `${isUrgent ? '[SLA] ' : ''}${subject}`, description: `Письмо от: ${from} Message-ID: ${messageId} ${email.text ?? ''}`, responsible_id: isUrgent ? 17 : 23, deadline: deadline.toISOString(), priority: isUrgent ? 2 : 1, tags: ['email', 'n8n', isUrgent ? 'sla-fast' : 'sla-standard'], attachment_count: attachments.length } } }]; В production лучше заменить простую регулярку срочности на словарь категорий: бухгалтерия, техподдержка, продажи, VIP-домен. Но даже базовое правило уже лучше ручной обработки почты без дедлайна. Готовый workflow JSON: скачать и импортировать ¶ Полный workflow JSON находится в архиве сайта. Он показывает структуру: получение письма, нормализация, Message-ID dedupe, загрузка вложений, вызов Bitrix24 API и уведомление владельца. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Email to Bitrix24 task with SLA", "nodes": [ { "name": "Email Trigger", "type": "n8n-nodes-base.emailReadImap", "purpose": "Получить новое письмо из ящика поддержки" }, { "name": "Normalize email", "type": "n8n-nodes-base.code", "purpose": "Собрать dedupe_key, SLA deadline и Bitrix24 task fields" }, { "name": "Check Message-ID", "type": "n8n-nodes-base.postgres", "purpose": "Не создать задачу повторно при повторной доставке письма" }, { "name": "Upload attachments", "type": "n8n-nodes-base.httpRequest", "purpose": "Передать вложения или ссылки на файлы" }, { "name": "Create Bitrix24 task", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать tasks.task.add" }, { "name": "Notify owner", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить ответственному о новой SLA-задаче" } ], "connections": "Email Trigger → Normalize → Dedupe → Attachments → tasks.task.add → Notify" } Пошаговая настройка почты, n8n и задач Битрикс24 ¶ Подключите IMAP, Gmail или Microsoft mailbox к n8n и ограничьте папку входящих. Импортируйте workflow JSON и замените Bitrix24 webhook URL. Настройте таблицу dedupe по Message-ID . Пропишите ID ответственных и правила SLA для срочных/обычных писем. Решите, как хранить вложения: напрямую в Битрикс24, в облаке или ссылкой в описании. Отправьте тестовое письмо дважды и убедитесь, что задача создаётся один раз. Идеальная задача: есть источник письма, дедлайн SLA, ответственный и информация о вложении. Тесты перед production и проверка tasks.task.add ¶ Проверяйте не только появление задачи. Откройте карточку Битрикс24 и убедитесь, что заголовок читаемый, в описании есть отправитель и Message-ID, дедлайн соответствует SLA, а вложения доступны ответственному. curl -X POST "https://YOUR-N8N-DOMAIN/webhook/bitrix24-task-from-email" \ -H "Content-Type: application/json" \ --data @bitrix24-task-from-email-payload.json Повторный Message-ID не должен создавать вторую задачу. Письмо без темы должно получать безопасный title, а не падать. Срочное письмо должно иметь короткий deadline и правильного ответственного. Ошибка Bitrix24 API должна попадать в alert или DLQ. Production-риски email-to-task автоматизации ¶ Нет Message-ID dedupe. Повторная доставка или retry создаст несколько задач. HTML-письмо не очищается. В задачу попадают мусорные теги и подписи. Вложения теряются. Клиент приложил счёт или скриншот, а менеджер видит только текст. Нет SLA-календаря. Простые “+2 часа” ломаются на выходных и праздниках. Персональные данные в уведомлениях. В Telegram/Slack лучше отправлять ссылку на задачу, а не полный текст письма. Полезные ссылки и смежные workflow ¶ Официальная документация: Bitrix24 REST tasks.task.add и обзор задач Bitrix24 REST . Внутри Nodbot смотрите Битрикс24 в n8n , Gmail attachments to Yandex Disk , Retry и DLQ и Telegram alert для ошибок workflow . Критерии готовности ¶ Каждое письмо с одним Message-ID создаёт не больше одной задачи. У задачи есть ответственный, deadline, источник и ссылка/вложение. Срочные письма получают отдельный SLA и тег. Ошибки Bitrix24 API видны владельцу workflow. Команда знает, какие письма автоматизируются, а какие остаются ручными. Нужно превратить почту в SLA-задачи? Nodbot настроит email → n8n → Битрикс24: дедупликацию, вложения, SLA, ответственных и мониторинг ошибок. Обсудить email-to-task workflow

## Test payload

```json
{
  "message_id": "<20260530.1042.support@example.ru>",
  "from": "client@example.ru",
  "subject": "СРОЧНО: не приходит отчет по заказу 10492",
  "text": "Добрый день. Не получили отчет после оплаты. Просим проверить сегодня.",
  "received_at": "2026-05-30T09:42:00.000Z",
  "attachments": [
    { "filename": "payment.pdf", "mimeType": "application/pdf", "size": 183422 }
  ]
}
```

## Key implementation snippet

```javascript
const email = $json;
const subject = String(email.subject ?? '(без темы)').trim();
const from = String(email.from ?? '').trim().toLowerCase();
const messageId = String(email.message_id ?? email.messageId ?? '').trim();
if (!messageId) throw new Error('Email has no Message-ID; cannot deduplicate safely');

const isUrgent = /срочно|urgent|asap|сегодня/i.test(subject + ' ' + (email.text ?? ''));
const now = new Date(email.received_at ?? Date.now());
const deadline = new Date(now.getTime() + (isUrgent ? 2 : 8) * 60 * 60 * 1000);
const attachments = Array.isArray(email.attachments) ? email.attachments : [];

return [{
  json: {
    dedupe_key: `email-task:${messageId}`,
    bitrix_task: {
      title: `${isUrgent ? '[SLA] ' : ''}${subject}`,
      description: `Письмо от: ${from}
Message-ID: ${messageId}

${email.text ?? ''}`,
      responsible_id: isUrgent ? 17 : 23,
      deadline: deadline.toISOString(),
      priority: isUrgent ? 2 : 1,
      tags: ['email', 'n8n', isUrgent ? 'sla-fast' : 'sla-standard'],
      attachment_count: attachments.length
    }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Email to Bitrix24 task with SLA",
  "nodes": [
    { "name": "Email Trigger", "type": "n8n-nodes-base.emailReadImap", "purpose": "Получить новое письмо из ящика поддержки" },
    { "name": "Normalize email", "type": "n8n-nodes-base.code", "purpose": "Собрать dedupe_key, SLA deadline и Bitrix24 task fields" },
    { "name": "Check Message-ID", "type": "n8n-nodes-base.postgres", "purpose": "Не создать задачу повторно при повторной доставке письма" },
    { "name": "Upload attachments", "type": "n8n-nodes-base.httpRequest", "purpose": "Передать вложения или ссылки на файлы" },
    { "name": "Create Bitrix24 task", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать tasks.task.add" },
    { "name": "Notify owner", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить ответственному о новой SLA-задаче" }
  ],
  "connections": "Email Trigger → Normalize → Dedupe → Attachments → tasks.task.add → Notify"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "SEO-брифы через n8n: контент без ошибок | Nodbot"
source_url: "https://nodbot.ru/workflows/content-factory-seo-briefs/"
canonical_url: "https://nodbot.ru/workflows/content-factory-seo-briefs/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 973
---

# Контент-фабрика на n8n: SEO-брифы, фактчекинг и очередь публикаций

## AI summary

Страница показывает, как собрать в n8n контент-фабрику для SEO-брифов: принять тему, проверить интент, собрать факты, подготовить ТЗ, поставить материал в очередь и не выпустить непроверенный текст.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API/CMS/мессенджер, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему контент-фабрика без контроля плодит слабые статьи
- Архитектура workflow для SEO-брифов
- Контракт входных данных
- Скрипт n8n для проверки интента и фактов
- Готовый workflow JSON
- Пошаговая настройка контент-фабрики
- Тесты перед production
- Production-риски SEO-контента
- Полезные ссылки и смежные сценарии
- Критерии готовности

## Key topics

- контент-фабрика n8n
- SEO-бриф
- фактчекинг
- LLM-разметка
- очередь публикаций

## Source outline

Контент-фабрика на n8n: SEO-брифы, фактчекинг и очередь публикаций ¶ Обновлено: 2026-05-30 AI summary: Страница показывает, как собрать в n8n контент-фабрику для SEO-брифов: принять тему, проверить интент, собрать факты, подготовить ТЗ, поставить материал в очередь и не выпустить непроверенный текст. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему контент-фабрика без контроля плодит слабые статьи Архитектура workflow для SEO-брифов Контракт входных данных Скрипт n8n для проверки интента и фактов Готовый workflow JSON Пошаговая настройка контент-фабрики Тесты перед production Production-риски SEO-контента Полезные ссылки и смежные сценарии Критерии готовности Проблема: без строгого брифа автоматизированный контент превращается в одинаковые статьи, слабые заголовки и непроверенные факты, которые не помогают пользователю и мешают SEO. Решение: надежный сценарий — принимать тему через n8n, проверять интент, собирать источники, формировать редакционный SEO-бриф, добавлять LLM-разметку и ставить задачу в очередь публикации. Workflow превращает тему в проверяемый SEO-бриф, а не в сырой автогенерированный текст. Проблема: почему контент-фабрика без контроля плодит слабые статьи ¶ Автоматизация контента часто начинается с простой идеи: отправить тему в LLM и получить черновик. На практике такой процесс быстро создаёт одинаковые статьи, выдуманные факты, слабые заголовки и страницы, которые конкурируют между собой. Для SEO это опаснее, чем медленная ручная подготовка: сайт получает много URL, но мало полезности. Контент-фабрика на n8n должна работать как редакционный конвейер, а не как генератор текста. На входе нужна тема, интент, целевая страница, список обязательных блоков, источники и критерии готовности. На выходе — не абстрактный текст, а SEO-бриф, который редактор может проверить и превратить в полезную статью. Архитектура workflow для SEO-брифов ¶ Нода Роль Что проверить Webhook brief request Принимает тему и данные кластера topic, target_url, intent, primary_keyword Validate brief inputs Проверяет полноту ТЗ нет пустого интента, есть источники и CTA Collect official sources Собирает первоисточники не подменять docs блогами и форумами Build editor task Готовит структуру статьи H1/H2, LSI, payload, workflow JSON Queue for publication Отправляет задачу в Notion/CMS статус, владелец, дедлайн Контракт входных данных ¶ { "topic": "n8n Google Sheets upsert по телефону", "cluster": "workflows/crm", "target_url": "/workflows/google-sheets-upsert-by-phone/", "audience": "интеграторы n8n и владельцы CRM", "intent": "решить проблему дублей лидов", "primary_keyword": "n8n google sheets upsert", "must_include": [ "payload", "Code node", "production-риски", "workflow JSON" ], "sources": [ "https://docs.n8n.io/", "https://developers.google.com/sheets/api" ], "deadline": "2026-06-03" } Не передавайте в workflow только ключевое слово. Для качественного SEO-брифа нужен контекст: кто читатель, какую боль решает материал, чем страница отличается от соседних и какие блоки нельзя пропустить. Скрипт n8n для проверки интента и фактов ¶ const src = $json.body ?? $json; const topic = String(src.topic ?? '').trim(); const keyword = String(src.primary_keyword ?? '').trim().toLowerCase(); const intent = String(src.intent ?? '').trim(); if (!topic || topic.length < 12) { throw new Error('Topic is too short for SEO brief'); } const required = ['payload', 'workflow json', 'production', 'code node']; const mustInclude = (src.must_include ?? []).map(v => String(v).toLowerCase()); const missing = required.filter(item => !mustInclude.join(' ').includes(item)); const slug = topic .toLowerCase() .replace(/[^a-zа-яё0-9]+/gi, '-') .replace(/^-|-$/g, '') .slice(0, 80); return [{ json: { content_status: missing.length ? 'needs_editor_review' : 'ready_for_brief', slug, title_angle: `${topic}: конкретная проблема и production-решение`, search_intent: intent || 'problem-solution tutorial', primary_keyword: keyword, required_blocks: ['Problem/Solution', 'TOC', 'workflow JSON', 'test payload', 'risks', 'CTA'], missing_requirements: missing, llm_summary: `SEO-бриф для статьи: ${topic}. Интент: ${intent || keyword}`, created_at: new Date().toISOString() } }]; Что делает этот Code Node Он не пишет статью автоматически. Он проверяет, достаточно ли данных для редакционного брифа, формирует slug, обязательные блоки и статус. Если нет workflow JSON, payload или production-рисков, задача уходит на доработку до генерации текста. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - SEO brief factory with fact-check queue", "nodes": [ { "name": "Webhook brief request", "type": "n8n-nodes-base.webhook", "purpose": "Принять тему, интент и исходные источники" }, { "name": "Validate brief inputs", "type": "n8n-nodes-base.code", "purpose": "Проверить тему, keyword, обязательные блоки и LLM-summary" }, { "name": "Collect official sources", "type": "n8n-nodes-base.httpRequest", "purpose": "Собрать ссылки на официальные документы и первоисточники" }, { "name": "Build editor task", "type": "n8n-nodes-base.code", "purpose": "Сформировать ТЗ с H1/H2, payload, рисками и CTA" }, { "name": "Queue for publication", "type": "n8n-nodes-base.httpRequest", "purpose": "Отправить бриф в Notion, CMS или трекер задач" } ], "connections": "Webhook → Validate → Sources → Build task → Queue" } Пошаговая настройка контент-фабрики ¶ Создайте форму или внутренний webhook для подачи темы. Опишите обязательные поля: интент, аудитория, target URL, первичные источники. Подключите хранилище задач: Notion, Google Sheets, Linear, YouTrack или CMS. Добавьте правило, которое блокирует задачу без источников, кода, тестов и CTA. Сделайте отдельный статус для фактчекинга, чтобы непроверенный текст не попадал в публикацию. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/content-factory-seo-briefs" \ -H "Content-Type: application/json" \ --data @content-factory-seo-briefs-payload.json Прогоните три сценария: полный SEO-бриф, тема без источников и тема, которая пересекается с существующей страницей. В последнем случае workflow должен предложить обновление текущего URL, а не создание нового дубля. Production-риски SEO-контента ¶ Редакторский комментарий попал в статью. Уберите любые блоки вида “SEO-интент страницы” из публичного текста. LLM придумала факты. Разделяйте генерацию структуры и проверку по источникам. Каннибализация. Перед созданием новой темы проверяйте существующие URL кластера. Нет LLM-разметки. Без AI summary и LLM markdown страница хуже переиспользуется поиском и ассистентами. Нет владельца задачи. Контент-фабрика без ответственного быстро превращается в очередь черновиков. Полезные ссылки и смежные сценарии ¶ Для внедрения пригодятся внутренние материалы: регрессионные тесты промптов , тестирование workflow , Notion → WordPress черновик и RSS-дайджест в Telegram . Из внешних источников используйте официальную документацию n8n и API-документы сервисов, которые подключаете к контент-процессу. Так должна выглядеть задача на выходе: интент, статус, требования и следующий шаг для редактора. Критерии готовности ¶ Каждая тема привязана к интенту и target URL. В брифе есть H1/H2, LSI, источники, code/payload и CTA. Новая статья не дублирует существующую страницу кластера. Фактчекинг отделён от генерации текста. LLM summary и markdown обновляются вместе с HTML. Нужна контент-фабрика без SEO-воды? Nodbot настроит процесс: брифы, фактчекинг, LLM-разметку, очередь публикации и контроль дублей между страницами. Обсудить контент-процесс

## Test payload

```json
{
  "topic": "n8n Google Sheets upsert по телефону",
  "cluster": "workflows/crm",
  "target_url": "/workflows/google-sheets-upsert-by-phone/",
  "audience": "интеграторы n8n и владельцы CRM",
  "intent": "решить проблему дублей лидов",
  "primary_keyword": "n8n google sheets upsert",
  "must_include": [
    "payload",
    "Code node",
    "production-риски",
    "workflow JSON"
  ],
  "sources": [
    "https://docs.n8n.io/",
    "https://developers.google.com/sheets/api"
  ],
  "deadline": "2026-06-03"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const topic = String(src.topic ?? '').trim();
const keyword = String(src.primary_keyword ?? '').trim().toLowerCase();
const intent = String(src.intent ?? '').trim();

if (!topic || topic.length < 12) {
  throw new Error('Topic is too short for SEO brief');
}

const required = ['payload', 'workflow json', 'production', 'code node'];
const mustInclude = (src.must_include ?? []).map(v => String(v).toLowerCase());
const missing = required.filter(item => !mustInclude.join(' ').includes(item));

const slug = topic
  .toLowerCase()
  .replace(/[^a-zа-яё0-9]+/gi, '-')
  .replace(/^-|-$/g, '')
  .slice(0, 80);

return [{
  json: {
    content_status: missing.length ? 'needs_editor_review' : 'ready_for_brief',
    slug,
    title_angle: `${topic}: конкретная проблема и production-решение`,
    search_intent: intent || 'problem-solution tutorial',
    primary_keyword: keyword,
    required_blocks: ['Problem/Solution', 'TOC', 'workflow JSON', 'test payload', 'risks', 'CTA'],
    missing_requirements: missing,
    llm_summary: `SEO-бриф для статьи: ${topic}. Интент: ${intent || keyword}`,
    created_at: new Date().toISOString()
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - SEO brief factory with fact-check queue",
  "nodes": [
    {
      "name": "Webhook brief request",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять тему, интент и исходные источники"
    },
    {
      "name": "Validate brief inputs",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить тему, keyword, обязательные блоки и LLM-summary"
    },
    {
      "name": "Collect official sources",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Собрать ссылки на официальные документы и первоисточники"
    },
    {
      "name": "Build editor task",
      "type": "n8n-nodes-base.code",
      "purpose": "Сформировать ТЗ с H1/H2, payload, рисками и CTA"
    },
    {
      "name": "Queue for publication",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Отправить бриф в Notion, CMS или трекер задач"
    }
  ],
  "connections": "Webhook → Validate → Sources → Build task → Queue"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "DaData и n8n: обогащение лидов с quality gate | Nodbot"
source_url: "https://nodbot.ru/workflows/dadata-enrich-lead/"
canonical_url: "https://nodbot.ru/workflows/dadata-enrich-lead/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1235
---

# Обогащение лидов через DaData и n8n: телефон, компания и quality gate

## AI summary

Problem/Solution-мануал по обогащению лидов через DaData и n8n: нормализация телефона, ИНН, подсказки по организации, confidence gate, защита CRM от перезаписи хороших данных и production-тесты.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить webhook/API, проверить дубли, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему автоматическое обогащение лидов может испортить CRM
- Архитектура workflow DaData → n8n → CRM
- Контракт входных данных для enrichment
- Нормализация телефона, ИНН и confidence gate (Code Node)
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка DaData API, n8n и CRM
- Тесты перед production и проверка DaData API
- Production-риски обогащения данных
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- DaData API
- n8n enrichment
- quality gate
- CRM data quality
- phone normalization
- ИНН
- manual review
- workflow JSON

## Source outline

Обогащение лидов через DaData и n8n: телефон, компания и quality gate ¶ Обновлено: 2026-05-30 Сохранить в мой план Открыть мой план Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте JSON в n8n, замените DaData API key, secret и CRM endpoint. Перед production проверьте quality gate на реальных лидах. Содержание Проблема: почему автоматическое обогащение лидов может испортить CRM Архитектура workflow DaData → n8n → CRM Контракт входных данных для enrichment Нормализация телефона, ИНН и confidence gate (Code Node) Готовый workflow JSON: скачать и импортировать Пошаговая настройка DaData API, n8n и CRM Тесты перед production и проверка DaData API Production-риски обогащения данных Полезные ссылки и смежные workflow Критерии готовности Проблема: обогащение лидов через DaData кажется безопасным, пока workflow не начинает перезаписывать уже проверенные телефоны, названия компаний и реквизиты в CRM. Один неточный match по названию может превратить качественную карточку клиента в спорную запись. Решение: делать enrichment через n8n с quality gate: сначала нормализовать телефон и ИНН, затем запросить DaData API, посчитать confidence score и обновлять CRM автоматически только при достаточной уверенности. Спорные данные должны попадать в ручную проверку, а не прямо в карточку продаж. Это практический скрипт n8n для обогащения CRM: payload, Code Node, workflow JSON, тесты, риски и понятный критерий, когда можно доверять данным DaData. Workflow не пишет найденные данные в CRM напрямую: между DaData и CRM стоит quality gate. Проблема: почему автоматическое обогащение лидов может испортить CRM ¶ Типичная ошибка — воспринимать подсказку как истину. DaData хорошо помогает найти организацию по ИНН или названию, но в реальном потоке лидов бывают сокращения, филиалы, старые компании, телефоны из коллтрекинга и заявки от посредников. Поэтому интегратор должен отделить “подсказку для оператора” от “данных, которыми можно обновить CRM без человека”. Особенно опасно перезаписывать поле company , ответственного или юридическое лицо после первого успешного enrichment. Правильная автоматизация продаж сохраняет исходные данные формы, добавляет enriched-блок рядом и показывает источник/уверенность. Архитектура workflow DaData → n8n → CRM ¶ Нода Роль Что проверить Webhook input Принимает lead payload из CRM, Tilda или Битрикс24 lead_id , телефон, ИНН, email, источник Normalize and score Готовит телефон, ИНН и базовый score Регулярка телефона, 10/12 цифр ИНН, пустые значения DaData clean phone Проверяет и стандартизирует номер API key/secret, лимиты, страна и формат DaData suggest party Ищет компанию по ИНН или названию Не брать первый match без confidence gate Quality gate Решает: auto update или manual review Порог score и список полей, разрешённых к обновлению CRM update / review task Обновляет карточку или создаёт задачу Не перезаписывать проверенные поля без правила Контракт входных данных для enrichment ¶ Передавайте в enrichment только поля, которые реально участвуют в решении: идентификатор лида, телефон, email, ИНН, название и ссылку на CRM. Полный комментарий клиента и лишние персональные данные здесь не нужны. { "lead_id": "crm-10492", "name": "ООО Ромашка", "phone": "+7 (495) 123-45-67", "email": "sales@romashka.example", "inn": "7707083893", "source": "tilda_form", "crm_url": "https://crm.example.ru/leads/10492" } Если ИНН отсутствует, workflow может искать компанию по названию, но такой результат должен иметь меньший score. Если нет ни ИНН, ни нормального телефона, лучше создать задачу “проверить данные”, чем писать случайные подсказки в CRM. Нормализация телефона, ИНН и confidence gate (Code Node) ¶ Этот Code Node не вызывает DaData напрямую. Он готовит стабильный объект для HTTP Request и решает, есть ли смысл обогащать запись автоматически. const src = $json.body ?? $json; const rawPhone = String(src.phone ?? '').trim(); let digits = rawPhone.replace(/\D/g, ''); if (digits.length === 11 && digits.startsWith('8')) digits = `7${digits.slice(1)}`; if (digits.length === 10) digits = `7${digits}`; const phoneOk = /^7\d{10}$/.test(digits); const inn = String(src.inn ?? '').replace(/\D/g, ''); const innOk = /^(\d{10}|\d{12})$/.test(inn); const email = String(src.email ?? '').trim().toLowerCase(); const companyQuery = innOk ? inn : String(src.name ?? '').trim(); const score = [ phoneOk ? 30 : 0, innOk ? 40 : 0, companyQuery.length >= 3 ? 20 : 0, email.includes('@') ? 10 : 0 ].reduce((a, b) => a + b, 0); return [{ json: { lead_id: src.lead_id, phone_normalized: phoneOk ? `+${digits}` : null, inn, email, company_query: companyQuery, confidence_score: score, enrichment_mode: score >= 70 ? 'auto_update' : 'manual_review', dadata: { clean_phone_url: 'https://cleaner.dadata.ru/api/v1/clean/phone', suggest_party_url: 'https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/party' } } }]; Порог 70 — пример. Для B2B-лидов с ИНН его можно поднять до 80–90, а для входящих заявок без реквизитов оставить ручную проверку. Главное — фиксировать правило в workflow, а не держать его в голове интегратора. Готовый workflow JSON: скачать и импортировать ¶ Полный workflow JSON находится в архиве сайта и доступен по кнопке в начале статьи. Внутри есть HTTP Request для DaData, ветка quality gate и пример обновления CRM. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - DaData lead enrichment with quality gate", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять lead_id, телефон, email, ИНН и название компании" }, { "name": "Normalize and score", "type": "n8n-nodes-base.code", "purpose": "Подготовить телефон, ИНН и confidence_score" }, { "name": "DaData clean phone", "type": "n8n-nodes-base.httpRequest", "purpose": "Очистить и проверить телефон" }, { "name": "DaData suggest party", "type": "n8n-nodes-base.httpRequest", "purpose": "Найти организацию по ИНН или названию" }, { "name": "Quality gate", "type": "n8n-nodes-base.if", "purpose": "Разделить auto_update и manual_review" }, { "name": "Update CRM or create review task", "type": "n8n-nodes-base.httpRequest", "purpose": "Обновить CRM только при достаточной уверенности" } ], "connections": "Webhook → Normalize → DaData phone/party → Quality gate → CRM update or review" } Пошаговая настройка DaData API, n8n и CRM ¶ Создайте DaData credentials в n8n: API key и Secret key храните в credentials или ENV. Импортируйте workflow JSON и замените CRM endpoint на ваш URL обновления лида. Решите, какие поля можно обновлять автоматически: например, phone_validated, company_inn, company_name_suggested. Настройте ветку manual review для score ниже порога: задача менеджеру, комментарий или отдельный статус. Запустите тестовый payload с ИНН, без ИНН и с плохим телефоном. Хороший результат: исходные поля сохранены, enriched-значения подписаны источником и score. Тесты перед production и проверка DaData API ¶ Проверяйте не только HTTP 200 от DaData. Важно увидеть, какие именно поля workflow собирается обновить и почему score достаточный. Для каждого теста сохраните execution, чтобы потом объяснить менеджерам логику принятия решения. curl -X POST "https://YOUR-N8N-DOMAIN/webhook/dadata-enrich-lead" \ -H "Content-Type: application/json" \ --data @dadata-enrich-lead-payload.json Лид с валидным ИНН и телефоном должен уйти в auto_update . Лид только с названием компании должен уйти в manual_review или получить низкий score. Плохой телефон не должен перезаписывать рабочий номер в CRM. Ошибка лимита DaData должна попасть в alert/retry, а не в тихий success. Production-риски обогащения данных ¶ Перезапись хороших данных. Никогда не заменяйте проверенные поля без признака источника и даты обогащения. Первый match принят автоматически. Для названий компаний это риск, особенно при франшизах и филиалах. DaData token попал в лог. Не отправляйте headers и полный response в публичные алерты. Нет лимитов и backoff. Массовая переработка базы может быстро упереться в ограничения API. Нет ручной очереди. Все спорные лиды должны быть видны человеку, иначе они просто теряются. Полезные ссылки и смежные workflow ¶ Официальная документация: DaData API подсказок по организациям . Внутри Nodbot полезны страницы Tilda → Битрикс24 , Tilda → amoCRM , retry и DLQ для HTTP Request и HTTP Request node . Критерии готовности ¶ В workflow есть порог confidence score и ветка manual review. Исходные данные формы не удаляются и не перезаписываются без trace. DaData credentials не видны в HTML, workflow notes и alert-сообщениях. Тесты покрывают валидный ИНН, неточный company name, плохой телефон и лимит API. Менеджер видит enriched-поля, источник и дату последней проверки. Нужно обогатить CRM без хаоса в данных? Nodbot настроит DaData enrichment через n8n с quality gate, ручной очередью и безопасным обновлением CRM-полей. Обсудить enrichment workflow

## Test payload

```json
{
  "lead_id": "crm-10492",
  "name": "ООО Ромашка",
  "phone": "+7 (495) 123-45-67",
  "email": "sales@romashka.example",
  "inn": "7707083893",
  "source": "tilda_form",
  "crm_url": "https://crm.example.ru/leads/10492"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const rawPhone = String(src.phone ?? '').trim();
let digits = rawPhone.replace(/\D/g, '');
if (digits.length === 11 && digits.startsWith('8')) digits = `7${digits.slice(1)}`;
if (digits.length === 10) digits = `7${digits}`;

const phoneOk = /^7\d{10}$/.test(digits);
const inn = String(src.inn ?? '').replace(/\D/g, '');
const innOk = /^(\d{10}|\d{12})$/.test(inn);
const email = String(src.email ?? '').trim().toLowerCase();
const companyQuery = innOk ? inn : String(src.name ?? '').trim();

const score = [
  phoneOk ? 30 : 0,
  innOk ? 40 : 0,
  companyQuery.length >= 3 ? 20 : 0,
  email.includes('@') ? 10 : 0
].reduce((a, b) => a + b, 0);

return [{
  json: {
    lead_id: src.lead_id,
    phone_normalized: phoneOk ? `+${digits}` : null,
    inn,
    email,
    company_query: companyQuery,
    confidence_score: score,
    enrichment_mode: score >= 70 ? 'auto_update' : 'manual_review',
    dadata: {
      clean_phone_url: 'https://cleaner.dadata.ru/api/v1/clean/phone',
      suggest_party_url: 'https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/party'
    }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - DaData lead enrichment with quality gate",
  "nodes": [
    { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять lead_id, телефон, email, ИНН и название компании" },
    { "name": "Normalize and score", "type": "n8n-nodes-base.code", "purpose": "Подготовить телефон, ИНН и confidence_score" },
    { "name": "DaData clean phone", "type": "n8n-nodes-base.httpRequest", "purpose": "Очистить и проверить телефон" },
    { "name": "DaData suggest party", "type": "n8n-nodes-base.httpRequest", "purpose": "Найти организацию по ИНН или названию" },
    { "name": "Quality gate", "type": "n8n-nodes-base.if", "purpose": "Разделить auto_update и manual_review" },
    { "name": "Update CRM or create review task", "type": "n8n-nodes-base.httpRequest", "purpose": "Обновить CRM только при достаточной уверенности" }
  ],
  "connections": "Webhook → Normalize → DaData phone/party → Quality gate → CRM update or review"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Backup n8n в S3: Docker Compose и PostgreSQL | Nodbot"
source_url: "https://nodbot.ru/workflows/docker-compose-backup-to-s3/"
canonical_url: "https://nodbot.ru/workflows/docker-compose-backup-to-s3/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1040
---

# Backup n8n в S3 через Docker Compose: PostgreSQL, workflows и restore-test

## AI summary

AI-friendly Problem/Solution-мануал: как настроить backup n8n в Docker Compose с PostgreSQL, выгрузкой workflows, S3-compatible storage, retention policy, restore-test, workflow JSON, bash-командами и production-чеклистом.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить безопасность/API/backup, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: backup n8n бесполезен без restore-test
- Архитектура backup workflow для Docker Compose
- Контракт параметров backup job
- Команды: pg_dump, workflows export и upload в S3
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка backup n8n в S3
- Тесты restore, retention и integrity check
- Production-риски резервного копирования
- Полезные ссылки и документация
- Критерии готовности

## Key topics

- n8n backup
- Docker Compose
- PostgreSQL pg_dump
- S3 compatible storage
- restore-test
- N8N_ENCRYPTION_KEY

## Source outline

Backup n8n в S3 через Docker Compose: PostgreSQL, workflows и restore-test ¶ Обновлено: 2026-05-30 AI summary: AI-friendly Problem/Solution-мануал: как настроить backup n8n в Docker Compose с PostgreSQL, выгрузкой workflows, S3-compatible storage, retention policy, restore-test, workflow JSON, bash-командами и production-чеклистом. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Перед запуском замените SSH host, S3 endpoint, bucket, retention и имена Docker Compose services. Содержание Проблема: backup n8n бесполезен без restore-test Архитектура backup workflow для Docker Compose Контракт параметров backup job Команды: pg_dump, workflows export и upload в S3 Готовый workflow JSON: скачать и импортировать Пошаговая настройка backup n8n в S3 Тесты restore, retention и integrity check Production-риски резервного копирования Полезные ссылки и документация Критерии готовности Проблема: self-hosted n8n в Docker Compose часто живёт годами без проверенного восстановления. Файл “backup.tar.gz” вроде есть, но никто не знает, содержит ли он PostgreSQL, workflows, бинарные данные, настройки encryption key и можно ли поднять из него рабочую копию. Решение: настроить backup n8n в S3-совместимое хранилище как production-процесс: pg_dump PostgreSQL, export workflows, archive, upload, retention, integrity check и регулярный restore-test. Только тогда резервная копия помогает при ошибке обновления, падении VPS или повреждении volume. Backup считается готовым только после успешной проверки восстановления. Проблема: backup n8n бесполезен без restore-test ¶ Самая частая ошибка — копировать только Docker volume или только JSON workflows. Для n8n этого мало: основная рабочая история, credentials metadata и executions обычно лежат в PostgreSQL, а возможность расшифровать credentials зависит от N8N_ENCRYPTION_KEY . Если ключ потерян, backup базы не спасёт credentials. Поэтому workflow должен не просто загрузить архив в S3, а зафиксировать состав backup, размер, checksum, retention policy и результат восстановления на отдельной тестовой среде. Архитектура backup workflow для Docker Compose ¶ Нода Роль Что проверить Schedule nightly Запускает backup по расписанию Часовой пояс, окно низкой нагрузки Prepare backup id Собирает имена файлов и retention Уникальный timestamp, environment label Run pg_dump Снимает PostgreSQL dump Права пользователя, формат -Fc , ненулевой размер Export workflows Экспортирует workflow JSON Все workflows, не полагаться только на UI export Upload to S3 Кладёт архив в S3-compatible storage Endpoint, bucket policy, шифрование Notify result Отправляет статус в Telegram/Slack Размер, checksum, restore-test Контракт параметров backup job ¶ Параметры backup лучше хранить явно: так новая команда поймёт, какой контейнер дампится, где лежит bucket и сколько дней держать копии. { "backup_name": "n8n-prod-nightly", "postgres_container": "n8n-postgres-1", "n8n_container": "n8n-app-1", "database": "n8n", "s3_bucket": "s3://company-backups/n8n/prod", "retention_days": 30, "restore_test": true } Команды: pg_dump, workflows export и upload в S3 ¶ Code Node готовит безопасные имена файлов, а реальные команды выполняются через SSH на Docker host или отдельный runner. Не запускайте dump из браузерного окружения. const src = $json.body ?? $json; const now = new Date(); const stamp = now.toISOString().replace(/[:.]/g, '-'); const name = String(src.backup_name ?? 'n8n-prod').replace(/[^a-z0-9_-]/gi, '-').toLowerCase(); const retentionDays = Number(src.retention_days ?? 30); if (retentionDays < 7) throw new Error('Retention must be at least 7 days for production n8n'); return [{ json: { backup_id: `${name}-${stamp}`, pg_file: `/tmp/${name}-${stamp}.pgdump`, workflows_file: `/tmp/${name}-${stamp}-workflows.json`, archive_file: `/tmp/${name}-${stamp}.tar.gz`, s3_prefix: String(src.s3_bucket ?? '').replace(/\/$/, ''), retention_days: retentionDays, restore_test_required: src.restore_test !== false, labels: { app: 'n8n', type: 'backup', environment: 'production' } } }]; Bash-команды для runner или SSH-ноды ¶ # PostgreSQL dump from Docker Compose mkdir -p /tmp/n8n-backup PGFILE="/tmp/n8n-backup/n8n-$(date -u +%Y%m%dT%H%M%SZ).pgdump" docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc > "$PGFILE" # Export workflows and credentials metadata from n8n container WF="/tmp/n8n-backup/workflows-$(date -u +%Y%m%dT%H%M%SZ).json" docker compose exec -T n8n n8n export:workflow --all --pretty > "$WF" # Archive and upload to S3-compatible storage ARCHIVE="${PGFILE%.pgdump}.tar.gz" tar -czf "$ARCHIVE" -C /tmp/n8n-backup "$(basename "$PGFILE")" "$(basename "$WF")" aws s3 cp "$ARCHIVE" "s3://company-backups/n8n/prod/$(basename "$ARCHIVE")" --only-show-errors Что положить рядом с архивом N8N_ENCRYPTION_KEY — хранить отдельно в секретном хранилище, не в архиве. Версию n8n и PostgreSQL. Checksum архива. Инструкцию restore для дежурного инженера. Готовый workflow JSON: скачать и импортировать ¶ Готовый workflow JSON включает расписание, подготовку backup id, placeholder SSH-команды, upload в S3 и уведомление. После импорта замените endpoint и credentials. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - n8n Docker Compose backup to S3", "nodes": [ { "name": "Schedule nightly", "type": "n8n-nodes-base.scheduleTrigger", "purpose": "Запустить backup по расписанию" }, { "name": "Prepare backup id", "type": "n8n-nodes-base.code", "purpose": "Собрать имена файлов и retention" }, { "name": "Run pg_dump", "type": "n8n-nodes-base.ssh", "purpose": "Снять PostgreSQL dump с Docker host" }, { "name": "Export workflows", "type": "n8n-nodes-base.ssh", "purpose": "Экспортировать workflows" }, { "name": "Upload to S3", "type": "n8n-nodes-base.httpRequest", "purpose": "Загрузить архив в S3-compatible storage" }, { "name": "Notify result", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить статус backup и restore-test" } ], "connections": "Schedule → Prepare → pg_dump/export → S3 upload → Notify" } Пошаговая настройка backup n8n в S3 ¶ Проверьте, что n8n работает на PostgreSQL, а не на SQLite. Сохраните N8N_ENCRYPTION_KEY в отдельном secret vault. Создайте S3 bucket с версионированием или lifecycle policy. Настройте SSH-доступ runner-а к Docker host с минимальными правами. Запустите workflow вручную и проверьте размер dump, checksum и upload. Поднимите тестовый restore на отдельной машине. Тесты restore, retention и integrity check ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/docker-compose-backup-to-s3" -H "Content-Type: application/json" --data @docker-compose-backup-to-s3-payload.json Минимальный restore-test: создать чистую PostgreSQL, восстановить dump, запустить n8n с тем же encryption key, открыть UI, проверить credentials и выполнить один безопасный workflow. Production-риски резервного копирования ¶ Нет encryption key. Credentials не расшифруются после восстановления. Backup лежит на том же VPS. При потере диска исчезает и сайт, и копия. Не проверяется размер архива. Можно месяцами загружать пустой dump. Retention бесконечный. Bucket растёт и хранит лишние персональные данные. Restore не тестировался. Ошибка обнаружится только в аварии. Полезные ссылки и документация ¶ Смотрите также: Backup self-hosted n8n , PostgreSQL backup/restore , ENV-переменные n8n , Telegram-алерт об ошибках . Документация: Docker Compose , Docker volumes backup/restore , S3 PutObject . Критерии готовности ¶ PostgreSQL dump создаётся в формате, пригодном для restore. Workflow JSON экспортируется отдельно от базы. N8N_ENCRYPTION_KEY сохранён вне VPS. Архив уходит в S3-compatible storage с retention. Restore-test выполняется регулярно и имеет владельца. Нужен backup, которому можно доверять? Nodbot настроит backup и restore-test для self-hosted n8n: PostgreSQL, workflows, S3, алерты и runbook восстановления. Настроить backup

## Test payload

```json
{
  "backup_name": "n8n-prod-nightly",
  "postgres_container": "n8n-postgres-1",
  "n8n_container": "n8n-app-1",
  "database": "n8n",
  "s3_bucket": "s3://company-backups/n8n/prod",
  "retention_days": 30,
  "restore_test": true
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const now = new Date();
const stamp = now.toISOString().replace(/[:.]/g, '-');
const name = String(src.backup_name ?? 'n8n-prod').replace(/[^a-z0-9_-]/gi, '-').toLowerCase();
const retentionDays = Number(src.retention_days ?? 30);
if (retentionDays < 7) throw new Error('Retention must be at least 7 days for production n8n');

return [{
  json: {
    backup_id: `${name}-${stamp}`,
    pg_file: `/tmp/${name}-${stamp}.pgdump`,
    workflows_file: `/tmp/${name}-${stamp}-workflows.json`,
    archive_file: `/tmp/${name}-${stamp}.tar.gz`,
    s3_prefix: String(src.s3_bucket ?? '').replace(/\/$/, ''),
    retention_days: retentionDays,
    restore_test_required: src.restore_test !== false,
    labels: { app: 'n8n', type: 'backup', environment: 'production' }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - n8n Docker Compose backup to S3",
  "nodes": [
    { "name": "Schedule nightly", "type": "n8n-nodes-base.scheduleTrigger", "purpose": "Запустить backup по расписанию" },
    { "name": "Prepare backup id", "type": "n8n-nodes-base.code", "purpose": "Собрать имена файлов и retention" },
    { "name": "Run pg_dump", "type": "n8n-nodes-base.ssh", "purpose": "Снять PostgreSQL dump с Docker host" },
    { "name": "Export workflows", "type": "n8n-nodes-base.ssh", "purpose": "Экспортировать workflows" },
    { "name": "Upload to S3", "type": "n8n-nodes-base.httpRequest", "purpose": "Загрузить архив в S3-compatible storage" },
    { "name": "Notify result", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить статус backup и restore-test" }
  ],
  "connections": "Schedule → Prepare → pg_dump/export → S3 upload → Notify"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Error Workflow в n8n: Telegram-алерт | Nodbot"
source_url: "https://nodbot.ru/workflows/error-workflow-telegram-alert/"
canonical_url: "https://nodbot.ru/workflows/error-workflow-telegram-alert/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 972
---

# Error Workflow в n8n: Telegram-алерт с severity, дедупликацией и runbook

## AI summary

AI-friendly Problem/Solution-мануал: как настроить Error Workflow в n8n, чтобы Telegram получал полезный алерт с workflow name, execution_id, error node, severity, dedupe key и ссылкой на runbook, а не поток одинаковых сообщений.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить безопасность/API/backup, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему failed execution в n8n теряется без Error Workflow
- Архитектура Error Workflow для Telegram-алертов
- Контракт данных Error Trigger
- Code Node: severity, dedupe key и короткое сообщение
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка Error Workflow в n8n
- Тесты алертов, runbook и anti-spam
- Production-риски алертинга
- Полезные ссылки и документация
- Критерии готовности

## Key topics

- n8n Error Workflow
- Telegram alert
- failed execution
- severity
- dedupe key
- runbook

## Source outline

Error Workflow в n8n: Telegram-алерт с severity, дедупликацией и runbook ¶ Обновлено: 2026-05-30 AI summary: AI-friendly Problem/Solution-мануал: как настроить Error Workflow в n8n, чтобы Telegram получал полезный алерт с workflow name, execution_id, error node, severity, dedupe key и ссылкой на runbook, а не поток одинаковых сообщений. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, подключите Telegram credential и назначьте его Error Workflow для production-сценариев. Содержание Проблема: почему failed execution в n8n теряется без Error Workflow Архитектура Error Workflow для Telegram-алертов Контракт данных Error Trigger Code Node: severity, dedupe key и короткое сообщение Готовый workflow JSON: скачать и импортировать Пошаговая настройка Error Workflow в n8n Тесты алертов, runbook и anti-spam Production-риски алертинга Полезные ссылки и документация Критерии готовности Проблема: failed execution в n8n часто замечают только тогда, когда менеджер сообщает, что лид не попал в CRM, счёт не обновился или клиент не получил письмо. Логи есть, но команда не видит их в рабочем канале. Решение: отдельный Error Workflow с Telegram-алертом, severity, dedupe key и ссылкой на runbook. Это не “прислать красное сообщение”, а минимальная система инцидентов для автоматизации продаж, CRM и платежных workflow. Хороший алерт короткий, дедуплицированный и ведёт прямо к execution и runbook. Проблема: почему failed execution в n8n теряется без Error Workflow ¶ Вручную проверять executions невозможно: ошибка может случиться ночью, в выходной или после обновления credential. Если workflow связан с оплатами, заявками или SLA поддержки, “увидим завтра” превращается в потерянные деньги. Error Workflow в n8n позволяет централизовать реакцию на сбой и не добавлять Telegram-ноду в каждый сценарий отдельно. Но алерты без severity быстро превращаются в шум. Команда должна отличать временный timeout от сломанного OAuth, а повторяющиеся 429 не должны засыпать чат сотней одинаковых сообщений. Архитектура Error Workflow для Telegram-алертов ¶ Нода Роль Что проверить Error Trigger Получает данные failed execution Workflow назначен как Error Workflow Classify severity Собирает severity и dedupe key Правила для 401/403/429/timeout Check dedupe Подавляет повтор одинаковых ошибок TTL, unique key, reset после recovery Send Telegram alert Отправляет понятный алерт chat_id, parse mode, лимит длины Incident log Пишет событие в Notion/Jira/CRM Не хранить токены и полный stack trace Контракт данных Error Trigger ¶ Error Trigger отдаёт контекст выполнения: workflow, node, execution URL и сообщение ошибки. Для теста можно использовать такой payload через отдельный test webhook или pin data. { "execution": { "id": "84721", "url": "https://n8n.example.com/execution/84721" }, "workflow": { "id": "crm-sync", "name": "CRM sync from webhook" }, "node": { "name": "Update CRM deal", "type": "n8n-nodes-base.httpRequest" }, "error": { "message": "429 Too Many Requests", "stack": "NodeApiError: rate limit" }, "lastNodeExecuted": "Update CRM deal", "mode": "trigger" } Code Node: severity, dedupe key и короткое сообщение ¶ Code Node ниже делает алерт полезным: классифицирует severity, нормализует похожие ошибки в один dedupe key и собирает короткий текст для Telegram. const e = $json; const workflow = e.workflow?.name ?? 'Unknown workflow'; const executionId = e.execution?.id ?? 'unknown'; const node = e.node?.name ?? e.lastNodeExecuted ?? 'unknown node'; const message = String(e.error?.message ?? 'Unknown error'); let severity = 'warning'; if (/401|403|auth|credential/i.test(message)) severity = 'critical'; if (/payment|invoice|production|crm/i.test(workflow + ' ' + message)) severity = 'critical'; if (/429|timeout|ETIMEDOUT|ECONNRESET/i.test(message)) severity = 'warning'; const dedupeKey = `n8n-error:${workflow}:${node}:${message.replace(/\d+/g, '#').slice(0, 120)}`; const runbookUrl = `https://nodbot.ru/runbooks/n8n-error-workflow/#${encodeURIComponent(workflow.toLowerCase().replace(/\s+/g, '-'))}`; const text = [ `🚨 n8n ${severity.toUpperCase()}`, `Workflow: ${workflow}`, `Node: ${node}`, `Execution: ${executionId}`, `Error: ${message.slice(0, 500)}`, `Runbook: ${runbookUrl}` ].join(' '); return [{ json: { severity, dedupe_key: dedupeKey, telegram_text: text, execution_url: e.execution?.url, runbook_url: runbookUrl } }]; Почему нужен dedupe key Если внешний API отвечает 429 десять минут подряд, команда должна получить один инцидент с обновлением, а не сотню сообщений. Dedupe key можно хранить в Postgres, Redis или Google Sheets, но для production лучше durable storage. Готовый workflow JSON: скачать и импортировать ¶ Полный workflow JSON доступен для импорта. Внутри оставлены placeholder credentials для Telegram и storage-ноды. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - n8n Error Workflow Telegram alert", "nodes": [ { "name": "Error Trigger", "type": "n8n-nodes-base.errorTrigger", "purpose": "Получить failed execution" }, { "name": "Classify severity", "type": "n8n-nodes-base.code", "purpose": "Собрать severity, dedupe_key и runbook URL" }, { "name": "Check dedupe", "type": "n8n-nodes-base.postgres", "purpose": "Не слать одинаковый алерт каждую минуту" }, { "name": "Send Telegram alert", "type": "n8n-nodes-base.telegram", "purpose": "Отправить короткий диагностический алерт" }, { "name": "Create incident comment", "type": "n8n-nodes-base.httpRequest", "purpose": "Опционально записать событие в CRM/Notion/Jira" } ], "connections": "Error Trigger → Classify severity → Check dedupe → Telegram → Incident log" } Пошаговая настройка Error Workflow в n8n ¶ Создайте Telegram bot и добавьте его в рабочий чат инцидентов. Импортируйте workflow JSON и замените Telegram credential. Настройте Postgres/Redis dedupe storage с TTL. Назначьте этот workflow как Error Workflow для production-сценариев n8n. Создайте runbook: кто отвечает, что проверить и как откатить изменение. Тесты алертов, runbook и anti-spam ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/test-error-workflow" -H "Content-Type: application/json" --data @error-workflow-telegram-alert-payload.json Дополнительно принудительно сломайте тестовый workflow через Stop And Error node. В Telegram должны прийти workflow name, node, execution_id, severity и ссылка на runbook. Production-риски алертинга ¶ Один общий чат для всего. Critical-ошибки тонут в информационных уведомлениях. Нет ссылки на execution. Инженер тратит время на поиск нужного запуска. Stack trace целиком в Telegram. Можно случайно раскрыть токены и персональные данные. Нет dedupe. Один сбой внешнего API создаёт лавину сообщений. Error Workflow не назначен. Шаблон есть, но production-сценарии его не используют. Полезные ссылки и документация ¶ Смотрите также: Retry и DLQ для HTTP Request , Проверка подписи webhook , ENV-переменные n8n . Официальная документация: n8n error handling , Error Trigger node , Telegram Bot API . Критерии готовности ¶ Любой failed production workflow отправляет диагностический алерт. В сообщении есть execution URL, workflow name, node и короткая ошибка. Повторяющиеся ошибки дедуплицируются. Critical-ошибки отделены от warning. У каждого critical-сценария есть runbook и ответственный. Нужно, чтобы n8n перестал падать незаметно? Nodbot настроит Error Workflow, Telegram/Jira алерты, retry, DLQ и runbook-и для ваших production-автоматизаций. Настроить мониторинг

## Test payload

```json
{
  "execution": { "id": "84721", "url": "https://n8n.example.com/execution/84721" },
  "workflow": { "id": "crm-sync", "name": "CRM sync from webhook" },
  "node": { "name": "Update CRM deal", "type": "n8n-nodes-base.httpRequest" },
  "error": { "message": "429 Too Many Requests", "stack": "NodeApiError: rate limit" },
  "lastNodeExecuted": "Update CRM deal",
  "mode": "trigger"
}
```

## Key implementation snippet

```javascript
const e = $json;
const workflow = e.workflow?.name ?? 'Unknown workflow';
const executionId = e.execution?.id ?? 'unknown';
const node = e.node?.name ?? e.lastNodeExecuted ?? 'unknown node';
const message = String(e.error?.message ?? 'Unknown error');

let severity = 'warning';
if (/401|403|auth|credential/i.test(message)) severity = 'critical';
if (/payment|invoice|production|crm/i.test(workflow + ' ' + message)) severity = 'critical';
if (/429|timeout|ETIMEDOUT|ECONNRESET/i.test(message)) severity = 'warning';

const dedupeKey = `n8n-error:${workflow}:${node}:${message.replace(/\d+/g, '#').slice(0, 120)}`;
const runbookUrl = `https://nodbot.ru/runbooks/n8n-error-workflow/#${encodeURIComponent(workflow.toLowerCase().replace(/\s+/g, '-'))}`;
const text = [
  `🚨 n8n ${severity.toUpperCase()}`,
  `Workflow: ${workflow}`,
  `Node: ${node}`,
  `Execution: ${executionId}`,
  `Error: ${message.slice(0, 500)}`,
  `Runbook: ${runbookUrl}`
].join('
');

return [{ json: { severity, dedupe_key: dedupeKey, telegram_text: text, execution_url: e.execution?.url, runbook_url: runbookUrl } }];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - n8n Error Workflow Telegram alert",
  "nodes": [
    { "name": "Error Trigger", "type": "n8n-nodes-base.errorTrigger", "purpose": "Получить failed execution" },
    { "name": "Classify severity", "type": "n8n-nodes-base.code", "purpose": "Собрать severity, dedupe_key и runbook URL" },
    { "name": "Check dedupe", "type": "n8n-nodes-base.postgres", "purpose": "Не слать одинаковый алерт каждую минуту" },
    { "name": "Send Telegram alert", "type": "n8n-nodes-base.telegram", "purpose": "Отправить короткий диагностический алерт" },
    { "name": "Create incident comment", "type": "n8n-nodes-base.httpRequest", "purpose": "Опционально записать событие в CRM/Notion/Jira" }
  ],
  "connections": "Error Trigger → Classify severity → Check dedupe → Telegram → Incident log"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "GigaChat и n8n: черновики ответов поддержки | Nodbot"
source_url: "https://nodbot.ru/workflows/gigachat-support-draft/"
canonical_url: "https://nodbot.ru/workflows/gigachat-support-draft/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 959
---

# GigaChat + n8n для поддержки: черновик ответа без утечки данных

## AI summary

Практический workflow GigaChat + n8n для поддержки: принять обращение, удалить лишние персональные данные, получить черновик ответа, проверить риск-флаги и передать оператору на review.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему LLM-ответ поддержки нельзя отправлять напрямую
- Архитектура workflow GigaChat + n8n для support draft
- Контракт входного обращения
- Code Node для очистки данных и prompt-контракта
- Готовый workflow JSON
- Пошаговая настройка GigaChat API и review-процесса
- Тесты перед production
- Production-риски LLM в поддержке
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- GigaChat API
- support draft
- PII masking
- n8n HTTP Request
- human review

## Source outline

GigaChat + n8n для поддержки: черновик ответа без утечки данных ¶ Обновлено: 2026-05-30 AI summary: Практический workflow GigaChat + n8n для поддержки: принять обращение, удалить лишние персональные данные, получить черновик ответа, проверить риск-флаги и передать оператору на review. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему LLM-ответ поддержки нельзя отправлять напрямую Архитектура workflow GigaChat + n8n для support draft Контракт входного обращения Code Node для очистки данных и prompt-контракта Готовый workflow JSON Пошаговая настройка GigaChat API и review-процесса Тесты перед production Production-риски LLM в поддержке Полезные ссылки и смежные workflow Критерии готовности Проблема: LLM может быстро подготовить ответ, но в поддержке ошибка по оплате, возврату или персональным данным превращается в риск для компании. Решение: n8n должен использовать GigaChat как генератор черновика: сначала маскировать данные, затем получить draft, проверить риск-флаги и передать оператору на review. Workflow ускоряет оператора, но не отправляет LLM-ответ клиенту напрямую. Проблема: почему LLM-ответ поддержки нельзя отправлять напрямую ¶ GigaChat API удобно использовать для черновиков ответов на русском языке, но поддержка — это зона с повышенным риском. В обращении могут быть телефон, email, номер заказа, спор по оплате, требование возврата или юридическая формулировка. Если автоматизация поддержки сразу отправит LLM-ответ клиенту, компания рискует дать неверное обещание или раскрыть лишние данные. Правильный сценарий — support draft: n8n принимает обращение, маскирует персональные данные, собирает prompt с ограничениями, получает черновик от GigaChat и отправляет его оператору на review. Это ускоряет поддержку, но оставляет ответственность и финальную проверку за человеком. Архитектура workflow GigaChat + n8n для support draft ¶ Нода Роль Что проверить Webhook ticket input Получает обращение из CRM/email/helpdesk ticket_id, channel, текст клиента Sanitize and build prompt Маскирует PII и собирает prompt телефон, email, карта, лишние данные Call GigaChat API Запрашивает черновик Bearer token, model, timeout, retries Fact and risk guard Проверяет риск-флаги оплата, возврат, договор, доступ Send draft to operator Отправляет черновик человеку кнопки approve/edit, ссылка на тикет Контракт входного обращения ¶ { "ticket_id": "SUP-10492", "channel": "email", "customer_text": "Здравствуйте. Я оплатил заказ 10492, но доступ не открылся. Телефон +7 916 123-45-67. Что делать?", "customer_name": "Иван", "priority": "high", "kb_articles": [ "https://example.ru/help/payment-access", "https://example.ru/help/refund-policy" ], "operator_chat_id": "-1001234567890" } В payload желательно передавать ссылки на статьи базы знаний. Тогда GigaChat получает не только вопрос клиента, но и ограниченный контекст, по которому оператор сможет проверить факты. Code Node для очистки данных и prompt-контракта ¶ const src = $json.body ?? $json; const raw = String(src.customer_text ?? '').trim(); if (!raw) throw new Error('Empty support request'); const masked = raw .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/ig, '[email]') .replace(/\+?\d[\d\s().-]{8,}\d/g, '[phone]') .replace(/\d{12,19}/g, '[possible_card]'); const risky = /(возврат|договор|суд|претенз|персональн|карта|паспорт|доступ|оплат)/i.test(raw); const prompt = `Ты помощник службы поддержки. Подготовь черновик ответа, не обещай возврат или компенсацию без проверки. Если фактов не хватает, задай уточняющий вопрос. Обращение клиента: ${masked}`; return [{ json: { ticket_id: src.ticket_id, channel: src.channel ?? 'unknown', sanitized_text: masked, risky, gigachat_request: { model: 'GigaChat', messages: [ { role: 'system', content: 'Готовь только черновик для оператора, не финальный ответ клиенту.' }, { role: 'user', content: prompt } ], temperature: 0.2 }, review_required: true } }]; Зачем маскировать данные до LLM-запроса Для черновика ответа модели обычно не нужен полный телефон, email или номер карты. Чем меньше персональных данных уходит во внешний API, тем проще контролировать безопасность и соответствие внутренним правилам. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - GigaChat support draft with PII masking", "nodes": [ { "name": "Webhook ticket input", "type": "n8n-nodes-base.webhook", "purpose": "Принять обращение из email, CRM или helpdesk" }, { "name": "Sanitize and build prompt", "type": "n8n-nodes-base.code", "purpose": "Замаскировать телефон/email/карты и собрать prompt" }, { "name": "Call GigaChat API", "type": "n8n-nodes-base.httpRequest", "purpose": "Получить черновик ответа от GigaChat" }, { "name": "Fact and risk guard", "type": "n8n-nodes-base.code", "purpose": "Проверить risky flags, ссылки на KB и полноту ответа" }, { "name": "Send draft to operator", "type": "n8n-nodes-base.telegram", "purpose": "Отправить черновик на review оператору" } ], "connections": "Webhook → Sanitize → GigaChat API → Guard → Operator review" } Пошаговая настройка GigaChat API и review-процесса ¶ Получите доступ к GigaChat API и настройте credential/ENV для токена. Подключите источник обращений: email, CRM, Bitrix24, amoCRM или helpdesk. Добавьте Code Node для PII masking до запроса к модели. Соберите prompt-контракт: черновик, без обещаний, с уточняющими вопросами при нехватке фактов. Отправляйте результат оператору, а не клиенту напрямую. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/gigachat-support-draft" \ -H "Content-Type: application/json" \ --data @gigachat-support-draft-payload.json Проверьте тикет с оплатой, тикет с персональными данными, пустое обращение, запрос на возврат, длинное письмо и отсутствие KB-ссылок. Workflow должен маскировать данные, ставить risk flag и не выпускать ответ без review. Production-риски LLM в поддержке ¶ LLM отправляет финальный ответ. Для чувствительной поддержки используйте только draft + review. PII уходит в API без фильтра. Маскируйте телефон, email, карты и лишние идентификаторы. Нет проверки фактов. Черновик должен ссылаться на KB или требовать уточнения. Токен GigaChat попал в execution. Храните credentials в ENV/credential store и не логируйте headers. Нет лимитов и fallback. При 401/429/timeout оператор должен получить понятную ошибку, а не молчание. Полезные ссылки и смежные workflow ¶ См. также Telegram AI-бот с approval , RAG FAQ bot на Qdrant , уведомления об ошибках и права AI-агентов . Официальные документы: GigaChat REST API и n8n HTTP Request . Оператор получает маскированный текст, риск-флаги и черновик, а не автоматический ответ клиенту. Критерии готовности ¶ Телефон, email и похожие на карту значения маскируются до LLM-запроса. GigaChat возвращает черновик, а не финальный ответ клиенту. В рискованных темах включается обязательный human review. Ошибки API и лимиты уходят в alert. Оператор видит ссылку на тикет, исходный текст и KB-контекст. Хотите ускорить поддержку без утечек данных? Nodbot настроит GigaChat support draft: PII masking, prompt-контракт, review, SLA, мониторинг ошибок и интеграцию с вашей CRM/helpdesk. Настроить support draft

## Test payload

```json
{
  "ticket_id": "SUP-10492",
  "channel": "email",
  "customer_text": "Здравствуйте. Я оплатил заказ 10492, но доступ не открылся. Телефон +7 916 123-45-67. Что делать?",
  "customer_name": "Иван",
  "priority": "high",
  "kb_articles": [
    "https://example.ru/help/payment-access",
    "https://example.ru/help/refund-policy"
  ],
  "operator_chat_id": "-1001234567890"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const raw = String(src.customer_text ?? '').trim();
if (!raw) throw new Error('Empty support request');

const masked = raw
  .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/ig, '[email]')
  .replace(/\+?\d[\d\s().-]{8,}\d/g, '[phone]')
  .replace(/\d{12,19}/g, '[possible_card]');

const risky = /(возврат|договор|суд|претенз|персональн|карта|паспорт|доступ|оплат)/i.test(raw);
const prompt = `Ты помощник службы поддержки. Подготовь черновик ответа, не обещай возврат или компенсацию без проверки. Если фактов не хватает, задай уточняющий вопрос.

Обращение клиента:
${masked}`;

return [{
  json: {
    ticket_id: src.ticket_id,
    channel: src.channel ?? 'unknown',
    sanitized_text: masked,
    risky,
    gigachat_request: {
      model: 'GigaChat',
      messages: [
        { role: 'system', content: 'Готовь только черновик для оператора, не финальный ответ клиенту.' },
        { role: 'user', content: prompt }
      ],
      temperature: 0.2
    },
    review_required: true
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - GigaChat support draft with PII masking",
  "nodes": [
    {
      "name": "Webhook ticket input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять обращение из email, CRM или helpdesk"
    },
    {
      "name": "Sanitize and build prompt",
      "type": "n8n-nodes-base.code",
      "purpose": "Замаскировать телефон/email/карты и собрать prompt"
    },
    {
      "name": "Call GigaChat API",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Получить черновик ответа от GigaChat"
    },
    {
      "name": "Fact and risk guard",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить risky flags, ссылки на KB и полноту ответа"
    },
    {
      "name": "Send draft to operator",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Отправить черновик на review оператору"
    }
  ],
  "connections": "Webhook → Sanitize → GigaChat API → Guard → Operator review"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Gmail вложения в Яндекс Диск через n8n | Nodbot"
source_url: "https://nodbot.ru/workflows/gmail-attachments-to-yandex-disk/"
canonical_url: "https://nodbot.ru/workflows/gmail-attachments-to-yandex-disk/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1009
---

# Gmail → Яндекс Диск через n8n: сохранение вложений, фильтры и защита от дублей

## AI summary

AI-friendly Problem/Solution-мануал: как автоматически сохранять вложения Gmail на Яндекс Диск через n8n, фильтровать письма, раскладывать файлы по папкам, не дублировать вложения и уведомлять команду.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API/файлы/мониторинг, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему вложения из Gmail теряются в переписке
- Архитектура workflow Gmail → Яндекс Диск
- Контракт данных письма и вложений
- Code Node: путь файла, dedupe key и безопасное имя
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка Gmail, n8n и Яндекс Диска
- Тесты вложений, фильтров и повторов
- Production-риски файловой автоматизации
- Полезные ссылки и документация
- Критерии готовности

## Key topics

- Gmail attachments
- Yandex Disk
- n8n binary data
- deduplication
- file automation
- email workflow

## Source outline

Gmail → Яндекс Диск через n8n: сохранение вложений, фильтры и защита от дублей ¶ Обновлено: 2026-05-30 AI summary: AI-friendly Problem/Solution-мануал: как автоматически сохранять вложения Gmail на Яндекс Диск через n8n, фильтровать письма, раскладывать файлы по папкам, не дублировать вложения и уведомлять команду. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему вложения из Gmail теряются в переписке Архитектура workflow Gmail → Яндекс Диск Контракт данных письма и вложений Code Node: путь файла, dedupe key и безопасное имя Готовый workflow JSON: скачать и импортировать Пошаговая настройка Gmail, n8n и Яндекс Диска Тесты вложений, фильтров и повторов Production-риски файловой автоматизации Полезные ссылки и документация Критерии готовности Проблема: вложения из Gmail легко теряются в переписке, скачиваются вручную и дублируются в разных папках. Это особенно больно для счетов, актов, договоров и документов от поставщиков. Решение: сделать workflow Gmail → Яндекс Диск через n8n: отфильтровать письма, извлечь вложения, собрать безопасный путь, проверить dedupe key и отправить уведомление команде. Файлы сохраняются с понятной структурой папок и ключом дедупликации. Проблема: почему вложения из Gmail теряются в переписке ¶ Счета, акты, коммерческие предложения и закрывающие документы часто приходят в Gmail как вложения. Пока их вручную скачивает бухгалтер или менеджер, часть файлов остаётся в цепочках писем, попадает в разные папки или загружается дважды. Автоматизация через n8n решает эту боль: письмо фильтруется, вложение сохраняется на Яндекс Диск, а команда получает ссылку и понятный статус. Страница закрывает конкретный интент “Gmail вложения в Яндекс Диск через n8n”, а не общую тему email automation. Здесь важны фильтры, структура папок, безопасные имена файлов и повторная обработка одного письма. Архитектура workflow Gmail → Яндекс Диск ¶ Нода Роль Что проверить Gmail trigger Получает новые письма Query, label, unread/read policy Extract attachments Забирает binary файлы Размер, MIME type, несколько вложений Build path Создаёт путь на Яндекс Диске Дата, отправитель, безопасное имя Check dedupe Не грузит файл повторно message_id + filename + size Upload to Yandex Disk Сохраняет файл OAuth/WebDAV, overwrite policy Контракт данных письма и вложений ¶ Для тестов удобно передавать сокращённый JSON письма. В реальном workflow Gmail node отдаст binary data, но бизнес-логика пути и дедупликации остаётся такой же. { "message_id": "18f4a9d7c2", "from": "supplier@example.ru", "subject": "Счет и акт за май", "date": "2026-05-30T09:15:00Z", "attachments": [ { "filename": "invoice-10492.pdf", "mimeType": "application/pdf", "size": 184920 }, { "filename": "act-10492.pdf", "mimeType": "application/pdf", "size": 122400 } ], "folder": "suppliers" } Code Node: путь файла, dedupe key и безопасное имя ¶ Code Node ниже превращает письмо в массив файлов для upload. Он чистит символы, которые ломают пути, и формирует dedupe key, чтобы повторный запуск не создавал копии вида invoice (1).pdf . const msg = $json; const messageId = String(msg.message_id ?? msg.id ?? '').trim(); if (!messageId) throw new Error('Gmail message_id is required for dedupe'); const from = String(msg.from ?? 'unknown').replace(/[<>:"/\|?*]+/g, '_').slice(0, 80); const subject = String(msg.subject ?? 'no-subject').replace(/[<>:"/\|?*]+/g, '_').slice(0, 100); const date = new Date(msg.date ?? Date.now()).toISOString().slice(0, 10); const baseFolder = String(msg.folder ?? 'inbox').replace(/[^A-Za-zА-Яа-я0-9._-]+/g, '_'); const attachments = Array.isArray(msg.attachments) ? msg.attachments : []; return attachments.map((file, index) => { const original = String(file.filename ?? `attachment-${index + 1}`).replace(/[<>:"/\|?*]+/g, '_'); return { json: { message_id: messageId, dedupe_key: `gmail:${messageId}:${original}:${file.size ?? 0}`, yandex_path: `/n8n/${baseFolder}/${date}/${from}/${original}`, original_filename: original, mime_type: file.mimeType ?? 'application/octet-stream', size: file.size ?? 0, title: `${subject} — ${original}` }}; }); Как выбрать фильтр Gmail Начните с узкого query: has:attachment from:supplier@example.ru newer_than:7d . После проверки расширяйте фильтр по label или домену. Не запускайте workflow сразу на всю историю ящика. Готовый workflow JSON: скачать и импортировать ¶ В архив добавлены workflow JSON и payload. После импорта замените Gmail credential, токен Яндекс Диска, базовую папку и правило фильтрации писем. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Gmail attachments to Yandex Disk", "nodes": [ { "name": "Gmail trigger", "type": "n8n-nodes-base.gmailTrigger", "purpose": "Получать новые письма по фильтру" }, { "name": "Extract attachments", "type": "n8n-nodes-base.gmail", "purpose": "Забрать binary вложения" }, { "name": "Build Yandex path Code", "type": "n8n-nodes-base.code", "purpose": "Собрать путь, имя файла и dedupe key" }, { "name": "Upload to Yandex Disk", "type": "n8n-nodes-base.httpRequest", "purpose": "Загрузить файл через WebDAV/REST" }, { "name": "Notify result", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить о сохранении или ошибке" } ], "connections": "Gmail → Extract → Build path → Upload → Notify" } Пошаговая настройка Gmail, n8n и Яндекс Диска ¶ Создайте отдельный Gmail label для писем, которые нужно обрабатывать. Настройте Gmail trigger или IMAP Read node с фильтром has:attachment . Добавьте Code Node для безопасного имени файла и структуры папок. Подключите upload на Яндекс Диск через WebDAV или REST API. Сохраняйте dedupe key в таблицу/БД и отправляйте короткий Telegram-отчёт. Тесты вложений, фильтров и повторов ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/gmail-attachments-to-yandex-disk" -H "Content-Type: application/json" --data @gmail-attachments-to-yandex-disk-payload.json Письмо с двумя PDF должно создать два файла в одной папке. Повторная обработка того же message_id не должна грузить дубли. Файл с кириллицей и пробелами должен получить безопасный путь. Письмо без вложений должно завершаться без ошибки и без алерта. Ошибка upload должна попадать в Error Workflow или Telegram alert. Production-риски файловой автоматизации ¶ Workflow обрабатывает всю историю. Можно случайно загрузить тысячи старых вложений и упереться в лимиты. Overwrite включён без контроля. Новый файл может затереть старый документ с тем же именем. Нет дедупликации. Gmail trigger или ручной retry создаёт копии документов. Токен Яндекс Диска в тексте ноды. Храните секреты в credentials/ENV. Нет политики персональных данных. Вложения могут содержать договоры, паспорта и реквизиты. Полезные ссылки и документация ¶ Смотрите также: Error Workflow с Telegram-алертом , Безопасное хранение ENV , Retry и DLQ для HTTP Request . Официальная документация: Gmail API guides , Yandex Disk API , n8n binary data . Критерии готовности ¶ Фильтр Gmail выбирает только нужные письма с вложениями. Каждый файл получает предсказуемый путь: категория, дата, отправитель, имя. Повторный запуск по тому же письму не создаёт дубль. Ошибки upload видны в Telegram или Error Workflow. Команда знает, какие типы файлов можно хранить на Яндекс Диске и кто владелец папки. Нужно разобрать почту без ручной рутины? Nodbot настроит Gmail/IMAP → Яндекс Диск, фильтры, dedupe, алерты и безопасное хранение вложений под вашу структуру документов. Автоматизировать вложения

## Test payload

```json
{
  "message_id": "18f4a9d7c2",
  "from": "supplier@example.ru",
  "subject": "Счет и акт за май",
  "date": "2026-05-30T09:15:00Z",
  "attachments": [
    { "filename": "invoice-10492.pdf", "mimeType": "application/pdf", "size": 184920 },
    { "filename": "act-10492.pdf", "mimeType": "application/pdf", "size": 122400 }
  ],
  "folder": "suppliers"
}
```

## Key implementation snippet

```javascript
const msg = $json;
const messageId = String(msg.message_id ?? msg.id ?? '').trim();
if (!messageId) throw new Error('Gmail message_id is required for dedupe');

const from = String(msg.from ?? 'unknown').replace(/[<>:"/\|?*]+/g, '_').slice(0, 80);
const subject = String(msg.subject ?? 'no-subject').replace(/[<>:"/\|?*]+/g, '_').slice(0, 100);
const date = new Date(msg.date ?? Date.now()).toISOString().slice(0, 10);
const baseFolder = String(msg.folder ?? 'inbox').replace(/[^A-Za-zА-Яа-я0-9._-]+/g, '_');

const attachments = Array.isArray(msg.attachments) ? msg.attachments : [];
return attachments.map((file, index) => {
  const original = String(file.filename ?? `attachment-${index + 1}`).replace(/[<>:"/\|?*]+/g, '_');
  return { json: {
    message_id: messageId,
    dedupe_key: `gmail:${messageId}:${original}:${file.size ?? 0}`,
    yandex_path: `/n8n/${baseFolder}/${date}/${from}/${original}`,
    original_filename: original,
    mime_type: file.mimeType ?? 'application/octet-stream',
    size: file.size ?? 0,
    title: `${subject} — ${original}`
  }};
});
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Gmail attachments to Yandex Disk",
  "nodes": [
    { "name": "Gmail trigger", "type": "n8n-nodes-base.gmailTrigger", "purpose": "Получать новые письма по фильтру" },
    { "name": "Extract attachments", "type": "n8n-nodes-base.gmail", "purpose": "Забрать binary вложения" },
    { "name": "Build Yandex path Code", "type": "n8n-nodes-base.code", "purpose": "Собрать путь, имя файла и dedupe key" },
    { "name": "Upload to Yandex Disk", "type": "n8n-nodes-base.httpRequest", "purpose": "Загрузить файл через WebDAV/REST" },
    { "name": "Notify result", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить о сохранении или ошибке" }
  ],
  "connections": "Gmail → Extract → Build path → Upload → Notify"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "n8n + Google Sheets: upsert строки по телефону | Nodbot"
source_url: "https://nodbot.ru/workflows/google-sheets-upsert-by-phone/"
canonical_url: "https://nodbot.ru/workflows/google-sheets-upsert-by-phone/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 998
---

# Google Sheets + n8n: upsert строки по телефону без дублей

## AI summary

Практический шаблон n8n для upsert в Google Sheets по телефону: нормализация номера, встроенный Append or Update Row, защита от дублей, тестовый payload и production-чеклист.

## Best used for

Материал помогает внедрить страницу как production-runbook: понять интент, проверить риски, сохранить owner и не смешивать тему с соседними сценариями.

## Key topics

- Когда нужен upsert, а не append
- Архитектура workflow
- Контракт входных данных
- Нормализация телефона в Code node
- Импортируемый workflow JSON
- Настройка Google Sheets
- Тесты на дубли
- Production-риски
- Критерий готовности

## Source outline

# Google Sheets + n8n: upsert строки по телефону без дублей [¶](#google-sheets-n8n-upsert-stroki-po-telefonu-bez-dubley "Permanent link")

Обновлено: 2026-05-30

Сохранить в мой план [Открыть мой план](/my-plan/)

**Шаблон для внедрения**

[Скачать workflow JSON](/assets/workflows/google-sheets-upsert-by-phone.json)[Скачать test payload](/assets/workflows/google-sheets-upsert-by-phone-payload.json)Скопировать curl

Используйте готовый JSON workflow как основу: после импорта замените Google credential, spreadsheetId, название листа и проверьте правило нормализации телефона на своих номерах.

**Задача workflow — не просто добавить лид в таблицу, а сохранить одну актуальную строку на один телефон.** Повторная заявка из формы, Telegram, VK, CRM или лендинга должна обновить существующую запись, а не создать дубль. Так менеджер видит чистую таблицу, а последующие автоматизации не отправляют повторные сообщения одному и тому же человеку.

![Схема workflow n8n для Google Sheets upsert по телефону](/assets/images/workflows/google-sheets-upsert-by-phone-graph.svg)

Схема потока: Webhook принимает заявку, Code нормализует телефон, Google Sheets делает append или update по колонке phone\_normalized, Webhook возвращает безопасный ответ.

## Когда нужен upsert, а не append [¶](#kogda-nuzhen-upsert-a-ne-append "Permanent link")

Append добавляет новую строку при каждом событии. Это удобно для журнала событий, но плохо для таблицы лидов: один и тот же клиент может появиться три раза, фильтры начинают врать, а интеграция с CRM получает неочевидные повторы.

Upsert работает иначе: workflow использует стабильный ключ, ищет существующую запись и либо обновляет её, либо добавляет новую строку. В российских продажах таким ключом часто удобнее делать телефон: email может быть разным, а номер нужен для звонка, WhatsApp, Telegram и CRM.

## Архитектура workflow [¶](#arhitektura-workflow "Permanent link")

| Нода | Роль | Что проверить |
| --- | --- | --- |
| Webhook input | принимает lead payload | метод POST, production URL, JSON body |
| Normalize phone | создаёт единый ключ | +7, 8, пробелы, скобки, пустые значения |
| Append or update lead row | пишет в Google Sheets | matching column: phone\_normalized |
| Respond to Webhook | возвращает технический ответ | без токенов, лишних персональных данных и сырого payload |

Базовый вариант использует встроенную операцию Google Sheets `Append or Update Row`. Ручная схема `Find row → IF → Update/Append` нужна, когда у вас есть сложные ветки: например, не обновлять источник первого лида, писать audit trail, отправлять alert при конфликте или проверять несколько ключей.

## Контракт входных данных [¶](#kontrakt-vhodnyh-dannyh "Permanent link")

Payload должен быть коротким и стабильным. Обязательный минимум — телефон. Остальные поля нужны для удобства менеджера и последующих интеграций: имя, email, источник, внешний id и время получения события.

```
{
  "phone": "+7 (999) 111-22-33",
  "name": "Сергей",
  "email": "sergey@example.ru",
  "source": "vk_lead_form",
  "external_id": "lead-58391",
  "received_at": "2026-05-30T10:00:00Z"
}
```

Если телефон пустой или не приводится к нормальному виду, workflow должен остановиться до записи. Не подставляйте фиктивные значения вроде `unknown`: такие строки потом невозможно дедуплицировать и опасно отправлять в CRM.

## Нормализация телефона в Code node [¶](#normalizatsiya-telefona-v-code-node "Permanent link")

Ключевой шаг — получить одинаковое значение из форматов `+7 (999) 111-22-33`, `8 999 111 22 33` и `9991112233`. Для российской базы лидов удобно хранить ключ в формате `+79991112233`.

```
const input = $json.body ?? $json;
const raw = String(input.phone ?? '').trim();
let digits = raw.replace(/\D/g, '');

if (digits.length === 11 && digits.startsWith('8')) {
  digits = `7${digits.slice(1)}`;
}
if (digits.length === 10) {
  digits = `7${digits}`;
}
if (!/^7\d{10}$/.test(digits)) {
  throw new Error(`Invalid phone: ${raw}`);
}

return [{
  json: {
    phone_raw: raw,
    phone_normalized: `+${digits}`,
    name: input.name ?? '',
    email: input.email ?? '',
    source: input.source ?? 'unknown',
    external_id: input.external_id ?? input.lead_id ?? '',
    first_seen_at: input.received_at ?? new Date().toISOString(),
    updated_at: new Date().toISOString(),
    update_count: Number(input.update_count ?? 0) + 1
  }
}];
```

Эта нода возвращает `phone_raw` для аудита и `phone_normalized` для поиска. В Google Sheets именно `phone_normalized` должен быть выбран как matching column. Если вы работаете с международными номерами, замените правило на библиотеку или отдельный справочник стран, а не расширяйте регулярку хаотично.

## Импортируемый workflow JSON [¶](#importiruemyy-workflow-json "Permanent link")

Полный JSON лежит в архиве и доступен по кнопке «Скачать workflow JSON». Ниже — сокращённая структура, чтобы сразу было видно, что это именно workflow n8n, а не только пример входного payload.

```
{
  "name": "Nodbot - n8n Google Sheets upsert by phone",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "httpMethod": "POST",
        "path": "google-sheets-upsert-by-phone",
        "responseMode": "responseNode"
      }
    },
    {
      "name": "Normalize phone",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "// full code is shown above in the article"
      }
    },
    {
      "name": "Append or update lead row",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": "YOUR_SPREADSHEET_ID",
        "sheetName": "Leads",
        "matchingColumns": [
          "phone_normalized"
        ]
      }
    },
    {
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook"
    }
  ],
  "connections": {
    "Webhook input": "Normalize phone → Append or update lead row → Respond to Webhook"
  }
}
```

После импорта откройте ноду Google Sheets, выберите credential, укажите spreadsheetId и лист `Leads`, затем обновите схему колонок. Если n8n не подтянул новые заголовки после изменения таблицы, заново выберите mapping mode и пересохраните ноду.

## Настройка Google Sheets [¶](#nastroyka-google-sheets "Permanent link")

1. Создайте отдельный production-лист, а не используйте тестовую таблицу с демо-данными.
2. Добавьте колонки `phone_raw`, `phone_normalized`, `name`, `email`, `source`, `external_id`, `first_seen_at`, `updated_at` и `update_count`.
3. Выдайте Google credential доступ только к нужной таблице, а не ко всему Drive аккаунта.
4. Не переименовывайте лист вручную после публикации workflow: лучше сначала изменить ноду, затем таблицу.

## Тесты на дубли [¶](#testy-na-dubli "Permanent link")

Один успешный запуск не доказывает готовность. Отправьте payload дважды: первый запуск должен создать строку, второй — обновить её по `phone_normalized`. Затем измените имя при том же телефоне и убедитесь, что новая строка не появилась.

```
curl -X POST "https://YOUR-N8N-DOMAIN/webhook/google-sheets-upsert-by-phone" \
  -H "Content-Type: application/json" \
  --data @google-sheets-upsert-by-phone-payload.json
```

Дополнительно проверьте номер в формате `8 999 111 22 33`, пустой телефон, лишние пробелы и повторный external\_id. Если тесты создают дубли, сначала смотрите matching column, потом нормализацию, затем права Google credential.

## Production-риски [¶](#production-riski "Permanent link")

* **Гонки при одновременных заявках.** Если два события с одним телефоном пришли почти одновременно, оба могут успеть создать строку. Для критичных сценариев используйте [Webhook + Postgres idempotency](/workflows/webhook-idempotency-to-postgres/).
* **Лимиты Google API.** Не запускайте массовый импорт через тот же workflow без batch-логики, retry и backoff.
* **Ручные правки таблицы.** Если менеджер удалил колонку или переименовал лист, нода начнёт падать или писать не туда.
* **Персональные данные в executions.** Ограничьте сохранение execution data и не логируйте полный payload без необходимости.
* **Смешение журнала и карточки лида.** Для истории событий заведите отдельный append-only лист, а этот workflow оставьте для актуального состояния клиента.

## Критерий готовности [¶](#kriteriy-gotovnosti-google-sheets-upsert "Permanent link")

Workflow можно включать в production, когда повторный payload обновляет строку, номер нормализуется одинаково, ошибки Google Sheets попадают в alert, таблица имеет владельца, а команда знает, где менять mapping. Для более строгой защиты от повторов используйте [Postgres-идемпотентность](/workflows/webhook-idempotency-to-postgres/), а для обработки временных ошибок — [retry и dead-letter queue](/workflows/retry-dlq-http-request/).


---

---
title: "Скрининг резюме HH через n8n и AI | Nodbot"
source_url: "https://nodbot.ru/workflows/hh-resume-screening/"
canonical_url: "https://nodbot.ru/workflows/hh-resume-screening/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1076
---

# Скрининг резюме HH через n8n: AI-оценка без автоотказов

## AI summary

Практический workflow для HR: взять резюме HH и критерии вакансии, извлечь только job-related факты, сформировать scoring с evidence, отправить спорные случаи рекрутеру и записать результат в ATS без автоматических отказов.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему AI-скрининг резюме HH нельзя делать как автоотказ
- Архитектура workflow для скрининга резюме
- Контракт входных данных: резюме, вакансия и критерии
- Code Node: нормализация критериев и prompt-контракт
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка HH, n8n и ATS
- Тесты перед production и проверка качества
- Production-риски HR automation и AI scoring
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- HH resume screening
- AI scoring
- human review
- ATS
- HeadHunter API

## Source outline

Скрининг резюме HH через n8n: AI-оценка без автоотказов ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для HR: взять резюме HH и критерии вакансии, извлечь только job-related факты, сформировать scoring с evidence, отправить спорные случаи рекрутеру и записать результат в ATS без автоматических отказов. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему AI-скрининг резюме HH нельзя делать как автоотказ Архитектура workflow для скрининга резюме Контракт входных данных: резюме, вакансия и критерии Code Node: нормализация критериев и prompt-контракт Готовый workflow JSON: скачать и импортировать Пошаговая настройка HH, n8n и ATS Тесты перед production и проверка качества Production-риски HR automation и AI scoring Полезные ссылки и смежные workflow Критерии готовности Проблема: AI-скрининг резюме может ускорить рекрутера, но при неправильной настройке превращается в непрозрачный автоотказ по неполным или чувствительным данным. Решение: workflow в n8n должен извлекать только job-related факты, сравнивать их с критериями вакансии, сохранять evidence и отправлять итог рекрутеру на review. AI готовит карточку, но финальное решение остается у рекрутера. Проблема: почему AI-скрининг резюме HH нельзя делать как автоотказ ¶ Скрининг резюме HH через n8n часто начинается с простой идеи: получить отклик, отправить текст резюме в AI, поставить балл и автоматически решить, подходит кандидат или нет. Для HR это опасный сценарий. Резюме может быть неполным, модель может ошибиться в опыте, а чувствительные признаки вообще не должны попадать в scoring. Правильный workflow не заменяет рекрутера. Он готовит структурированную карточку: совпадения с требованиями вакансии, недостающие факты, red flags, вопросы для интервью и объяснение оценки. Финальное решение остается у человека, а n8n отвечает за автоматизацию рутины, аудит и запись результата в ATS или CRM. Архитектура workflow для скрининга резюме ¶ Нода Роль Что проверить Webhook input Принимает resume_id, vacancy_id и критерии нет лишних персональных данных в payload Prepare criteria Разделяет must-have и nice-to-have запрещенные признаки не участвуют в scoring Fetch resume facts Получает факты резюме HH или ATS ссылка на исходник сохраняется для аудита AI scoring Сравнивает факты с критериями каждый балл имеет evidence Recruiter review gate Отправляет карточку человеку нет автоматического отказа Update ATS Записывает summary, score и вопросы статусы не ломают воронку найма Контракт входных данных: резюме, вакансия и критерии ¶ { "resume_id": "hh-resume-812345", "vacancy_id": "backend-nodejs-remote", "candidate": { "name": "Мария", "source": "hh.ru", "resume_url": "https://hh.ru/resume/xxxx" }, "vacancy_criteria": { "must_have": [ "Node.js от 3 лет", "PostgreSQL", "REST API", "опыт production support" ], "nice_to_have": [ "n8n", "Redis", "Docker" ], "exclude_from_scoring": [ "возраст", "пол", "семейное положение", "фото" ] }, "ats": { "candidate_id": "ats-1042", "pipeline": "backend-hiring" } } В payload важно передавать не “всё резюме целиком”, а ссылку или идентификатор источника, критерии вакансии и список признаков, которые запрещено использовать. Так скрипт n8n остается контролируемым, а HR-команда понимает, почему кандидат получил конкретный score. Code Node: нормализация критериев и prompt-контракт ¶ const input = $json.body ?? $json; const criteria = input.vacancy_criteria ?? {}; const mustHave = Array.isArray(criteria.must_have) ? criteria.must_have : []; const niceToHave = Array.isArray(criteria.nice_to_have) ? criteria.nice_to_have : []; const excluded = new Set((criteria.exclude_from_scoring ?? []).map(v => String(v).toLowerCase())); if (!input.resume_id || !input.vacancy_id) { throw new Error('resume_id and vacancy_id are required'); } const promptContract = { role: 'HR screening assistant', task: 'Compare only job-related facts from resume with vacancy criteria', forbidden_signals: [...excluded], output_schema: { score: '0-100', must_have_match: 'array with evidence', gaps: 'array with missing evidence', interview_questions: 'array', decision: 'shortlist | recruiter_review', confidence: 'low | medium | high' }, rule: 'Do not reject candidate automatically; send uncertain or negative cases to recruiter_review' }; return [{ json: { resume_id: input.resume_id, vacancy_id: input.vacancy_id, ats_candidate_id: input.ats?.candidate_id, must_have: mustHave, nice_to_have: niceToHave, prompt_contract: promptContract, review_required: true, audit_key: `hh:${input.vacancy_id}:${input.resume_id}` } }]; Почему evidence важнее общего score Число 82/100 само по себе не объясняет решение. Evidence показывает, какая строка резюме подтверждает навык, а где модель сделала предположение. Это помогает рекрутеру быстро проверить карточку и не превращает AI screening в черный ящик. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - HH resume screening with human review", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять resume_id, vacancy_id и критерии вакансии" }, { "name": "Prepare criteria and prompt", "type": "n8n-nodes-base.code", "purpose": "Нормализовать must-have/nice-to-have и запретить чувствительные признаки" }, { "name": "Fetch resume facts", "type": "n8n-nodes-base.httpRequest", "purpose": "Получить факты из HH/ATS или внутреннего парсера" }, { "name": "AI scoring", "type": "n8n-nodes-base.httpRequest", "purpose": "Сравнить факты с критериями и вернуть evidence" }, { "name": "Recruiter review gate", "type": "n8n-nodes-base.if", "purpose": "Не делать автоотказ; отправить карточку рекрутеру" }, { "name": "Update ATS", "type": "n8n-nodes-base.httpRequest", "purpose": "Записать score, summary и вопросы в ATS" } ], "connections": "Webhook → Criteria → Resume facts → AI scoring → Review gate → ATS" } Пошаговая настройка HH, n8n и ATS ¶ Опишите критерии вакансии до подключения AI: must-have, nice-to-have и недопустимые сигналы. Подключите источник резюме: HH API, ATS export, email с откликами или внутреннюю базу кандидатов. Добавьте Code Node для нормализации критериев и prompt-контракта. Настройте AI scoring так, чтобы он возвращал evidence, gaps и вопросы для интервью. Записывайте результат в ATS только после проверки человеком или с явным статусом `recruiter_review`. Тесты перед production и проверка качества ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/hh-resume-screening" \ -H "Content-Type: application/json" \ --data @hh-resume-screening-payload.json Проверьте сильное резюме, слабое резюме, неполное резюме, кандидата с нестандартным опытом и кейс без обязательного навыка. Негативные и спорные кейсы должны попадать на human review, а не создавать автоотказ. Production-риски HR automation и AI scoring ¶ Автоматический отказ. AI может помогать, но не должен самостоятельно закрывать кандидата без прозрачного правила. Скоринг по чувствительным признакам. Возраст, пол, фото и семейное положение не должны попадать в критерии. Нет evidence. Рекрутер не сможет проверить, откуда взялась оценка. Разные вакансии используют один prompt. Критерии должны быть привязаны к vacancy_id. История решений не хранится. Без audit_key сложно объяснить, почему карточка изменилась. Полезные ссылки и смежные workflow ¶ См. также GigaChat support draft , права AI-агентов и уведомления об ошибках . Официальные документы: HeadHunter API и n8n HTTP Request . Результат должен быть проверяемой карточкой для рекрутера, а не скрытым автоотказом. Критерии готовности ¶ Каждый score содержит evidence и gaps. Негативные решения уходят на human review. Запрещенные признаки исключены из prompt и scoring. Результат записывается в ATS с audit_key и ссылкой на исходное резюме. Ошибки API/AI не меняют статус кандидата молча. Нужен безопасный AI-скрининг резюме? Nodbot настроит HR workflow с критериями вакансии, evidence, human review, ATS-записью, audit trail и мониторингом ошибок. Обсудить HR workflow

## Test payload

```json
{
  "resume_id": "hh-resume-812345",
  "vacancy_id": "backend-nodejs-remote",
  "candidate": {
    "name": "Мария",
    "source": "hh.ru",
    "resume_url": "https://hh.ru/resume/xxxx"
  },
  "vacancy_criteria": {
    "must_have": [
      "Node.js от 3 лет",
      "PostgreSQL",
      "REST API",
      "опыт production support"
    ],
    "nice_to_have": [
      "n8n",
      "Redis",
      "Docker"
    ],
    "exclude_from_scoring": [
      "возраст",
      "пол",
      "семейное положение",
      "фото"
    ]
  },
  "ats": {
    "candidate_id": "ats-1042",
    "pipeline": "backend-hiring"
  }
}
```

## Key implementation snippet

```javascript
const input = $json.body ?? $json;
const criteria = input.vacancy_criteria ?? {};
const mustHave = Array.isArray(criteria.must_have) ? criteria.must_have : [];
const niceToHave = Array.isArray(criteria.nice_to_have) ? criteria.nice_to_have : [];
const excluded = new Set((criteria.exclude_from_scoring ?? []).map(v => String(v).toLowerCase()));

if (!input.resume_id || !input.vacancy_id) {
  throw new Error('resume_id and vacancy_id are required');
}

const promptContract = {
  role: 'HR screening assistant',
  task: 'Compare only job-related facts from resume with vacancy criteria',
  forbidden_signals: [...excluded],
  output_schema: {
    score: '0-100',
    must_have_match: 'array with evidence',
    gaps: 'array with missing evidence',
    interview_questions: 'array',
    decision: 'shortlist | recruiter_review',
    confidence: 'low | medium | high'
  },
  rule: 'Do not reject candidate automatically; send uncertain or negative cases to recruiter_review'
};

return [{
  json: {
    resume_id: input.resume_id,
    vacancy_id: input.vacancy_id,
    ats_candidate_id: input.ats?.candidate_id,
    must_have: mustHave,
    nice_to_have: niceToHave,
    prompt_contract: promptContract,
    review_required: true,
    audit_key: `hh:${input.vacancy_id}:${input.resume_id}`
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - HH resume screening with human review",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять resume_id, vacancy_id и критерии вакансии"
    },
    {
      "name": "Prepare criteria and prompt",
      "type": "n8n-nodes-base.code",
      "purpose": "Нормализовать must-have/nice-to-have и запретить чувствительные признаки"
    },
    {
      "name": "Fetch resume facts",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Получить факты из HH/ATS или внутреннего парсера"
    },
    {
      "name": "AI scoring",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Сравнить факты с критериями и вернуть evidence"
    },
    {
      "name": "Recruiter review gate",
      "type": "n8n-nodes-base.if",
      "purpose": "Не делать автоотказ; отправить карточку рекрутеру"
    },
    {
      "name": "Update ATS",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Записать score, summary и вопросы в ATS"
    }
  ],
  "connections": "Webhook → Criteria → Resume facts → AI scoring → Review gate → ATS"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Кросспостинг Instagram в Telegram через n8n | Nodbot"
source_url: "https://nodbot.ru/workflows/instagram-telegram-crosspost/"
canonical_url: "https://nodbot.ru/workflows/instagram-telegram-crosspost/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 957
---

# Кросспостинг Instagram в Telegram через n8n: посты без ручной публикации

## AI summary

Workflow для контент-команды: получить публикацию Instagram через Graph API или входной webhook, очистить caption, проверить дедупликацию, подготовить Telegram-сообщение с media_url и отправить его в канал без повторов.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему ручной кросспостинг Instagram в Telegram ломает контент-план
- Архитектура workflow Instagram → n8n → Telegram
- Контракт входных данных публикации
- Code Node: очистка caption, hashtags и dedupe key
- Готовый workflow JSON
- Пошаговая настройка Instagram Graph API и Telegram канала
- Тесты перед production
- Production-риски кросспостинга
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Instagram Graph API
- Telegram Bot API
- crossposting
- dedupe
- content automation

## Source outline

Кросспостинг Instagram в Telegram через n8n: посты без ручной публикации ¶ Обновлено: 2026-05-30 AI summary: Workflow для контент-команды: получить публикацию Instagram через Graph API или входной webhook, очистить caption, проверить дедупликацию, подготовить Telegram-сообщение с media_url и отправить его в канал без повторов. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему ручной кросспостинг Instagram в Telegram ломает контент-план Архитектура workflow Instagram → n8n → Telegram Контракт входных данных публикации Code Node: очистка caption, hashtags и dedupe key Готовый workflow JSON Пошаговая настройка Instagram Graph API и Telegram канала Тесты перед production Production-риски кросспостинга Полезные ссылки и смежные workflow Критерии готовности Проблема: ручной перенос постов из Instagram в Telegram приводит к дублям, потерянным ссылкам, ошибкам форматирования и хаосу в контент-плане. Решение: n8n получает media object, очищает caption, проверяет dedupe key и публикует пост в Telegram-канал с журналом результата. Workflow переносит публикацию в Telegram только после нормализации и проверки на дубли. Проблема: почему ручной кросспостинг Instagram в Telegram ломает контент-план ¶ Контент-команда часто публикует пост в Instagram, затем вручную копирует текст, картинку и ссылку в Telegram. На малом объёме это терпимо, но при регулярных рубриках появляются ошибки: забыли ссылку, потеряли хэштеги, отправили два раза, перепутали канал или опубликовали черновой caption. Кросспостинг Instagram в Telegram через n8n решает эту боль: workflow получает media object, чистит caption, проверяет `media_id` на повтор, выбирает формат отправки и пишет результат в журнал. Это не “автопостинг ради автопостинга”, а контролируемая автоматизация контент-дистрибуции. Архитектура workflow Instagram → n8n → Telegram ¶ Нода Роль Что проверить Webhook or schedule input Получает публикацию Instagram Business/Creator account, права Graph API Normalize caption Очищает текст и хэштеги длина Telegram caption, переносы, HTML Check dedupe Ищет media_id в журнале unique key по Instagram media id Send Telegram post Публикует фото/текст chat_id, права бота, формат media Audit result Сохраняет message_id можно найти, что и когда ушло Контракт входных данных публикации ¶ { "instagram_business_account_id": "17841400000000000", "media": { "id": "17900112233445566", "media_type": "IMAGE", "media_url": "https://cdn.example.com/post.jpg", "permalink": "https://www.instagram.com/p/POSTCODE/", "caption": "Новый кейс автоматизации продаж 🚀\n\n#n8n #crm #automation", "timestamp": "2026-05-30T10:00:00+0000" }, "telegram": { "chat_id": "@nodbot_channel", "parse_mode": "HTML" } } Не храните access token в payload или тексте workflow. Для Instagram Graph API используйте credentials или ENV, а в event передавайте только идентификаторы, media_url, caption и permalink. Code Node: очистка caption, hashtags и dedupe key ¶ const input = $json.body ?? $json; const media = input.media ?? input; const captionRaw = String(media.caption ?? '').trim(); const safeCaption = captionRaw .replace(/<[^>]*>/g, '') .replace(/ {3,}/g, ' ') .slice(0, 900); const hashtags = [...captionRaw.matchAll(/#[\p{L}\p{N}_]+/gu)].map(m => m[0].toLowerCase()); const permalink = String(media.permalink ?? '').trim(); const mediaUrl = String(media.media_url ?? '').trim(); const mediaType = String(media.media_type ?? 'IMAGE').toUpperCase(); if (!media.id || !permalink) { throw new Error('Instagram media id and permalink are required'); } const telegramText = `${safeCaption} Источник: ${permalink}`.trim(); return [{ json: { dedupe_key: `instagram:${media.id}`, media_id: media.id, media_type: mediaType, media_url: mediaUrl, permalink, hashtags, telegram: { chat_id: input.telegram?.chat_id, text: telegramText, send_as_photo: mediaType === 'IMAGE' && Boolean(mediaUrl), parse_mode: 'HTML' } } }]; Почему нужен журнал публикаций Schedule workflow может повторно увидеть тот же media object, а ручной повтор webhook может случиться при тестах. Unique key по `instagram:media_id` защищает Telegram-канал от дублей. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Instagram to Telegram crosspost with dedupe", "nodes": [ { "name": "Webhook or schedule input", "type": "n8n-nodes-base.webhook", "purpose": "Получить media object из Instagram Graph API или расписания" }, { "name": "Normalize caption and media", "type": "n8n-nodes-base.code", "purpose": "Очистить caption, собрать hashtags и dedupe_key" }, { "name": "Check dedupe", "type": "n8n-nodes-base.postgres", "purpose": "Не публиковать один media_id дважды" }, { "name": "Send Telegram post", "type": "n8n-nodes-base.telegram", "purpose": "Опубликовать фото/текст в канал" }, { "name": "Audit result", "type": "n8n-nodes-base.postgres", "purpose": "Записать media_id, chat_id и message_id" } ], "connections": "Input → Normalize → Dedupe → Telegram → Audit" } Пошаговая настройка Instagram Graph API и Telegram канала ¶ Проверьте, что аккаунт Instagram является Business или Creator и подключен к Meta app. Настройте источник media: polling по расписанию через Graph API или внутренний webhook из вашей контент-системы. Создайте Telegram bot, добавьте его администратором канала и проверьте `chat_id`. Добавьте таблицу дедупликации: `dedupe_key`, `media_id`, `telegram_message_id`, `sent_at`. Прогоните тестовый payload и убедитесь, что повтор не публикуется второй раз. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/instagram-telegram-crosspost" \ -H "Content-Type: application/json" \ --data @instagram-telegram-crosspost-payload.json Проверьте пост с фото, длинным caption, несколькими переносами, кириллическими хэштегами, отсутствующим media_url и повторным media_id. Для каждого сценария должен быть понятный результат: публикация, пропуск или alert. Production-риски кросспостинга ¶ Лимиты и права Instagram Graph API. Если token истек или app потерял разрешения, workflow должен отправить alert. Дубли в Telegram. Без durable dedupe один пост может выйти дважды. Сломанный HTML/Markdown. Caption нужно экранировать под выбранный parse mode. Разный смысл аудиторий. Иногда Telegram требует другой CTA, поэтому добавьте ручной override для важных постов. Нет аудита. Без message_id сложно удалить или исправить опубликованный пост. Полезные ссылки и смежные workflow ¶ См. также RSS → Telegram digest , content factory SEO briefs и Telegram alert для ошибок . Официальные документы: Instagram content publishing , Instagram APIs и Telegram Bot API . Журнал публикации показывает media_id, канал, dedupe key и message_id. Критерии готовности ¶ Один Instagram media_id публикуется в Telegram только один раз. Caption очищается и не ломает Telegram parse mode. Token и chat_id не лежат в открытом payload. Ошибки Graph API и Telegram Bot API уходят в alert. Есть журнал публикаций с message_id и permalink. Хотите автоматизировать контент-дистрибуцию? Nodbot настроит Instagram → Telegram workflow с Graph API, дедупликацией, журналом публикаций, alert-ами и безопасным хранением токенов. Настроить кросспостинг

## Test payload

```json
{
  "instagram_business_account_id": "17841400000000000",
  "media": {
    "id": "17900112233445566",
    "media_type": "IMAGE",
    "media_url": "https://cdn.example.com/post.jpg",
    "permalink": "https://www.instagram.com/p/POSTCODE/",
    "caption": "Новый кейс автоматизации продаж 🚀\n\n#n8n #crm #automation",
    "timestamp": "2026-05-30T10:00:00+0000"
  },
  "telegram": {
    "chat_id": "@nodbot_channel",
    "parse_mode": "HTML"
  }
}
```

## Key implementation snippet

```javascript
const input = $json.body ?? $json;
const media = input.media ?? input;
const captionRaw = String(media.caption ?? '').trim();
const safeCaption = captionRaw
  .replace(/<[^>]*>/g, '')
  .replace(/
{3,}/g, '

')
  .slice(0, 900);

const hashtags = [...captionRaw.matchAll(/#[\p{L}\p{N}_]+/gu)].map(m => m[0].toLowerCase());
const permalink = String(media.permalink ?? '').trim();
const mediaUrl = String(media.media_url ?? '').trim();
const mediaType = String(media.media_type ?? 'IMAGE').toUpperCase();

if (!media.id || !permalink) {
  throw new Error('Instagram media id and permalink are required');
}

const telegramText = `${safeCaption}

Источник: ${permalink}`.trim();

return [{
  json: {
    dedupe_key: `instagram:${media.id}`,
    media_id: media.id,
    media_type: mediaType,
    media_url: mediaUrl,
    permalink,
    hashtags,
    telegram: {
      chat_id: input.telegram?.chat_id,
      text: telegramText,
      send_as_photo: mediaType === 'IMAGE' && Boolean(mediaUrl),
      parse_mode: 'HTML'
    }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Instagram to Telegram crosspost with dedupe",
  "nodes": [
    {
      "name": "Webhook or schedule input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Получить media object из Instagram Graph API или расписания"
    },
    {
      "name": "Normalize caption and media",
      "type": "n8n-nodes-base.code",
      "purpose": "Очистить caption, собрать hashtags и dedupe_key"
    },
    {
      "name": "Check dedupe",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Не публиковать один media_id дважды"
    },
    {
      "name": "Send Telegram post",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Опубликовать фото/текст в канал"
    },
    {
      "name": "Audit result",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Записать media_id, chat_id и message_id"
    }
  ],
  "connections": "Input → Normalize → Dedupe → Telegram → Audit"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "MCP tool для внутреннего API через n8n | Nodbot"
source_url: "https://nodbot.ru/workflows/mcp-internal-api-tool/"
canonical_url: "https://nodbot.ru/workflows/mcp-internal-api-tool/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1048
---

# MCP tool для внутреннего API через n8n: безопасный доступ AI к данным

## AI summary

Страница показывает, как использовать n8n как безопасный gateway между AI/MCP tool call и внутренним API: проверить tool name, валидировать аргументы, применить allowlist, записать audit log и только потом вызвать backend.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему AI нельзя давать прямой доступ к внутреннему API
- Архитектура MCP tool gateway через n8n
- Контракт tool call и JSON args
- Code Node: allowlist, JSON Schema и policy check
- Готовый workflow JSON
- Пошаговая настройка MCP tool, n8n и внутреннего API
- Тесты перед production
- Production-риски MCP и tool calling
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- MCP
- tool calling
- internal API
- allowlist
- audit log
- n8n webhook

## Source outline

MCP tool для внутреннего API через n8n: безопасный доступ AI к данным ¶ Обновлено: 2026-05-30 AI summary: Страница показывает, как использовать n8n как безопасный gateway между AI/MCP tool call и внутренним API: проверить tool name, валидировать аргументы, применить allowlist, записать audit log и только потом вызвать backend. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему AI нельзя давать прямой доступ к внутреннему API Архитектура MCP tool gateway через n8n Контракт tool call и JSON args Code Node: allowlist, JSON Schema и policy check Готовый workflow JSON Пошаговая настройка MCP tool, n8n и внутреннего API Тесты перед production Production-риски MCP и tool calling Полезные ссылки и смежные workflow Критерии готовности Проблема: AI и MCP tool calling дают модели доступ к действиям, но прямой вызов внутреннего API без allowlist, validation и audit превращает ассистента в рискованный proxy. Решение: n8n должен работать как gateway: принять tool call, проверить политику, записать audit, вызвать только разрешенный endpoint и вернуть sanitized response. n8n становится контролируемым policy-слоем между AI и внутренними сервисами. Проблема: почему AI нельзя давать прямой доступ к внутреннему API ¶ MCP и tool calling делают AI полезнее: модель может запросить клиента в CRM, проверить статус заказа или подготовить ответ оператору. Но прямой доступ к внутреннему API опасен. Prompt injection может попросить модель вызвать не тот endpoint, параметры могут оказаться слишком широкими, а токен backend-а попадет в execution logs. Безопасный подход — сделать n8n policy gateway. AI вызывает не произвольный URL, а конкретный MCP tool: `crm.find_customer`, `orders.get_status` или другой allowlisted метод. Workflow проверяет роль пользователя, JSON args, лимиты, reason, пишет audit log и только после этого обращается к внутреннему API. Архитектура MCP tool gateway через n8n ¶ Нода Роль Что проверить MCP tool webhook Принимает tool call request_id, actor, tool name Validate allowlist Проверяет права и args role-based access, required fields Write audit log Фиксирует запрос до API reason, sanitized args, timestamp Call internal API Вызывает backend endpoint только allowlisted URL, timeout Sanitize response Убирает лишние поля PII minimization, max rows Respond Возвращает JSON result без stack trace и секретов Контракт tool call и JSON args ¶ { "tool": "crm.find_customer", "request_id": "req-2026-05-30-1042", "actor": { "user_id": "u-17", "role": "support_agent" }, "args": { "phone": "+7 916 123-45-67", "include_orders": false }, "policy": { "environment": "production", "reason": "support_ticket_lookup", "max_rows": 3 } } Контракт должен быть узким: одно действие, понятная причина вызова, минимум аргументов и жесткий лимит строк. Это помогает контролировать AI-интеграцию и не превращает MCP server в открытый proxy к внутренней сети. Code Node: allowlist, JSON Schema и policy check ¶ const input = $json.body ?? $json; const allowedTools = { 'crm.find_customer': { roles: ['support_agent', 'admin'], required: ['phone'], max_rows: 3, endpoint: '/crm/customers/search' }, 'orders.get_status': { roles: ['support_agent', 'admin'], required: ['order_id'], max_rows: 1, endpoint: '/orders/status' } }; const spec = allowedTools[input.tool]; if (!spec) throw new Error(`Tool is not allowed: ${input.tool}`); const role = input.actor?.role; if (!spec.roles.includes(role)) { throw new Error(`Role ${role} cannot call ${input.tool}`); } const args = input.args ?? {}; for (const field of spec.required) { if (!args[field]) throw new Error(`Missing required arg: ${field}`); } const phone = args.phone ? String(args.phone).replace(/\D/g, '') : undefined; if (phone && !/^(7|8)\d{10}$/.test(phone)) { throw new Error('Invalid phone format for tool call'); } return [{ json: { request_id: input.request_id, tool: input.tool, actor: input.actor, endpoint: spec.endpoint, method: 'POST', sanitized_args: { ...args, phone: phone ? `+7${phone.slice(-10)}` : undefined }, limit: Math.min(input.policy?.max_rows ?? spec.max_rows, spec.max_rows), audit: { reason: input.policy?.reason ?? 'not_provided', environment: input.policy?.environment ?? 'production', checked_at: new Date().toISOString() } } }]; Почему allowlist лучше, чем фильтр URL Фильтрация URL пытается угадать, что опасно. Allowlist описывает, что разрешено: конкретный tool, роли, required args, endpoint и максимальный лимит результата. Это проще проверять, тестировать и объяснять службе безопасности. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - MCP internal API tool gateway", "nodes": [ { "name": "MCP tool webhook", "type": "n8n-nodes-base.webhook", "purpose": "Принять tool call от MCP client/AI gateway" }, { "name": "Validate allowlist and args", "type": "n8n-nodes-base.code", "purpose": "Проверить tool name, роль, аргументы и policy" }, { "name": "Write audit log", "type": "n8n-nodes-base.postgres", "purpose": "Сохранить request_id, actor, reason и sanitized args" }, { "name": "Call internal API", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать только разрешенный endpoint" }, { "name": "Sanitize response", "type": "n8n-nodes-base.code", "purpose": "Убрать лишние поля до возврата AI" }, { "name": "Respond to MCP client", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть безопасный JSON result" } ], "connections": "Webhook → Validate → Audit → API → Sanitize → Respond" } Пошаговая настройка MCP tool, n8n и внутреннего API ¶ Опишите список разрешенных tools: имя, роли, аргументы, endpoint и лимиты. Создайте Webhook в n8n как gateway для MCP client или AI orchestration слоя. Добавьте Code Node для allowlist, role check и нормализации аргументов. Пишите audit log до вызова backend-а, чтобы видеть даже запрещенные попытки. Возвращайте AI только sanitized response, без секретов, внутренних id и лишних PII. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/mcp-internal-api-tool" \ -H "Content-Type: application/json" \ --data @mcp-internal-api-tool-payload.json Проверьте разрешенный tool, неизвестный tool, роль без доступа, отсутствующий required arg, слишком широкий лимит и prompt injection в текстовом поле. Запрещенные кейсы должны завершаться контролируемой ошибкой и audit-записью. Production-риски MCP и tool calling ¶ Overprivileged credentials. Токен n8n не должен иметь доступ ко всему backend-у. Prompt injection. Модель может попытаться вызвать другой tool или запросить больше данных. Нет audit log. Нельзя расследовать, кто и зачем вызвал внутренний API. Слишком широкий response. Возвращайте минимум полей, нужных для ответа. Ошибки backend-а видит пользователь. Убирайте stack trace и внутренние URL из ответа AI. Полезные ссылки и смежные workflow ¶ См. также права AI-агентов , архитектуру AI-агентов , проверку подписи webhook и GigaChat support draft . Официальные документы: Model Context Protocol , MCP Specification и n8n Webhook node . Audit log показывает tool, actor, limit, reason и результат policy check. Критерии готовности ¶ Каждый tool есть в allowlist с ролями и лимитами. Аргументы валидируются до вызова внутреннего API. Audit log пишется для разрешенных и запрещенных попыток. Ответ AI содержит только минимально нужные поля. Секреты backend-а хранятся в credentials/ENV, а не в payload. Нужен безопасный MCP tool gateway? Nodbot спроектирует allowlist, policy checks, audit log, schema validation и безопасный доступ AI к вашим внутренним API через n8n. Обсудить MCP gateway

## Test payload

```json
{
  "tool": "crm.find_customer",
  "request_id": "req-2026-05-30-1042",
  "actor": {
    "user_id": "u-17",
    "role": "support_agent"
  },
  "args": {
    "phone": "+7 916 123-45-67",
    "include_orders": false
  },
  "policy": {
    "environment": "production",
    "reason": "support_ticket_lookup",
    "max_rows": 3
  }
}
```

## Key implementation snippet

```javascript
const input = $json.body ?? $json;
const allowedTools = {
  'crm.find_customer': {
    roles: ['support_agent', 'admin'],
    required: ['phone'],
    max_rows: 3,
    endpoint: '/crm/customers/search'
  },
  'orders.get_status': {
    roles: ['support_agent', 'admin'],
    required: ['order_id'],
    max_rows: 1,
    endpoint: '/orders/status'
  }
};

const spec = allowedTools[input.tool];
if (!spec) throw new Error(`Tool is not allowed: ${input.tool}`);

const role = input.actor?.role;
if (!spec.roles.includes(role)) {
  throw new Error(`Role ${role} cannot call ${input.tool}`);
}

const args = input.args ?? {};
for (const field of spec.required) {
  if (!args[field]) throw new Error(`Missing required arg: ${field}`);
}

const phone = args.phone ? String(args.phone).replace(/\D/g, '') : undefined;
if (phone && !/^(7|8)\d{10}$/.test(phone)) {
  throw new Error('Invalid phone format for tool call');
}

return [{
  json: {
    request_id: input.request_id,
    tool: input.tool,
    actor: input.actor,
    endpoint: spec.endpoint,
    method: 'POST',
    sanitized_args: { ...args, phone: phone ? `+7${phone.slice(-10)}` : undefined },
    limit: Math.min(input.policy?.max_rows ?? spec.max_rows, spec.max_rows),
    audit: {
      reason: input.policy?.reason ?? 'not_provided',
      environment: input.policy?.environment ?? 'production',
      checked_at: new Date().toISOString()
    }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - MCP internal API tool gateway",
  "nodes": [
    {
      "name": "MCP tool webhook",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять tool call от MCP client/AI gateway"
    },
    {
      "name": "Validate allowlist and args",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить tool name, роль, аргументы и policy"
    },
    {
      "name": "Write audit log",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Сохранить request_id, actor, reason и sanitized args"
    },
    {
      "name": "Call internal API",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Вызвать только разрешенный endpoint"
    },
    {
      "name": "Sanitize response",
      "type": "n8n-nodes-base.code",
      "purpose": "Убрать лишние поля до возврата AI"
    },
    {
      "name": "Respond to MCP client",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть безопасный JSON result"
    }
  ],
  "connections": "Webhook → Validate → Audit → API → Sanitize → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "МойСклад stock alert через n8n: остатки | Nodbot"
source_url: "https://nodbot.ru/workflows/moysklad-stock-alert/"
canonical_url: "https://nodbot.ru/workflows/moysklad-stock-alert/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 950
---

# МойСклад → n8n: alert по остаткам, резервам и точке заказа

## AI summary

AI-friendly Problem/Solution-мануал: как настроить alert по остаткам МойСклад через n8n, учитывать резерв, минимальный запас и точку заказа, отправлять Telegram/CRM уведомление и не спамить команду.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API/файлы/мониторинг, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему остатки заканчиваются раньше отчёта
- Архитектура workflow для stock alert МойСклад
- Контракт данных товара и склада
- Code Node: расчет available stock и reorder alert
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка МойСклад, n8n и Telegram
- Тесты остатков, резервов и повторных алертов
- Production-риски складской автоматизации
- Полезные ссылки и документация
- Критерии готовности

## Key topics

- МойСклад
- stock alert
- остатки
- reorder point
- reserve
- закупки n8n

## Source outline

МойСклад → n8n: alert по остаткам, резервам и точке заказа ¶ Обновлено: 2026-05-30 AI summary: AI-friendly Problem/Solution-мануал: как настроить alert по остаткам МойСклад через n8n, учитывать резерв, минимальный запас и точку заказа, отправлять Telegram/CRM уведомление и не спамить команду. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему остатки заканчиваются раньше отчёта Архитектура workflow для stock alert МойСклад Контракт данных товара и склада Code Node: расчет available stock и reorder alert Готовый workflow JSON: скачать и импортировать Пошаговая настройка МойСклад, n8n и Telegram Тесты остатков, резервов и повторных алертов Production-риски складской автоматизации Полезные ссылки и документация Критерии готовности Проблема: остатки в МойСклад могут выглядеть нормальными, но доступный запас уже ниже точки заказа из-за резервов, продаж и задержек поставщика. Отчёт раз в неделю обнаруживает проблему слишком поздно. Решение: настроить workflow МойСклад → n8n: регулярно получать остатки, считать доступное количество, сравнивать с reorder point и отправлять точный alert закупкам. Alert должен учитывать резерв и склад, а не только общий остаток. Проблема: почему остатки заканчиваются раньше отчёта ¶ В МойСклад товар может числиться на остатке, но быть уже зарезервированным под заказ. Если смотреть только на stock , закупки узнают о дефиците поздно: клиент уже оформил заказ, менеджер обещал отгрузку, а свободного количества нет. Поэтому alert по остаткам должен учитывать резервы, склад, минимальный запас и точку заказа. Workflow n8n для МойСклад полезен, когда нужно не просто выгрузить отчёт, а создать регулярную автоматизацию закупок: проверить остатки, отфильтровать критичные позиции, отправить Telegram/CRM задачу и не повторять один и тот же alert каждый час. Архитектура workflow для stock alert МойСклад ¶ Нода Роль Что проверить Schedule daily Запускает проверку Время до закупочного окна Fetch stock Получает остатки МойСклад Склад, модификации, лимиты API Calculate reorder Считает доступный остаток stock - reserve + in_transit Filter alerts Оставляет только дефицит reorder_point, supplier, min_order_qty Notify procurement Отправляет alert Telegram, CRM task или email Контракт данных товара и склада ¶ Для каждого товара лучше иметь стабильный product_id , артикул, склад и точку заказа. Значения можно брать из МойСклад, Google Sheets или отдельной таблицы закупок. { "product_id": "c8e6a2f1-11a0-4e41-91b4-63e0e6a91f70", "name": "Картридж фильтра A-10", "sku": "FILTER-A10", "warehouse": "Основной склад", "stock": 12, "reserve": 5, "in_transit": 0, "reorder_point": 10, "min_order_qty": 20, "supplier": "ООО Поставщик" } Code Node: расчет available stock и reorder alert ¶ Code Node ниже не делает заказ автоматически. Он рассчитывает сигнал для человека или отдельного согласованного workflow закупки. const item = $json; const stock = Number(item.stock ?? 0); const reserve = Number(item.reserve ?? 0); const inTransit = Number(item.in_transit ?? 0); const reorderPoint = Number(item.reorder_point ?? item.min_stock ?? 0); const available = stock - reserve + inTransit; const needOrder = available <= reorderPoint; const qtyToOrder = needOrder ? Math.max(Number(item.min_order_qty ?? 1), reorderPoint * 2 - available) : 0; return [{ json: { product_id: item.product_id, sku: item.sku, name: item.name, warehouse: item.warehouse ?? 'default', stock, reserve, in_transit: inTransit, available, reorder_point: reorderPoint, alert: needOrder, qty_to_order: qtyToOrder, dedupe_key: `moysklad:${item.product_id}:${item.warehouse ?? 'default'}:${reorderPoint}`, message: needOrder ? `⚠️ ${item.sku}: доступно ${available}, точка заказа ${reorderPoint}, заказать ${qtyToOrder}` : `✅ ${item.sku}: запас в норме, доступно ${available}` }}]; Почему нельзя смотреть только на stock Остаток на складе может быть зарезервирован под заказы. Для закупок важнее доступное количество: фактический остаток минус резерв плюс ожидаемый приход. Готовый workflow JSON: скачать и импортировать ¶ В архиве страницы есть workflow JSON и payload. После импорта замените credential МойСклад, параметры склада, таблицу reorder points и канал уведомлений. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - MoySklad stock alert with reorder point", "nodes": [ { "name": "Schedule daily", "type": "n8n-nodes-base.scheduleTrigger", "purpose": "Запускать проверку остатков" }, { "name": "Fetch stock from MoySklad", "type": "n8n-nodes-base.httpRequest", "purpose": "Получить остатки, резервы и склады" }, { "name": "Calculate reorder Code", "type": "n8n-nodes-base.code", "purpose": "Посчитать available stock и qty_to_order" }, { "name": "Filter alerts", "type": "n8n-nodes-base.if", "purpose": "Отправить только товары ниже точки заказа" }, { "name": "Send Telegram/CRM alert", "type": "n8n-nodes-base.telegram", "purpose": "Уведомить закупки или создать задачу" } ], "connections": "Schedule → Fetch stock → Calculate → IF alert → Telegram/CRM" } Пошаговая настройка МойСклад, n8n и Telegram ¶ Определите список складов и товаров, которые участвуют в контроле остатков. Задайте reorder_point и min_order_qty для каждой SKU. Настройте HTTP Request к API МойСклад и проверьте пагинацию. Добавьте расчет available stock и фильтр по alert=true. Отправляйте результат в Telegram, Битрикс24 задачу или таблицу закупок. Тесты остатков, резервов и повторных алертов ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/moysklad-stock-alert" -H "Content-Type: application/json" --data @moysklad-stock-alert-payload.json Товар ниже точки заказа должен попасть в alert. Товар с большим резервом должен считаться дефицитным, даже если stock высокий. Позиция в пути должна уменьшать срочность, если это согласовано с закупками. Повторный запуск не должен спамить один и тот же alert без изменения статуса. Ошибка API МойСклад должна уходить в Error Workflow. Production-риски складской автоматизации ¶ Не учитываются резервы. Команда закупок видит “12 на складе”, хотя доступно только 7. Одна точка заказа для всех SKU. Быстроходные товары заканчиваются раньше, чем срабатывает alert. Нет дедупликации. Telegram получает один и тот же список дефицита каждый час. Пагинация API пропущена. Проверяется только первая страница товаров. Автозаказ без подтверждения. Для закупок лучше начинать с human approval. Полезные ссылки и документация ¶ Смотрите также: Error Workflow с Telegram-алертом , Retry и DLQ для API , Idempotency в Postgres . Официальная документация: МойСклад JSON API , n8n HTTP Request node , Telegram Bot API . Критерии готовности ¶ Alert строится по доступному остатку, а не только по stock. У каждой SKU есть точка заказа и минимальная партия. Workflow учитывает склад, резерв и товары в пути. Повторные уведомления дедуплицируются или группируются. Ошибки API, лимиты и пустые ответы попадают в мониторинг. Нужно автоматизировать контроль остатков? Nodbot настроит МойСклад, n8n, reorder alerts, Telegram/CRM задачи и human approval для закупок без хаоса. Настроить stock alert

## Test payload

```json
{
  "product_id": "c8e6a2f1-11a0-4e41-91b4-63e0e6a91f70",
  "name": "Картридж фильтра A-10",
  "sku": "FILTER-A10",
  "warehouse": "Основной склад",
  "stock": 12,
  "reserve": 5,
  "in_transit": 0,
  "reorder_point": 10,
  "min_order_qty": 20,
  "supplier": "ООО Поставщик"
}
```

## Key implementation snippet

```javascript
const item = $json;
const stock = Number(item.stock ?? 0);
const reserve = Number(item.reserve ?? 0);
const inTransit = Number(item.in_transit ?? 0);
const reorderPoint = Number(item.reorder_point ?? item.min_stock ?? 0);
const available = stock - reserve + inTransit;
const needOrder = available <= reorderPoint;
const qtyToOrder = needOrder ? Math.max(Number(item.min_order_qty ?? 1), reorderPoint * 2 - available) : 0;

return [{ json: {
  product_id: item.product_id,
  sku: item.sku,
  name: item.name,
  warehouse: item.warehouse ?? 'default',
  stock,
  reserve,
  in_transit: inTransit,
  available,
  reorder_point: reorderPoint,
  alert: needOrder,
  qty_to_order: qtyToOrder,
  dedupe_key: `moysklad:${item.product_id}:${item.warehouse ?? 'default'}:${reorderPoint}`,
  message: needOrder
    ? `⚠️ ${item.sku}: доступно ${available}, точка заказа ${reorderPoint}, заказать ${qtyToOrder}`
    : `✅ ${item.sku}: запас в норме, доступно ${available}`
}}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - MoySklad stock alert with reorder point",
  "nodes": [
    { "name": "Schedule daily", "type": "n8n-nodes-base.scheduleTrigger", "purpose": "Запускать проверку остатков" },
    { "name": "Fetch stock from MoySklad", "type": "n8n-nodes-base.httpRequest", "purpose": "Получить остатки, резервы и склады" },
    { "name": "Calculate reorder Code", "type": "n8n-nodes-base.code", "purpose": "Посчитать available stock и qty_to_order" },
    { "name": "Filter alerts", "type": "n8n-nodes-base.if", "purpose": "Отправить только товары ниже точки заказа" },
    { "name": "Send Telegram/CRM alert", "type": "n8n-nodes-base.telegram", "purpose": "Уведомить закупки или создать задачу" }
  ],
  "connections": "Schedule → Fetch stock → Calculate → IF alert → Telegram/CRM"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Notion в WordPress через n8n: черновики | Nodbot"
source_url: "https://nodbot.ru/workflows/notion-to-wordpress-draft/"
canonical_url: "https://nodbot.ru/workflows/notion-to-wordpress-draft/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 910
---

# Интеграция Notion и WordPress через n8n: черновик статьи без ручного копирования

## AI summary

Практический сценарий Notion → WordPress через n8n: забрать утвержденную страницу, очистить markdown/HTML, создать черновик в WordPress, сохранить slug и не опубликовать непроверенный материал.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API/CMS/мессенджер, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему ручной перенос из Notion в WordPress ломает публикации
- Архитектура workflow Notion → n8n → WordPress
- Контракт входных данных
- Подготовка markdown, slug и WordPress draft
- Готовый workflow JSON
- Пошаговая настройка связки Notion и WordPress
- Тесты перед production
- Production-риски публикации в CMS
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Notion to WordPress
- WordPress draft
- n8n editorial workflow
- markdown cleanup
- REST API

## Source outline

Интеграция Notion и WordPress через n8n: черновик статьи без ручного копирования ¶ Обновлено: 2026-05-30 AI summary: Практический сценарий Notion → WordPress через n8n: забрать утвержденную страницу, очистить markdown/HTML, создать черновик в WordPress, сохранить slug и не опубликовать непроверенный материал. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему ручной перенос из Notion в WordPress ломает публикации Архитектура workflow Notion → n8n → WordPress Контракт входных данных Подготовка markdown, slug и WordPress draft Готовый workflow JSON Пошаговая настройка связки Notion и WordPress Тесты перед production Production-риски публикации в CMS Полезные ссылки и смежные workflow Критерии готовности Проблема: ручной перенос статей из Notion в WordPress ломает форматирование, теряет SEO-поля и съедает время редактора. Решение: надежная связка Notion → n8n → WordPress создает безопасный draft, сохраняет source ID, slug, category и оставляет публикацию на ручной approval. Workflow переносит утвержденную страницу в WordPress как черновик, а не публикует сырой материал. Проблема: почему ручной перенос из Notion в WordPress ломает публикации ¶ Редакционные команды часто пишут в Notion, а публикуют в WordPress. Ручной перенос кажется быстрым, пока в статье не пропадают заголовки, списки, code block, alt-тексты, внутренние ссылки и SEO-поля. В итоге редактор тратит время на повторную верстку, а production получает черновик без понятной связи с исходной страницей. Интеграция Notion и WordPress через n8n нужна не для автопубликации любой заметки. Правильный сценарий создает именно черновик , сохраняет source page ID, slug, category и excerpt, а публикацию оставляет человеку. Архитектура workflow Notion → n8n → WordPress ¶ Нода Роль Что проверить Webhook import request Принимает Notion page_id секрет, статус Approved, автор Fetch Notion page Читает свойства и контент доступ integration к базе и странице Prepare WordPress draft Чистит markdown, slug и excerpt нет TODO, пустого title и битых ссылок Create WordPress draft Создает post со статусом draft REST URL, Application Password, category Return draft URL Возвращает ссылку редактору без токенов и приватных данных Контракт входных данных ¶ { "notion_page_id": "24f0c9cb2a344bcfa3d0d7b5aa000111", "wordpress_status": "draft", "category_slug": "n8n-workflows", "author_id": 3, "canonical_url": "https://nodbot.ru/workflows/notion-to-wordpress-draft/", "source": "notion-editorial-calendar" } Входной payload может приходить из Notion database automation, кнопки в админке или внутренней формы. Важно передавать статус публикации как draft и не давать workflow право публиковать сразу в production без проверки. Подготовка markdown, slug и WordPress draft ¶ const src = $json.body ?? $json; const pageTitle = String(src.title ?? src.notion_title ?? 'Черновик без названия').trim(); const markdown = String(src.markdown ?? src.content ?? '').trim(); if (!markdown || markdown.length < 500) { throw new Error('Notion page content is too short for WordPress draft'); } const slug = pageTitle .toLowerCase() .replace(/ё/g, 'e') .replace(/[^a-zа-я0-9]+/gi, '-') .replace(/^-|-$/g, '') .slice(0, 80); const cleaned = markdown .replace(/<!--.*?-->/gs, '') .replace(/ {3,}/g, ' ') .replace(/\[(TODO|FIXME)\]/gi, '**Нужно проверить:**'); return [{ json: { wordpress: { title: pageTitle, slug, status: src.wordpress_status ?? 'draft', content: cleaned, excerpt: cleaned.replace(/[#*_>`]/g, '').slice(0, 250), categories: src.category_ids ?? [], author: src.author_id ?? undefined }, source: { notion_page_id: src.notion_page_id, canonical_url: src.canonical_url ?? '', imported_at: new Date().toISOString() } } }]; Почему workflow создает только draft WordPress REST API позволяет создавать записи со статусом draft/publish. Для редакционного процесса безопаснее сначала создать draft, проверить preview, SEO-поля, изображения и только потом публиковать материал вручную или отдельным workflow после approval. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Notion to WordPress draft", "nodes": [ { "name": "Webhook import request", "type": "n8n-nodes-base.webhook", "purpose": "Принять page_id или событие календаря" }, { "name": "Fetch Notion page", "type": "n8n-nodes-base.notion", "purpose": "Получить свойства страницы и контент" }, { "name": "Prepare WordPress draft", "type": "n8n-nodes-base.code", "purpose": "Очистить markdown, slug, excerpt и статус draft" }, { "name": "Create WordPress draft", "type": "n8n-nodes-base.wordpress", "purpose": "Создать черновик через REST API" }, { "name": "Return draft URL", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть ссылку редактору" } ], "connections": "Webhook → Notion → Prepare → WordPress draft → Respond" } Пошаговая настройка связки Notion и WordPress ¶ Создайте Notion integration и выдайте ей доступ только к редакционной базе. В WordPress создайте Application Password для отдельного пользователя-бота. Сопоставьте Notion properties с WordPress полями: title, category, author, canonical URL. В Code Node добавьте правила очистки markdown, slug и excerpt. Запустите тест на небольшой странице с H2, списком, ссылкой и code block. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/notion-to-wordpress-draft" \ -H "Content-Type: application/json" \ --data @notion-to-wordpress-draft-payload.json Проверьте три типа страниц: обычный текст, длинный технический мануал с кодом и материал с изображениями. Workflow должен вернуть ссылку на draft и не менять статус на publish. Production-риски публикации в CMS ¶ Автопубликация без review. Один ошибочный Notion status может вывести сырой текст в индекс. HTML ломает Gutenberg. Не отправляйте случайный HTML, если редакторы работают с блоками. Потеря canonical. Если статья переносится между сайтами, canonical должен быть явным. Секреты в execution data. Не логируйте Application Password и токены Notion. Нет связи с source page. Сохраняйте Notion page ID в meta или комментарии workflow. Полезные ссылки и смежные workflow ¶ См. также контент-фабрику SEO-брифов , структурированный JSON от AI , версионирование workflow . Для интеграции используйте официальные документы Notion API и WordPress REST API posts . Результат должен быть понятен редактору: source, status draft, slug, category и следующий шаг. Критерии готовности ¶ Workflow создает только draft, а не publish. Title, slug, excerpt и category формируются предсказуемо. Code block и списки не ломаются при переносе. Есть source Notion page ID и ссылка на WordPress preview. Ошибки REST API уходят в alert, а не теряются в executions. Нужно связать Notion и WordPress без хаоса? Nodbot настроит импорт черновиков, маппинг полей, preview, проверки и безопасную публикацию через n8n. Настроить editorial workflow

## Test payload

```json
{
  "notion_page_id": "24f0c9cb2a344bcfa3d0d7b5aa000111",
  "wordpress_status": "draft",
  "category_slug": "n8n-workflows",
  "author_id": 3,
  "canonical_url": "https://nodbot.ru/workflows/notion-to-wordpress-draft/",
  "source": "notion-editorial-calendar"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const pageTitle = String(src.title ?? src.notion_title ?? 'Черновик без названия').trim();
const markdown = String(src.markdown ?? src.content ?? '').trim();

if (!markdown || markdown.length < 500) {
  throw new Error('Notion page content is too short for WordPress draft');
}

const slug = pageTitle
  .toLowerCase()
  .replace(/ё/g, 'e')
  .replace(/[^a-zа-я0-9]+/gi, '-')
  .replace(/^-|-$/g, '')
  .slice(0, 80);

const cleaned = markdown
  .replace(/<!--.*?-->/gs, '')
  .replace(/
{3,}/g, '

')
  .replace(/\[(TODO|FIXME)\]/gi, '**Нужно проверить:**');

return [{
  json: {
    wordpress: {
      title: pageTitle,
      slug,
      status: src.wordpress_status ?? 'draft',
      content: cleaned,
      excerpt: cleaned.replace(/[#*_>`]/g, '').slice(0, 250),
      categories: src.category_ids ?? [],
      author: src.author_id ?? undefined
    },
    source: {
      notion_page_id: src.notion_page_id,
      canonical_url: src.canonical_url ?? '',
      imported_at: new Date().toISOString()
    }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Notion to WordPress draft",
  "nodes": [
    {
      "name": "Webhook import request",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять page_id или событие календаря"
    },
    {
      "name": "Fetch Notion page",
      "type": "n8n-nodes-base.notion",
      "purpose": "Получить свойства страницы и контент"
    },
    {
      "name": "Prepare WordPress draft",
      "type": "n8n-nodes-base.code",
      "purpose": "Очистить markdown, slug, excerpt и статус draft"
    },
    {
      "name": "Create WordPress draft",
      "type": "n8n-nodes-base.wordpress",
      "purpose": "Создать черновик через REST API"
    },
    {
      "name": "Return draft URL",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть ссылку редактору"
    }
  ],
  "connections": "Webhook → Notion → Prepare → WordPress draft → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Ollama и n8n: локальные AI-сводки | Nodbot"
source_url: "https://nodbot.ru/workflows/ollama-local-ai-summary/"
canonical_url: "https://nodbot.ru/workflows/ollama-local-ai-summary/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1082
---

# Ollama и n8n: локальные AI-сводки без отправки данных в облако

## AI summary

Практический workflow для локальной AI-сводки: принять текст, очистить его, разбить на безопасные фрагменты, отправить в Ollama API, собрать итоговую summary и не выгружать внутренние данные во внешний AI-сервис.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Ollama
- local AI
- n8n HTTP Request
- summary
- privacy
- chunking

## Source outline

Ollama и n8n: локальные AI-сводки без отправки данных в облако ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для локальной AI-сводки: принять текст, очистить его, разбить на безопасные фрагменты, отправить в Ollama API, собрать итоговую summary и не выгружать внутренние данные во внешний AI-сервис. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: команда хочет автоматизировать сводки писем, заявок или документов, но не может отправлять коммерческие данные в облачные LLM из-за NDA, персональных данных или внутренней политики безопасности. Решение: использовать n8n как orchestrator и Ollama как локальный AI-runtime: workflow чистит входной текст, режет его на chunks, вызывает локальный `/api/generate`, собирает краткую сводку и пишет audit без лишних персональных данных. Workflow оставляет чувствительный текст внутри вашей инфраструктуры и возвращает проверяемую summary. Проблема: почему внутренние тексты нельзя всегда отправлять в облачный AI ¶ Локальная AI-сводка нужна там, где исходный текст нельзя отдавать внешнему провайдеру: коммерческие предложения, обращения клиентов, внутренние отчёты, протоколы встреч или фрагменты базы знаний. Простая интеграция “HTTP Request → облачная модель” решает задачу быстро, но может нарушить правила хранения данных. Ollama позволяет запускать модели локально, а n8n удобно использовать для маршрутизации, подготовки текста, контроля ошибок и передачи результата в CRM, Telegram или Google Sheets. Такая связка не делает модель магической: нужно контролировать размер текста, таймауты, качество ответа и fallback на ручную обработку. Архитектура workflow Ollama → n8n для локальной суммаризации ¶ Нода Роль Что проверить Webhook input принимает текст, source_id и режим summary лимит размера, автор запроса, тип источника Normalize text удаляет HTML, повторяющиеся пробелы и мусор нет секретов в логах и stack trace Chunk text режет длинный текст на фрагменты размер chunk меньше контекстного окна модели Call Ollama API вызывает локальный `/api/generate` base URL, model, timeout, stream=false Merge summary собирает итоговую сводку нет выдуманных фактов, есть action items Respond / Save возвращает JSON или пишет результат сохраняется source_id и audit_key Для production лучше держать Ollama на отдельной машине или контейнере рядом с n8n, а не на случайном ноутбуке. Так проще контролировать GPU/CPU, доступ к порту `11434` и обновления модели. Контракт входных данных для локальной AI-сводки ¶ { "source_id": "ticket-9831", "source_type": "support_thread", "language": "ru", "summary_mode": "action_items", "text": "Клиент просит перенести интеграцию с Google Sheets на Битрикс24, сохранить UTM и убрать дубли по телефону. Нужен срок и оценка." } В payload не нужен полный контекст бизнеса. Передавайте только текст, который реально нужен для summary, и стабильный `source_id`, чтобы результат можно было связать с исходным объектом. Code Node: очистка текста, chunking и prompt для Ollama ¶ const src = $json.body ?? $json; const text = String(src.text ?? '').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim(); if (text.length < 80) throw new Error('Text is too short for useful summary'); if (text.length > 60000) throw new Error('Text is too long: split before workflow'); const maxChunk = 5500; const chunks = []; for (let i = 0; i < text.length; i += maxChunk) { chunks.push(text.slice(i, i + maxChunk)); } const prompt = `Сделай краткую деловую сводку на русском. Верни JSON: summary, facts, action_items, risks. Не добавляй факты, которых нет в тексте.\n\nТекст:\n${chunks[0]}`; return [{ json: { source_id: String(src.source_id ?? 'unknown'), source_type: String(src.source_type ?? 'text'), model: src.model ?? 'qwen2.5:7b-instruct', ollama_body: { model: src.model ?? 'qwen2.5:7b-instruct', prompt, stream: false, options: { temperature: 0.2 } }, chunk_count: chunks.length, audit_key: `ollama-summary:${src.source_id ?? Date.now()}` } }]; Почему stream=false удобнее для автоматизации Потоковая генерация хороша для интерфейса чата, но workflow проще тестировать и логировать, когда Ollama возвращает один JSON-ответ. Для длинных документов лучше отдельно делать chunking и merge, а не ждать бесконечный stream. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Ollama local AI summary", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять текст для локальной сводки" }, { "name": "Normalize and chunk text", "type": "n8n-nodes-base.code", "purpose": "Очистить текст и подготовить prompt" }, { "name": "Call Ollama generate", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать локальный Ollama API" }, { "name": "Validate summary", "type": "n8n-nodes-base.code", "purpose": "Проверить JSON и отсутствие пустого ответа" }, { "name": "Save audit log", "type": "n8n-nodes-base.postgres", "purpose": "Сохранить source_id, model и latency" }, { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть summary в вызывающую систему" } ], "connections": "Webhook input → Normalize and chunk text → Call Ollama generate → Validate summary → Save audit log → Respond to Webhook" } Пошаговая настройка Ollama, n8n и локальной модели ¶ Установите Ollama и скачайте модель, которую реально выдерживает ваш сервер. Закройте порт `11434` от внешнего интернета и разрешите доступ только n8n. Импортируйте workflow JSON и замените base URL Ollama, если он отличается от `http://localhost:11434`. Настройте prompt под ваш тип данных: заявки, письма, отчёты или протоколы. Добавьте audit log: source_id, model, chunk_count, latency и статус ответа. Тесты перед production и проверка качества summary ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/ollama-local-ai-summary" \ -H "Content-Type: application/json" \ --data @ollama-local-ai-summary-payload.json Отправьте короткий текст, длинный текст, HTML-письмо и текст с персональными данными. Проверьте, что модель не добавляет факты, которых нет во входном тексте. Остановите Ollama и убедитесь, что workflow возвращает контролируемую ошибку. Проверьте timeout: зависший локальный AI не должен блокировать очередь n8n. Сравните summary с ручной выжимкой на 10 реальных примерах. Production-риски локального AI и Ollama API ¶ Ollama доступен извне. Локальная приватность теряет смысл, если порт API открыт в интернет. Нет лимита длины. Длинный текст может упасть по timeout или съесть всю память. Модель выдумывает факты. Prompt должен требовать evidence и запрет на добавление отсутствующих данных. Нет fallback. При недоступности Ollama нужна ручная очередь или облачный резерв только для разрешённых данных. Execution logs хранят исходный текст. Настройте политику хранения данных в n8n. Полезные ссылки и смежные workflow ¶ См. также OpenRouter model fallback , GigaChat support draft и Docker Compose для n8n . Официальные документы: Ollama API и n8n HTTP Request . Итоговая карточка показывает модель, source_id, число chunks и статус проверки. Критерии готовности ¶ Ollama недоступен из интернета и вызывается только из n8n. Есть лимиты размера текста, timeout и понятная ошибка при недоступной модели. Prompt требует JSON, action items и запрет на выдуманные факты. Audit log хранит source_id/model/status, но не избыточные персональные данные. Результат проверен на реальных примерах и принят владельцем процесса. Нужны локальные AI-сводки без утечки данных? Nodbot настроит Ollama, n8n, Docker, лимиты, prompt-контракт, audit log и интеграцию результата с вашей CRM или базой знаний. Обсудить локальный AI workflow

## Test payload

```json
{
  "source_id": "ticket-9831",
  "source_type": "support_thread",
  "language": "ru",
  "summary_mode": "action_items",
  "text": "Клиент просит перенести интеграцию с Google Sheets на Битрикс24, сохранить UTM и убрать дубли по телефону. Нужен срок и оценка."
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const text = String(src.text ?? '').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
if (text.length < 80) throw new Error('Text is too short for useful summary');
if (text.length > 60000) throw new Error('Text is too long: split before workflow');

const maxChunk = 5500;
const chunks = [];
for (let i = 0; i < text.length; i += maxChunk) {
  chunks.push(text.slice(i, i + maxChunk));
}

const prompt = `Сделай краткую деловую сводку на русском. Верни JSON: summary, facts, action_items, risks. Не добавляй факты, которых нет в тексте.\n\nТекст:\n${chunks[0]}`;

return [{
  json: {
    source_id: String(src.source_id ?? 'unknown'),
    source_type: String(src.source_type ?? 'text'),
    model: src.model ?? 'qwen2.5:7b-instruct',
    ollama_body: { model: src.model ?? 'qwen2.5:7b-instruct', prompt, stream: false, options: { temperature: 0.2 } },
    chunk_count: chunks.length,
    audit_key: `ollama-summary:${src.source_id ?? Date.now()}`
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Ollama local AI summary",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять текст для локальной сводки"
    },
    {
      "name": "Normalize and chunk text",
      "type": "n8n-nodes-base.code",
      "purpose": "Очистить текст и подготовить prompt"
    },
    {
      "name": "Call Ollama generate",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Вызвать локальный Ollama API"
    },
    {
      "name": "Validate summary",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить JSON и отсутствие пустого ответа"
    },
    {
      "name": "Save audit log",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Сохранить source_id, model и latency"
    },
    {
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть summary в вызывающую систему"
    }
  ],
  "connections": "Webhook input → Normalize and chunk text → Call Ollama generate → Validate summary → Save audit log → Respond to Webhook"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "1С и n8n: HTTP-обмен заказами без дублей | Nodbot"
source_url: "https://nodbot.ru/workflows/onec-http-exchange/"
canonical_url: "https://nodbot.ru/workflows/onec-http-exchange/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1118
---

# 1С и n8n: HTTP-обмен заказами со статусами, retry и дедупликацией

## AI summary

Практический workflow для обмена 1С и n8n: принять заказ или статус через HTTP, проверить подпись и внешний ID, нормализовать строки, не создать дубль, отправить подтверждение в 1С и обработать ошибки через retry/DLQ.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- 1C
- n8n
- HTTP exchange
- idempotency
- orders
- retry
- DLQ
- CRM integration

## Source outline

1С и n8n: HTTP-обмен заказами со статусами, retry и дедупликацией ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для обмена 1С и n8n: принять заказ или статус через HTTP, проверить подпись и внешний ID, нормализовать строки, не создать дубль, отправить подтверждение в 1С и обработать ошибки через retry/DLQ. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: 1С часто становится источником заказов, остатков или статусов, но прямой HTTP-обмен ломается на повторах, ручных перезапусках, временных 5xx и разных форматах номеров документов. Решение: использовать n8n как безопасный integration layer между 1С и внешними системами: принимать HTTP-события, проверять подпись, строить idempotency key по `external_id`, обновлять CRM/магазин и возвращать 1С понятный ответ. Workflow принимает заказ из 1С, нормализует строки, проверяет idempotency и возвращает подтверждение обмена. Проблема: почему HTTP-обмен 1С создает дубли и потерянные статусы ¶ В интеграциях с 1С дубли появляются не потому, что кто-то плохо написал webhook. Обычно причина в бизнес-реальности: пользователь повторно выгрузил документ, регламентное задание перезапустилось, сеть оборвалась после успешной записи, а 1С не получила подтверждение и отправила заказ ещё раз. Если n8n каждый раз создаёт новую сделку или заказ во внешней системе, бухгалтерия и продажи быстро перестают доверять автоматизации. Надёжный HTTP-обмен должен быть идемпотентным: один `external_id` из 1С приводит к одному бизнес-объекту, а повтор меняет статус или возвращает уже обработанный результат. Архитектура workflow 1С → n8n → CRM/API ¶ Нода Роль Что проверить 1C HTTP service отправляет заказ или статус метод POST, JSON, external_id, подпись n8n Webhook принимает событие от 1С production URL, timeout, корректный ответ Normalize order приводит поля к контракту суммы, НДС, строки товаров, телефоны Idempotency check ищет обработанный external_id unique key, статус, retry_count Upsert target system создаёт/обновляет CRM, сайт или склад маппинг полей, API ошибки, rate limit Confirm to 1C возвращает результат обмена код, message, target_id, повторный ответ Для обмена статусами и заказами лучше разделять event types: `order.created`, `order.updated`, `payment.status`, `shipment.status`. Так проще маршрутизировать ошибки и не смешивать разные бизнес-процессы в одном IF-блоке. Контракт входных данных из 1С ¶ { "event_type": "order.created", "external_id": "1c-doc-000184", "number": "Заказ покупателя 000184", "date": "2026-05-30T09:45:00+03:00", "customer": { "name": "ООО Ромашка", "inn": "7701000000", "phone": "+7 (495) 100-20-30" }, "items": [ { "sku": "N8N-SETUP", "name": "Внедрение n8n", "quantity": 1, "price": 49000, "vat": "20%" } ], "total": 49000, "currency": "RUB", "status": "new" } `external_id` — главный ключ. Не используйте номер документа как единственный ID, если в 1С есть разные базы, организации или типы документов с пересекающейся нумерацией. Code Node: нормализация заказа и idempotency key ¶ const src = $json.body ?? $json; const eventType = String(src.event_type ?? '').trim(); const externalId = String(src.external_id ?? '').trim(); if (!eventType) throw new Error('Missing event_type from 1C'); if (!externalId) throw new Error('Missing external_id from 1C'); const items = Array.isArray(src.items) ? src.items : []; if (items.length === 0) throw new Error('Order has no items'); const normalizedItems = items.map((item, index) => { const quantity = Number(item.quantity ?? 0); const price = Number(item.price ?? 0); if (quantity <= 0) throw new Error(`Invalid quantity at line ${index + 1}`); return { sku: String(item.sku ?? '').trim(), name: String(item.name ?? '').trim(), quantity, price, amount: Number((quantity * price).toFixed(2)), vat: String(item.vat ?? 'none') }; }); const total = normalizedItems.reduce((sum, item) => sum + item.amount, 0); const idempotencyKey = `1c:${eventType}:${externalId}`; return [{ json: { event_type: eventType, external_id: externalId, idempotency_key: idempotencyKey, order_number: String(src.number ?? externalId), customer: src.customer ?? {}, items: normalizedItems, total_calculated: Number(total.toFixed(2)), total_declared: Number(src.total ?? total), status: String(src.status ?? 'new'), received_at: new Date().toISOString() } }]; Почему нельзя отвечать 200 до записи idempotency Если n8n вернёт 200, а потом упадёт до записи external_id в durable storage, 1С будет считать обмен успешным. Сначала сохраняйте idempotency record или результат обработки, затем возвращайте подтверждение. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - 1C HTTP exchange with idempotency", "nodes": [ { "name": "1C Webhook", "type": "n8n-nodes-base.webhook", "purpose": "Принять заказ или статус от 1С" }, { "name": "Normalize 1C order", "type": "n8n-nodes-base.code", "purpose": "Проверить external_id, строки и суммы" }, { "name": "Check idempotency", "type": "n8n-nodes-base.postgres", "purpose": "Не обработать документ повторно" }, { "name": "Upsert CRM or API", "type": "n8n-nodes-base.httpRequest", "purpose": "Создать или обновить целевую систему" }, { "name": "Write exchange log", "type": "n8n-nodes-base.postgres", "purpose": "Сохранить результат, target_id и retry_count" }, { "name": "Respond to 1C", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть код, message и target_id" } ], "connections": "1C Webhook → Normalize 1C order → Check idempotency → Upsert CRM or API → Write exchange log → Respond to 1C" } Пошаговая настройка HTTP-сервиса 1С и webhook n8n ¶ Опишите контракт JSON с разработчиком 1С: event_type, external_id, customer, items, totals. Опубликуйте HTTP-сервис в 1С или настройте регламентную отправку на webhook n8n. Импортируйте workflow и добавьте проверку подписи или Basic/Auth token. Создайте таблицу exchange_log с unique index по idempotency_key. Настройте retry/DLQ для ошибок внешней CRM или API, чтобы 1С не теряла статус. Тесты перед production для обмена с 1С ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/onec-http-exchange" \ -H "Content-Type: application/json" \ --data @onec-http-exchange-payload.json Отправьте один и тот же `external_id` дважды: target object должен остаться один. Проверьте заказ без строк и с отрицательным количеством. Сымитируйте ошибку внешнего API 500 и проверьте retry/DLQ. Отправьте статус по уже созданному заказу и проверьте update, а не create. Сравните `total_declared` и `total_calculated` на строках с НДС и округлением. Production-риски интеграции 1С через HTTP ¶ Нет стабильного external_id. Повторы из 1С превращаются в новые сделки или заказы. Ответ 200 без durable log. 1С считает обмен успешным, хотя downstream API мог упасть. Смешаны разные event types. Статус оплаты случайно обрабатывается как новый заказ. Сумма не сверяется со строками. Внешняя система получает неправильный total. Нет DLQ. Временная ошибка API навсегда теряет документ обмена. Полезные ссылки и смежные workflow ¶ См. также retry и DLQ для HTTP Request , webhook idempotency to Postgres , idempotency keys и ЮKassa → CRM . Официальные документы: 1C:Enterprise documentation , 1C HTTP services и n8n Webhook node . Визуальная карточка показывает external_id, target_id и статус обработки документа обмена. Критерии готовности ¶ У каждого события из 1С есть стабильный external_id. Повторный документ не создаёт второй объект во внешней системе. Ошибки API уходят в retry/DLQ и видны владельцу интеграции. Ответ 1С содержит понятный код, message и target_id. Есть журнал обмена с idempotency_key, event_type, status и retry_count. Нужно связать 1С с CRM или сайтом без дублей? Nodbot спроектирует HTTP-обмен 1С и n8n: контракт данных, idempotency, retry/DLQ, журнал обмена, мониторинг и безопасный rollout. Обсудить интеграцию 1С

## Test payload

```json
{
  "event_type": "order.created",
  "external_id": "1c-doc-000184",
  "number": "Заказ покупателя 000184",
  "date": "2026-05-30T09:45:00+03:00",
  "customer": {
    "name": "ООО Ромашка",
    "inn": "7701000000",
    "phone": "+7 (495) 100-20-30"
  },
  "items": [
    {
      "sku": "N8N-SETUP",
      "name": "Внедрение n8n",
      "quantity": 1,
      "price": 49000,
      "vat": "20%"
    }
  ],
  "total": 49000,
  "currency": "RUB",
  "status": "new"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const eventType = String(src.event_type ?? '').trim();
const externalId = String(src.external_id ?? '').trim();
if (!eventType) throw new Error('Missing event_type from 1C');
if (!externalId) throw new Error('Missing external_id from 1C');

const items = Array.isArray(src.items) ? src.items : [];
if (items.length === 0) throw new Error('Order has no items');

const normalizedItems = items.map((item, index) => {
  const quantity = Number(item.quantity ?? 0);
  const price = Number(item.price ?? 0);
  if (quantity <= 0) throw new Error(`Invalid quantity at line ${index + 1}`);
  return {
    sku: String(item.sku ?? '').trim(),
    name: String(item.name ?? '').trim(),
    quantity,
    price,
    amount: Number((quantity * price).toFixed(2)),
    vat: String(item.vat ?? 'none')
  };
});

const total = normalizedItems.reduce((sum, item) => sum + item.amount, 0);
const idempotencyKey = `1c:${eventType}:${externalId}`;

return [{
  json: {
    event_type: eventType,
    external_id: externalId,
    idempotency_key: idempotencyKey,
    order_number: String(src.number ?? externalId),
    customer: src.customer ?? {},
    items: normalizedItems,
    total_calculated: Number(total.toFixed(2)),
    total_declared: Number(src.total ?? total),
    status: String(src.status ?? 'new'),
    received_at: new Date().toISOString()
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - 1C HTTP exchange with idempotency",
  "nodes": [
    {
      "name": "1C Webhook",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять заказ или статус от 1С"
    },
    {
      "name": "Normalize 1C order",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить external_id, строки и суммы"
    },
    {
      "name": "Check idempotency",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Не обработать документ повторно"
    },
    {
      "name": "Upsert CRM or API",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Создать или обновить целевую систему"
    },
    {
      "name": "Write exchange log",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Сохранить результат, target_id и retry_count"
    },
    {
      "name": "Respond to 1C",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть код, message и target_id"
    }
  ],
  "connections": "1C Webhook → Normalize 1C order → Check idempotency → Upsert CRM or API → Write exchange log → Respond to 1C"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "OpenRouter и n8n: fallback моделей | Nodbot"
source_url: "https://nodbot.ru/workflows/openrouter-model-fallback/"
canonical_url: "https://nodbot.ru/workflows/openrouter-model-fallback/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1028
---

# OpenRouter и n8n: fallback моделей без падения AI-сценария

## AI summary

Workflow для устойчивых AI-сценариев: отправить запрос в OpenRouter с приоритетным списком моделей, зафиксировать фактически использованную модель, обработать rate limit/downtime и вернуть структурированный ответ без ручной перезаписи workflow.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- OpenRouter
- model fallback
- n8n
- AI routing
- budget guard
- structured output

## Source outline

OpenRouter и n8n: fallback моделей без падения AI-сценария ¶ Обновлено: 2026-05-30 AI summary: Workflow для устойчивых AI-сценариев: отправить запрос в OpenRouter с приоритетным списком моделей, зафиксировать фактически использованную модель, обработать rate limit/downtime и вернуть структурированный ответ без ручной перезаписи workflow. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: AI workflow ломается, когда выбранная модель недоступна, уходит в rate limit, дорожает или не помещает запрос в контекст. Одна жёстко заданная модель в HTTP Request превращает автоматизацию в точку отказа. Решение: использовать OpenRouter как слой маршрутизации: n8n готовит безопасный prompt, передаёт массив моделей в порядке приоритета, проверяет фактически использованную модель и логирует стоимость, latency и fallback-причину. Workflow маршрутизирует AI-запрос через OpenRouter и логирует фактически использованную модель. Проблема: почему одна AI-модель в n8n становится точкой отказа ¶ Многие AI-сценарии в n8n начинают с одного HTTP Request к одной модели. Это удобно в демо, но плохо в production: модель может быть временно недоступна, провайдер может вернуть rate limit, а длинный prompt может не пройти по контексту. OpenRouter даёт единый API и маршрутизацию между моделями. Но fallback не отменяет инженерную дисциплину: нужно ограничивать input, контролировать бюджет, логировать выбранную модель и не подменять качество ответа случайной дешёвой моделью без проверки. Архитектура workflow OpenRouter fallback через n8n ¶ Нода Роль Что проверить Webhook input принимает задачу, prompt и требования к ответу нет секретов и лишних данных в prompt Prepare AI request собирает messages, models array и response_format температура, max_tokens, budget Call OpenRouter отправляет запрос в chat completions Authorization, timeout, retry Validate response проверяет JSON и фактическую модель нет пустого ответа и сломанного schema Audit usage пишет model, latency, fallback и cost hints можно расследовать деградацию Respond возвращает структурированный результат без stack trace и raw provider errors Fallback нужен не для хаотичной замены модели, а для сохранения SLA. Если сценарий требует строгого качества, ставьте fallback только на модели сопоставимого класса и добавляйте post-validation. Контракт входных данных для AI-запроса ¶ { "request_id": "ai-task-1042", "task": "classify_support_ticket", "input": "Клиент пишет, что оплата прошла, но доступ не открылся. Просит срочно проверить заказ 10492.", "model_priority": [ "openai/gpt-4o-mini", "anthropic/claude-3.5-haiku", "google/gemini-flash-1.5" ], "max_budget_usd": 0.05, "response_schema": [ "label", "confidence", "reason", "next_action" ] } Передавайте в payload не название “самой любимой модели”, а список допустимых моделей и требования к ответу. Так workflow можно менять без переписывания бизнес-логики. Code Node: сборка запроса с models array и budget guard ¶ const src = $json.body ?? $json; const input = String(src.input ?? '').trim(); if (!input) throw new Error('input is required'); if (input.length > 12000) throw new Error('input is too long for this fallback chain'); const allowedModels = [ 'openai/gpt-4o-mini', 'anthropic/claude-3.5-haiku', 'google/gemini-flash-1.5' ]; const requested = Array.isArray(src.model_priority) ? src.model_priority : allowedModels; const models = requested.filter(m => allowedModels.includes(m)); if (models.length === 0) throw new Error('No allowed models in model_priority'); return [{ json: { request_id: src.request_id ?? `ai-${Date.now()}`, openrouter_body: { models, messages: [ { role: 'system', content: 'Верни только JSON с полями label, confidence, reason, next_action.' }, { role: 'user', content: input } ], temperature: 0.1, max_tokens: 600 }, audit: { requested_models: models, max_budget_usd: Number(src.max_budget_usd ?? 0.05) } } }]; Почему fallback должен быть allowlisted Если дать пользователю произвольный model id, workflow может уйти на дорогую, слабую или неподходящую модель. Allowlist фиксирует качество, стоимость и контекстное окно для конкретного production-сценария. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - OpenRouter model fallback", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять AI-задачу и список допустимых моделей" }, { "name": "Prepare OpenRouter request", "type": "n8n-nodes-base.code", "purpose": "Собрать models array, prompt и guardrails" }, { "name": "Call OpenRouter chat completions", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать OpenRouter API" }, { "name": "Validate structured response", "type": "n8n-nodes-base.code", "purpose": "Проверить JSON и обязательные поля" }, { "name": "Audit model usage", "type": "n8n-nodes-base.postgres", "purpose": "Записать request_id, model и fallback" }, { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть результат вызывающему workflow" } ], "connections": "Webhook input → Prepare OpenRouter request → Call OpenRouter chat completions → Validate structured response → Audit model usage → Respond to Webhook" } Пошаговая настройка OpenRouter, n8n и fallback-цепочки ¶ Создайте OpenRouter API key и сохраните его в n8n credentials или ENV. Составьте allowlist моделей для конкретного сценария: качество, цена, контекст, скорость. Импортируйте workflow и проверьте endpoint OpenRouter chat completions. Настройте post-validation: обязательные поля JSON, confidence и максимальная длина ответа. Добавьте audit log, чтобы видеть, какая модель реально ответила и когда сработал fallback. Тесты перед production и проверка fallback ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/openrouter-model-fallback" \ -H "Content-Type: application/json" \ --data @openrouter-model-fallback-payload.json Запустите обычный запрос и проверьте JSON-структуру ответа. Искусственно уберите основную модель из allowlist и проверьте fallback. Отправьте слишком длинный prompt и убедитесь, что workflow падает до API-вызова. Проверьте rate limit/timeout: пользователь должен получить понятную ошибку. Сравните качество ответов основной и резервных моделей на 20 реальных задачах. Production-риски model fallback и AI routing ¶ Fallback на слабую модель. Сценарий продолжает работать, но качество тихо падает. Нет budget guard. Запросы могут уйти на дорогую модель без контроля. Raw prompt попадает в лог. Маскируйте персональные и коммерческие данные. Нет structured validation. Резервная модель может вернуть красивый текст вместо JSON. Ошибки провайдера показываются пользователю. Возвращайте безопасную business error, а детали пишите в audit. Полезные ссылки и смежные workflow ¶ См. также Ollama local AI summary , YandexGPT classifier и error workflow Telegram alert . Официальные документы: OpenRouter Model Fallbacks , OpenRouter API Reference и n8n HTTP Request . Audit показывает выбранную модель, статус schema validation и бюджетный лимит. Критерии готовности ¶ Модели заданы allowlist-ом, а не произвольным user input. Есть лимит длины prompt, max_tokens, timeout и бюджетный guard. Ответ валидируется как JSON до передачи дальше по workflow. Audit log фиксирует request_id, выбранную модель, latency и ошибку. Fallback-модели проверены на реальных данных, а не только на тестовой фразе. Нужен устойчивый AI workflow без ручной смены моделей? Nodbot настроит OpenRouter fallback, allowlist моделей, budget guard, structured validation, audit log и уведомления об ошибках в n8n. Обсудить AI fallback

## Test payload

```json
{
  "request_id": "ai-task-1042",
  "task": "classify_support_ticket",
  "input": "Клиент пишет, что оплата прошла, но доступ не открылся. Просит срочно проверить заказ 10492.",
  "model_priority": [
    "openai/gpt-4o-mini",
    "anthropic/claude-3.5-haiku",
    "google/gemini-flash-1.5"
  ],
  "max_budget_usd": 0.05,
  "response_schema": [
    "label",
    "confidence",
    "reason",
    "next_action"
  ]
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const input = String(src.input ?? '').trim();
if (!input) throw new Error('input is required');
if (input.length > 12000) throw new Error('input is too long for this fallback chain');

const allowedModels = [
  'openai/gpt-4o-mini',
  'anthropic/claude-3.5-haiku',
  'google/gemini-flash-1.5'
];
const requested = Array.isArray(src.model_priority) ? src.model_priority : allowedModels;
const models = requested.filter(m => allowedModels.includes(m));
if (models.length === 0) throw new Error('No allowed models in model_priority');

return [{
  json: {
    request_id: src.request_id ?? `ai-${Date.now()}`,
    openrouter_body: {
      models,
      messages: [
        { role: 'system', content: 'Верни только JSON с полями label, confidence, reason, next_action.' },
        { role: 'user', content: input }
      ],
      temperature: 0.1,
      max_tokens: 600
    },
    audit: { requested_models: models, max_budget_usd: Number(src.max_budget_usd ?? 0.05) }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - OpenRouter model fallback",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять AI-задачу и список допустимых моделей"
    },
    {
      "name": "Prepare OpenRouter request",
      "type": "n8n-nodes-base.code",
      "purpose": "Собрать models array, prompt и guardrails"
    },
    {
      "name": "Call OpenRouter chat completions",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Вызвать OpenRouter API"
    },
    {
      "name": "Validate structured response",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить JSON и обязательные поля"
    },
    {
      "name": "Audit model usage",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Записать request_id, model и fallback"
    },
    {
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть результат вызывающему workflow"
    }
  ],
  "connections": "Webhook input → Prepare OpenRouter request → Call OpenRouter chat completions → Validate structured response → Audit model usage → Respond to Webhook"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Qdrant RAG и n8n: FAQ-бот без галлюцинаций | Nodbot"
source_url: "https://nodbot.ru/workflows/qdrant-rag-faq-bot/"
canonical_url: "https://nodbot.ru/workflows/qdrant-rag-faq-bot/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1078
---

# Qdrant RAG и n8n: FAQ-бот по базе знаний с контролем источников

## AI summary

Практический RAG workflow для FAQ-бота: принять вопрос, нормализовать язык, получить embedding, найти релевантные chunks в Qdrant, собрать prompt с источниками, отдать ответ только по базе знаний и отправить неуверенные случаи на ручную проверку.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Qdrant
- RAG
- n8n
- FAQ bot
- embeddings
- source citations
- human review

## Source outline

Qdrant RAG и n8n: FAQ-бот по базе знаний с контролем источников ¶ Обновлено: 2026-05-30 AI summary: Практический RAG workflow для FAQ-бота: принять вопрос, нормализовать язык, получить embedding, найти релевантные chunks в Qdrant, собрать prompt с источниками, отдать ответ только по базе знаний и отправить неуверенные случаи на ручную проверку. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: FAQ-бот на LLM быстро отвечает красиво, но без retrieval-слоя он выдумывает тарифы, сроки, ограничения API и внутренние правила. Для поддержки это опаснее, чем медленный ответ человека. Решение: строим RAG-сценарий на n8n и Qdrant: вопрос превращается в embedding, Qdrant возвращает chunks с metadata, Code Node собирает строгий prompt, а модель отвечает только по найденным источникам или честно просит человека уточнить ответ. Workflow принимает вопрос, ищет фрагменты в Qdrant, собирает grounded prompt и возвращает ответ с источниками. Проблема: почему FAQ-бот без RAG начинает галлюцинировать ¶ Запрос “сделать чат-бота по базе знаний” часто звучит просто, но реальная боль начинается после первых неправильных ответов. Модель может уверенно придумать цену, сослаться на несуществующую инструкцию или ответить по старой версии регламента. Пользователь видит быстрый ответ, а команда поддержки получает эскалацию. RAG-бот должен работать как контролируемая поисковая система: сначала найти релевантные фрагменты, затем ограничить модель этими фрагментами, а при низкой уверенности не фантазировать. Поэтому эта инструкция не про “подключить AI к Qdrant”, а про production FAQ-бота с источниками, score, fallback и аудитом. Архитектура workflow Qdrant RAG FAQ-бота ¶ Нода Роль Что проверить Webhook question принимает вопрос, user_id и канал лимит длины, язык, идентификатор сессии Normalize query чистит вопрос и строит audit_key нет prompt injection и скрытых команд Create embedding получает vector для запроса одна модель embedding для индекса и запроса Search Qdrant ищет chunks по vector + фильтрам collection, top_k, score_threshold, metadata Build grounded prompt собирает контекст и источники только найденные chunks, ссылки на документы Answer or human review отвечает или отправляет на проверку confidence gate, no-answer policy, логирование Ключевое правило: embedding модель для загрузки базы знаний и embedding модель для запросов должны совпадать. Если размерность vectors отличается, Qdrant не сможет корректно искать, а если модель изменилась незаметно, качество retrieval упадёт без явной ошибки. Контракт входных данных для вопроса пользователя ¶ { "question": "Как восстановить workflow n8n после сбоя Postgres?", "user_id": "tg-9182", "channel": "telegram", "language": "ru", "filters": { "section": "hosting", "product": "n8n" }, "top_k": 5 } Фильтры в payload нужны, чтобы не искать по всей базе знаний. Для FAQ-бота полезно хранить `section`, `product`, `version`, `locale` и `doc_url` в payload каждого chunk. Code Node: сбор prompt, источников и confidence gate ¶ const src = $json.body ?? $json; const question = String(src.question ?? '').replace(/\s+/g, ' ').trim(); if (question.length < 8) throw new Error('Question is too short for RAG search'); if (question.length > 1200) throw new Error('Question is too long: ask user to shorten it'); const topK = Math.min(Number(src.top_k ?? 5), 8); const filters = src.filters ?? {}; const qdrantFilter = { must: [] }; for (const [key, value] of Object.entries(filters)) { if (value) qdrantFilter.must.push({ key, match: { value } }); } const systemGuard = [ 'Отвечай только по контексту из найденных источников.', 'Если ответа нет в контексте, скажи: "В базе знаний нет точного ответа".', 'Не придумывай тарифы, сроки, ссылки и команды.', 'В конце укажи source_ids использованных фрагментов.' ].join(' '); return [{ json: { question, top_k: topK, qdrant_search: { limit: topK, with_payload: true, filter: qdrantFilter }, system_guard: systemGuard, audit_key: `qdrant-rag:${src.user_id ?? 'anon'}:${Date.now()}`, min_score: Number(src.min_score ?? 0.72) } }]; Почему нужен no-answer policy RAG не гарантирует, что нужный ответ есть в базе. Если top chunks имеют низкий score или противоречат друг другу, безопаснее вернуть “нет точного ответа” и создать задачу на поддержку, чем публиковать уверенную галлюцинацию. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Qdrant RAG FAQ bot", "nodes": [ { "name": "Webhook question", "type": "n8n-nodes-base.webhook", "purpose": "Принять вопрос пользователя" }, { "name": "Normalize query", "type": "n8n-nodes-base.code", "purpose": "Очистить вопрос и собрать фильтр Qdrant" }, { "name": "Create embedding", "type": "n8n-nodes-base.httpRequest", "purpose": "Получить embedding для вопроса" }, { "name": "Search Qdrant points", "type": "n8n-nodes-base.httpRequest", "purpose": "Найти релевантные chunks" }, { "name": "Build grounded prompt", "type": "n8n-nodes-base.code", "purpose": "Собрать prompt с источниками" }, { "name": "Respond or human review", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть ответ или статус review" } ], "connections": "Webhook question → Normalize query → Create embedding → Search Qdrant points → Build grounded prompt → Respond or human review" } Пошаговая настройка Qdrant, embeddings и n8n ¶ Создайте Qdrant collection с размерностью, которая совпадает с embedding моделью. Загрузите chunks базы знаний с metadata: source_id, doc_url, section, locale, updated_at. Импортируйте workflow JSON и задайте Qdrant URL, API key и collection name. Настройте embedding endpoint, который использовался при индексации документов. Укажите score_threshold и ветку human review для слабых совпадений. Тесты перед production и проверка качества RAG ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/qdrant-rag-faq-bot" \ -H "Content-Type: application/json" \ --data @qdrant-rag-faq-bot-payload.json Задайте вопрос, ответ на который точно есть в базе знаний. Задайте вопрос вне базы и проверьте, что бот не выдумывает ответ. Проверьте старый документ и фильтр по `section` или `version`. Отправьте prompt injection вроде “игнорируй инструкции” и проверьте guard. Сравните top chunks и итоговый ответ на 30–50 реальных вопросах поддержки. Production-риски RAG-бота на Qdrant ¶ Нет metadata-фильтров. Бот достаёт похожий текст из неправильного продукта или старой версии документа. Score используется как абсолютная истина. Порог нужно калибровать на реальных вопросах, а не брать из примера. Chunks слишком большие. Модель получает шум и хуже отвечает. Нет обновления индекса. База знаний изменилась, а Qdrant продолжает отдавать старые фрагменты. Нет ссылок на источники. Пользователь не может проверить ответ, а поддержка не видит, почему бот так решил. Полезные ссылки и смежные workflow ¶ См. также RAG в n8n , chunking для RAG , vector store и Telegram AI bot with human approval . Официальные документы: Qdrant collections , Qdrant points , Qdrant search points API и n8n HTTP Request . Визуальная карточка показывает score, источник и решение: ответить или отправить на ручную проверку. Критерии готовности ¶ Collection создана с правильной размерностью vectors. Каждый chunk имеет source_id, doc_url, section и updated_at. Ответ содержит источники или честный no-answer. Prompt injection не отключает guard-инструкции. Есть ручная проверка для низкого score и спорных ответов. Нужен FAQ-бот, который не придумывает ответы? Nodbot настроит RAG на Qdrant: индексацию базы знаний, chunking, embeddings, prompt guard, source_ids, оценку качества и human review для спорных вопросов. Обсудить RAG-бота

## Test payload

```json
{
  "question": "Как восстановить workflow n8n после сбоя Postgres?",
  "user_id": "tg-9182",
  "channel": "telegram",
  "language": "ru",
  "filters": {
    "section": "hosting",
    "product": "n8n"
  },
  "top_k": 5
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const question = String(src.question ?? '').replace(/\s+/g, ' ').trim();
if (question.length < 8) throw new Error('Question is too short for RAG search');
if (question.length > 1200) throw new Error('Question is too long: ask user to shorten it');

const topK = Math.min(Number(src.top_k ?? 5), 8);
const filters = src.filters ?? {};
const qdrantFilter = { must: [] };
for (const [key, value] of Object.entries(filters)) {
  if (value) qdrantFilter.must.push({ key, match: { value } });
}

const systemGuard = [
  'Отвечай только по контексту из найденных источников.',
  'Если ответа нет в контексте, скажи: "В базе знаний нет точного ответа".',
  'Не придумывай тарифы, сроки, ссылки и команды.',
  'В конце укажи source_ids использованных фрагментов.'
].join(' ');

return [{
  json: {
    question,
    top_k: topK,
    qdrant_search: { limit: topK, with_payload: true, filter: qdrantFilter },
    system_guard: systemGuard,
    audit_key: `qdrant-rag:${src.user_id ?? 'anon'}:${Date.now()}`,
    min_score: Number(src.min_score ?? 0.72)
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Qdrant RAG FAQ bot",
  "nodes": [
    {
      "name": "Webhook question",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять вопрос пользователя"
    },
    {
      "name": "Normalize query",
      "type": "n8n-nodes-base.code",
      "purpose": "Очистить вопрос и собрать фильтр Qdrant"
    },
    {
      "name": "Create embedding",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Получить embedding для вопроса"
    },
    {
      "name": "Search Qdrant points",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Найти релевантные chunks"
    },
    {
      "name": "Build grounded prompt",
      "type": "n8n-nodes-base.code",
      "purpose": "Собрать prompt с источниками"
    },
    {
      "name": "Respond or human review",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть ответ или статус review"
    }
  ],
  "connections": "Webhook question → Normalize query → Create embedding → Search Qdrant points → Build grounded prompt → Respond or human review"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Retry и DLQ в n8n: HTTP Request без потерь | Nodbot"
source_url: "https://nodbot.ru/workflows/retry-dlq-http-request/"
canonical_url: "https://nodbot.ru/workflows/retry-dlq-http-request/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1088
---

# Retry и DLQ в n8n: безопасные HTTP-запросы без потерь и дублей

## AI summary

Практический workflow для устойчивых HTTP-интеграций: принять событие, собрать idempotency key, отправить запрос во внешний API, классифицировать ответ, повторить временные ошибки с backoff, а необработанные события положить в DLQ с понятным alert.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- n8n
- HTTP Request
- retry
- DLQ
- dead-letter queue
- idempotency
- API errors
- 429
- 5xx

## Source outline

Retry и DLQ в n8n: безопасные HTTP-запросы без потерь и дублей ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для устойчивых HTTP-интеграций: принять событие, собрать idempotency key, отправить запрос во внешний API, классифицировать ответ, повторить временные ошибки с backoff, а необработанные события положить в DLQ с понятным alert. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: внешний API может вернуть 429, 502 или timeout именно в момент, когда заявка уже принята бизнесом. Если n8n просто падает на HTTP Request, событие теряется или вручную перезапускается с риском дубля. Решение: строим retry/DLQ-слой в n8n: отделяем временные ошибки от постоянных, добавляем backoff, сохраняем payload и idempotency key, отправляем alert владельцу и даём команде безопасный способ переиграть событие. Workflow отправляет HTTP Request, классифицирует ответ, повторяет 429/5xx и сохраняет необработанные события в DLQ. Проблема: почему HTTP Request в n8n теряет события при 429 и 5xx ¶ Типичная интеграция выглядит безобидно: Webhook принимает заявку, HTTP Request отправляет её в CRM или склад, а дальше workflow завершается. Но production живёт иначе: API ограничивает частоту запросов, прокси рвёт соединение, токен истекает, а downstream-сервис отвечает 502 после того, как часть операции уже выполнена. Без retry и DLQ команда не понимает, какие события действительно обработаны, какие можно повторить, а какие нужно исправлять вручную. Эта статья решает конкретную боль интеграторов: как сделать HTTP Request в n8n устойчивым к временным сбоям и при этом не создать дубли при повторной отправке. Архитектура workflow retry/DLQ для HTTP-интеграции ¶ Нода Роль Что проверить Webhook or Trigger получает бизнес-событие event_id, source, payload, дедупликационный ключ Prepare API request собирает endpoint, headers и body нет секретов в тексте execution, timeout задан явно HTTP Request отправляет запрос во внешний API response code, response body, retryable network errors Classify response разделяет success, retry и DLQ 429/5xx/timeout не смешаны с 400/422 Retry with backoff повторяет временные ошибки attempt_count, next_retry_at, max attempts Dead-letter queue сохраняет необработанное событие payload, причина, владелец, ссылка на execution Главная SEO-и практическая разница между “retry” и “просто перезапустить workflow” — наличие контекста. В DLQ должен лежать исходный payload, статус API, число попыток, idempotency key и понятная причина, чтобы повтор был безопасным. Контракт входных данных для API-запроса ¶ { "event_id": "lead-10492", "source": "landing-webhook", "target": "crm-api", "idempotency_key": "landing:lead-10492", "customer": { "name": "Мария", "phone": "+7 (916) 555-12-34" }, "request": { "method": "POST", "url": "https://api.example.ru/leads", "body": { "name": "Мария", "phone": "+79165551234" } }, "attempt": 1 } `event_id` и `idempotency_key` обязательны. Если внешний API поддерживает заголовок `Idempotency-Key`, передавайте туда тот же ключ. Если не поддерживает — храните ключ в Postgres и не повторяйте бизнес-действие вслепую. Code Node: классификация ответа, retry и DLQ route ¶ const src = $json.body ?? $json; const status = Number(src.http_status ?? src.statusCode ?? 0); const attempt = Number(src.attempt ?? 1); const maxAttempts = Number(src.max_attempts ?? 5); const idempotencyKey = String(src.idempotency_key ?? src.event_id ?? '').trim(); if (!idempotencyKey) throw new Error('Missing idempotency_key for retry workflow'); const retryableStatus = [408, 409, 425, 429, 500, 502, 503, 504]; const isNetworkError = String(src.error ?? '').toLowerCase().includes('timeout'); const retryable = retryableStatus.includes(status) || isNetworkError; const permanentFailure = status >= 400 && status < 500 && !retryable; const delaySeconds = Math.min(900, Math.pow(2, attempt) * 15); let route = 'success'; if (retryable && attempt < maxAttempts) route = 'retry'; if (retryable && attempt >= maxAttempts) route = 'dlq'; if (permanentFailure) route = 'dlq'; return [{ json: { route, idempotency_key: idempotencyKey, attempt, max_attempts: maxAttempts, next_attempt: attempt + 1, retry_after_seconds: delaySeconds, status, reason: src.error ?? src.response?.message ?? 'classified_by_retry_policy', original_payload: src.original_payload ?? src } }]; Почему 400 и 500 нельзя обрабатывать одинаково 400/422 обычно означают ошибку данных и должны уходить в DLQ с описанием. 429/502/503 чаще временные: их можно повторять с backoff, но только с idempotency key и лимитом попыток. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - HTTP Request retry and DLQ policy", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять событие и idempotency key" }, { "name": "Prepare HTTP request", "type": "n8n-nodes-base.code", "purpose": "Собрать endpoint, headers, body и timeout" }, { "name": "Send HTTP Request", "type": "n8n-nodes-base.httpRequest", "purpose": "Отправить запрос во внешний API" }, { "name": "Classify API response", "type": "n8n-nodes-base.code", "purpose": "Разделить success/retry/DLQ" }, { "name": "Retry gate", "type": "n8n-nodes-base.if", "purpose": "Проверить лимит попыток и статус" }, { "name": "Write DLQ record", "type": "n8n-nodes-base.postgres", "purpose": "Сохранить payload, reason и execution URL" }, { "name": "Respond", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть безопасный результат" } ], "connections": "Webhook input → Prepare HTTP request → Send HTTP Request → Classify API response → Retry gate → Write DLQ record → Respond" } Пошаговая настройка retry, backoff и DLQ в n8n ¶ Импортируйте workflow и замените endpoint внешнего API. Добавьте idempotency key в payload и, если API поддерживает, в header `Idempotency-Key`. Создайте таблицу DLQ с полями idempotency_key, payload, reason, attempt, status. Настройте retry policy: 429/5xx/timeout повторять, 400/422 отправлять в DLQ. Добавьте Telegram/Slack alert только после записи DLQ, чтобы не потерять контекст. Тесты перед production и проверка повторов ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/retry-dlq-http-request" \ -H "Content-Type: application/json" \ --data @retry-dlq-http-request-payload.json Сымитируйте 200 OK и проверьте, что запись не попадает в DLQ. Сымитируйте 429 и убедитесь, что route = retry, а delay растёт. Сымитируйте 422 и проверьте route = dlq без повторов. Запустите один и тот же event_id дважды и проверьте idempotency. Отключите внешний API и убедитесь, что после max_attempts событие попадает в DLQ. Production-риски retry и dead-letter queue ¶ Retry без idempotency. Повтор может создать вторую сделку, списание или заявку. Бесконечные повторы. Workflow забивает очередь и маскирует настоящую ошибку данных. DLQ без payload. Нельзя безопасно восстановить событие после инцидента. Alert до записи DLQ. Уведомление пришло, но контекст потерян при сбое. Все ошибки считаются временными. 400/422 будут повторяться зря и увеличивать нагрузку. Полезные ссылки и смежные workflow ¶ См. также webhook idempotency to Postgres , Error Workflow → Telegram alert , retry/DLQ pattern и ЮKassa → CRM с idempotency . Официальные документы: n8n HTTP Request node , n8n error handling и HTTP status codes . Визуальная карточка показывает route, attempt, статус API и следующий шаг обработки. Критерии готовности ¶ Retryable-статусы отделены от ошибок данных. Каждый повтор использует idempotency key. DLQ хранит исходный payload, reason, status и attempt_count. Есть лимит попыток и понятный backoff. Команда знает, как безопасно переиграть DLQ-событие. Нужно, чтобы API-интеграции не теряли события? Nodbot настроит retry/DLQ-слой в n8n: классификацию ошибок, idempotency, журнал восстановления, alert и безопасные повторы. Настроить надежный HTTP workflow

## Test payload

```json
{
  "event_id": "lead-10492",
  "source": "landing-webhook",
  "target": "crm-api",
  "idempotency_key": "landing:lead-10492",
  "customer": {
    "name": "Мария",
    "phone": "+7 (916) 555-12-34"
  },
  "request": {
    "method": "POST",
    "url": "https://api.example.ru/leads",
    "body": {
      "name": "Мария",
      "phone": "+79165551234"
    }
  },
  "attempt": 1
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const status = Number(src.http_status ?? src.statusCode ?? 0);
const attempt = Number(src.attempt ?? 1);
const maxAttempts = Number(src.max_attempts ?? 5);
const idempotencyKey = String(src.idempotency_key ?? src.event_id ?? '').trim();

if (!idempotencyKey) throw new Error('Missing idempotency_key for retry workflow');

const retryableStatus = [408, 409, 425, 429, 500, 502, 503, 504];
const isNetworkError = String(src.error ?? '').toLowerCase().includes('timeout');
const retryable = retryableStatus.includes(status) || isNetworkError;
const permanentFailure = status >= 400 && status < 500 && !retryable;
const delaySeconds = Math.min(900, Math.pow(2, attempt) * 15);

let route = 'success';
if (retryable && attempt < maxAttempts) route = 'retry';
if (retryable && attempt >= maxAttempts) route = 'dlq';
if (permanentFailure) route = 'dlq';

return [{
  json: {
    route,
    idempotency_key: idempotencyKey,
    attempt,
    max_attempts: maxAttempts,
    next_attempt: attempt + 1,
    retry_after_seconds: delaySeconds,
    status,
    reason: src.error ?? src.response?.message ?? 'classified_by_retry_policy',
    original_payload: src.original_payload ?? src
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - HTTP Request retry and DLQ policy",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять событие и idempotency key"
    },
    {
      "name": "Prepare HTTP request",
      "type": "n8n-nodes-base.code",
      "purpose": "Собрать endpoint, headers, body и timeout"
    },
    {
      "name": "Send HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Отправить запрос во внешний API"
    },
    {
      "name": "Classify API response",
      "type": "n8n-nodes-base.code",
      "purpose": "Разделить success/retry/DLQ"
    },
    {
      "name": "Retry gate",
      "type": "n8n-nodes-base.if",
      "purpose": "Проверить лимит попыток и статус"
    },
    {
      "name": "Write DLQ record",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Сохранить payload, reason и execution URL"
    },
    {
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть безопасный результат"
    }
  ],
  "connections": "Webhook input → Prepare HTTP request → Send HTTP Request → Classify API response → Retry gate → Write DLQ record → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "RSS в Telegram через n8n: дайджест без спама | Nodbot"
source_url: "https://nodbot.ru/workflows/rss-to-telegram-news-digest/"
canonical_url: "https://nodbot.ru/workflows/rss-to-telegram-news-digest/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 935
---

# RSS-дайджест в Telegram через n8n: фильтр новостей, дедупликация и Markdown

## AI summary

Практический сценарий RSS → Telegram через n8n: читать ленты по расписанию, отсеивать нерелевантные новости, не публиковать один GUID дважды и отправлять аккуратный digest в канал.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API/CMS/мессенджер, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему RSS-автопостинг быстро превращается в спам
- Архитектура workflow RSS → n8n → Telegram
- Конфигурация входных лент
- Фильтр тем, дедупликация GUID и Markdown
- Готовый workflow JSON
- Пошаговая настройка RSS-дайджеста
- Тесты перед production
- Production-риски Telegram-канала
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- RSS to Telegram
- новостной дайджест
- GUID dedupe
- Telegram Bot API
- n8n RSS Read

## Source outline

RSS-дайджест в Telegram через n8n: фильтр новостей, дедупликация и Markdown ¶ Обновлено: 2026-05-30 AI summary: Практический сценарий RSS → Telegram через n8n: читать ленты по расписанию, отсеивать нерелевантные новости, не публиковать один GUID дважды и отправлять аккуратный digest в канал. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему RSS-автопостинг быстро превращается в спам Архитектура workflow RSS → n8n → Telegram Конфигурация входных лент Фильтр тем, дедупликация GUID и Markdown Готовый workflow JSON Пошаговая настройка RSS-дайджеста Тесты перед production Production-риски Telegram-канала Полезные ссылки и смежные workflow Критерии готовности Проблема: прямой RSS-автопостинг быстро засоряет Telegram-канал повторами, нерелевантными новостями и сломанной разметкой. Решение: надежный workflow читает ленты по расписанию, фильтрует темы, сохраняет GUID, собирает короткий digest и отправляет его в Telegram с контролируемым HTML/Markdown. Workflow превращает несколько RSS-лент в короткий дайджест с фильтром и dedupe. Проблема: почему RSS-автопостинг быстро превращается в спам ¶ RSS-лента удобна для мониторинга новостей, но прямой автопостинг в Telegram почти всегда портит канал. В ленте появляются пресс-релизы, повторы, нерелевантные темы, одинаковые GUID и длинные заголовки без контекста. Подписчик видит не дайджест, а поток мусора. Правильный RSS to Telegram workflow через n8n должен работать как редакционный фильтр: читать несколько лент, проверять ключевые слова, исключать спам, сохранять dedupe key и отправлять короткое сообщение в Markdown/HTML. Архитектура workflow RSS → n8n → Telegram ¶ Нода Роль Что проверить Schedule Trigger Запускает workflow по расписанию частота, часовой пояс, ночные окна Read RSS feeds Получает элементы лент URL, SSL, пустые ленты, дата публикации Filter and build digest Фильтрует темы и собирает сообщение include/exclude keywords, длина Telegram Check dedupe store Проверяет GUID хранилище вне памяти n8n Send Telegram digest Публикует дайджест chat_id, parse_mode, web preview Конфигурация входных лент ¶ { "feeds": [ "https://example.com/rss.xml", "https://example.org/feed" ], "telegram_chat_id": "-1001234567890", "include_keywords": [ "n8n", "automation", "AI agent", "CRM" ], "exclude_keywords": [ "casino", "press release", "giveaway" ], "max_items": 5, "utm_source": "telegram", "utm_medium": "digest", "utm_campaign": "rss_n8n_digest" } Храните конфигурацию лент отдельно от кода workflow. Так контент-менеджер сможет добавить источник или исключающее слово без редактирования нод. Фильтр тем, дедупликация GUID и Markdown ¶ const cfg = $json.config ?? $json; const items = $json.items ?? [$json]; const include = (cfg.include_keywords ?? []).map(v => String(v).toLowerCase()); const exclude = (cfg.exclude_keywords ?? []).map(v => String(v).toLowerCase()); const maxItems = Number(cfg.max_items ?? 5); const normalized = items.map(item => { const title = String(item.title ?? '').trim(); const link = String(item.link ?? item.guid ?? '').trim(); const text = `${title} ${item.contentSnippet ?? item.content ?? ''}`.toLowerCase(); const excluded = exclude.some(word => text.includes(word)); const included = include.length === 0 || include.some(word => text.includes(word)); return { title, link, guid: String(item.guid ?? link), included, excluded }; }).filter(i => i.title && i.link && i.included && !i.excluded) .slice(0, maxItems); if (!normalized.length) { return [{ json: { action: 'skip', reason: 'no_relevant_items' } }]; } const lines = normalized.map((item, index) => { const safeTitle = item.title.replace(/[<>]/g, ''); const separator = item.link.includes('?') ? '&' : '?'; const url = `${item.link}${separator}utm_source=${cfg.utm_source ?? 'telegram'}&utm_medium=${cfg.utm_medium ?? 'digest'}&utm_campaign=${cfg.utm_campaign ?? 'rss_digest'}`; return `${index + 1}. <a href="${url}">${safeTitle}</a>`; }); return [{ json: { action: 'send_digest', dedupe_keys: normalized.map(i => `rss:${i.guid}`), telegram: { chat_id: cfg.telegram_chat_id, parse_mode: 'HTML', disable_web_page_preview: true, text: `<b>Дайджест автоматизации</b> ${lines.join(' ')} #n8n #automation` } } }]; Почему используется HTML parse_mode Telegram Markdown легко ломается на символах из заголовков. HTML parse_mode проще контролировать: достаточно удалить опасные символы и не вставлять пользовательский HTML без очистки. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - RSS to Telegram digest with dedupe", "nodes": [ { "name": "Schedule Trigger", "type": "n8n-nodes-base.scheduleTrigger", "purpose": "Запустить дайджест по расписанию" }, { "name": "Read RSS feeds", "type": "n8n-nodes-base.rssFeedRead", "purpose": "Получить новые записи из RSS" }, { "name": "Filter and build digest", "type": "n8n-nodes-base.code", "purpose": "Отфильтровать темы, собрать Markdown/HTML и dedupe keys" }, { "name": "Check dedupe store", "type": "n8n-nodes-base.httpRequest", "purpose": "Не отправлять опубликованные GUID повторно" }, { "name": "Send Telegram digest", "type": "n8n-nodes-base.telegram", "purpose": "Опубликовать аккуратный дайджест в канал" } ], "connections": "Schedule → RSS → Filter → Dedupe → Telegram" } Пошаговая настройка RSS-дайджеста ¶ Соберите список RSS-источников и проверьте, что они стабильно отдают XML. Настройте Telegram Bot token и добавьте бота администратором канала. Опишите include/exclude keywords и лимит новостей в одном дайджесте. Подключите durable dedupe store: Postgres, Redis или таблицу с уникальным GUID. Проверьте сообщение в тестовом канале до публикации в основной. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/rss-to-telegram-news-digest" \ -H "Content-Type: application/json" \ --data @rss-to-telegram-news-digest-payload.json Протестируйте свежую новость, повторный GUID, пустую ленту, заголовок с HTML-символами и слишком длинный дайджест. Workflow должен либо отправить аккуратное сообщение, либо вернуть skip с понятной причиной. Production-риски Telegram-канала ¶ Нет дедупликации. После рестарта workflow может отправить старые новости заново. Слишком частое расписание. Канал получает поток отдельных постов вместо дайджеста. Ломается parse_mode. Один символ в заголовке может сорвать всю публикацию. Нерелевантные источники. Без exclude keywords в канал попадут пресс-релизы и мусор. Нет ручного override. Для важных каналов нужен режим “сначала в приватный чат на approval”. Полезные ссылки и смежные workflow ¶ См. также Telegram bot с human approval , Telegram alert для ошибок , идемпотентные ключи . Официальные документы: n8n RSS Read и Telegram Bot API . Дайджест должен быть коротким, предсказуемым и без повторов по GUID. Критерии готовности ¶ Повторный GUID не публикуется второй раз. В канале нет нерелевантных тем из exclude list. Сообщение проходит Telegram parse_mode без ошибок. Есть тестовый канал и ручной override для важных выпусков. UTM-метки добавляются к ссылкам одинаково. Хотите Telegram-дайджест без спама? Nodbot настроит RSS-источники, фильтр тем, dedupe store, форматирование и режим ручного approval для вашего канала. Настроить дайджест

## Test payload

```json
{
  "feeds": [
    "https://example.com/rss.xml",
    "https://example.org/feed"
  ],
  "telegram_chat_id": "-1001234567890",
  "include_keywords": [
    "n8n",
    "automation",
    "AI agent",
    "CRM"
  ],
  "exclude_keywords": [
    "casino",
    "press release",
    "giveaway"
  ],
  "max_items": 5,
  "utm_source": "telegram",
  "utm_medium": "digest",
  "utm_campaign": "rss_n8n_digest"
}
```

## Key implementation snippet

```javascript
const cfg = $json.config ?? $json;
const items = $json.items ?? [$json];
const include = (cfg.include_keywords ?? []).map(v => String(v).toLowerCase());
const exclude = (cfg.exclude_keywords ?? []).map(v => String(v).toLowerCase());
const maxItems = Number(cfg.max_items ?? 5);

const normalized = items.map(item => {
  const title = String(item.title ?? '').trim();
  const link = String(item.link ?? item.guid ?? '').trim();
  const text = `${title} ${item.contentSnippet ?? item.content ?? ''}`.toLowerCase();
  const excluded = exclude.some(word => text.includes(word));
  const included = include.length === 0 || include.some(word => text.includes(word));
  return { title, link, guid: String(item.guid ?? link), included, excluded };
}).filter(i => i.title && i.link && i.included && !i.excluded)
  .slice(0, maxItems);

if (!normalized.length) {
  return [{ json: { action: 'skip', reason: 'no_relevant_items' } }];
}

const lines = normalized.map((item, index) => {
  const safeTitle = item.title.replace(/[<>]/g, '');
  const separator = item.link.includes('?') ? '&' : '?';
  const url = `${item.link}${separator}utm_source=${cfg.utm_source ?? 'telegram'}&utm_medium=${cfg.utm_medium ?? 'digest'}&utm_campaign=${cfg.utm_campaign ?? 'rss_digest'}`;
  return `${index + 1}. <a href="${url}">${safeTitle}</a>`;
});

return [{
  json: {
    action: 'send_digest',
    dedupe_keys: normalized.map(i => `rss:${i.guid}`),
    telegram: {
      chat_id: cfg.telegram_chat_id,
      parse_mode: 'HTML',
      disable_web_page_preview: true,
      text: `<b>Дайджест автоматизации</b>

${lines.join('
')}

#n8n #automation`
    }
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - RSS to Telegram digest with dedupe",
  "nodes": [
    {
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "purpose": "Запустить дайджест по расписанию"
    },
    {
      "name": "Read RSS feeds",
      "type": "n8n-nodes-base.rssFeedRead",
      "purpose": "Получить новые записи из RSS"
    },
    {
      "name": "Filter and build digest",
      "type": "n8n-nodes-base.code",
      "purpose": "Отфильтровать темы, собрать Markdown/HTML и dedupe keys"
    },
    {
      "name": "Check dedupe store",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Не отправлять опубликованные GUID повторно"
    },
    {
      "name": "Send Telegram digest",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Опубликовать аккуратный дайджест в канал"
    }
  ],
  "connections": "Schedule → RSS → Filter → Dedupe → Telegram"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Telegram AI-бот с human approval через n8n | Nodbot"
source_url: "https://nodbot.ru/workflows/telegram-ai-bot-human-approval/"
canonical_url: "https://nodbot.ru/workflows/telegram-ai-bot-human-approval/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 937
---

# Telegram AI-бот через n8n: human approval перед ответом пользователю

## AI summary

Практический сценарий Telegram AI-бота на n8n: бот готовит черновик ответа, отправляет его оператору на approve/reject и пишет пользователю только после человеческого подтверждения.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему AI-бот без approval опасен для поддержки
- Архитектура workflow Telegram AI-бота с human approval
- Контракт входного сообщения Telegram
- Скрипт n8n для черновика, guardrails и callback data
- Готовый workflow JSON
- Пошаговая настройка Telegram бота, n8n и модерации
- Тесты перед production
- Production-риски AI-бота в Telegram
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Telegram AI bot
- human approval
- n8n Telegram Trigger
- callback query
- guardrails

## Source outline

Telegram AI-бот через n8n: human approval перед ответом пользователю ¶ Обновлено: 2026-05-30 AI summary: Практический сценарий Telegram AI-бота на n8n: бот готовит черновик ответа, отправляет его оператору на approve/reject и пишет пользователю только после человеческого подтверждения. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему AI-бот без approval опасен для поддержки Архитектура workflow Telegram AI-бота с human approval Контракт входного сообщения Telegram Скрипт n8n для черновика, guardrails и callback data Готовый workflow JSON Пошаговая настройка Telegram бота, n8n и модерации Тесты перед production Production-риски AI-бота в Telegram Полезные ссылки и смежные workflow Критерии готовности Проблема: AI-бот в Telegram может быстро ответить неверно в чувствительном сценарии: оплата, договор, возврат, персональные данные или нестандартное обещание менеджера. Решение: надежный workflow в n8n готовит черновик ответа, показывает его оператору с кнопками approve/reject и отправляет пользователю только подтвержденный текст. AI ускоряет подготовку ответа, но финальное решение остается за человеком. Проблема: почему AI-бот без approval опасен для поддержки ¶ Интеграция Telegram и n8n позволяет быстро собрать AI-бота, который отвечает пользователю почти мгновенно. Но в реальной поддержке мгновенность не всегда равна качеству. Клиент может спросить про оплату, возврат, договор, персональные данные или нестандартное обещание менеджера. Если скрипт n8n сразу отправит LLM-ответ в чат, ошибка станет публичной коммуникацией компании. Human approval решает эту боль: модель готовит черновик, оператор видит исходное сообщение, риск-флаги и вариант ответа, а пользователь получает финальный текст только после подтверждения. Такой workflow подходит для Telegram-поддержки, pre-sale консультаций, внутренних helpdesk-ботов и команд, которые хотят ускорить ответы без потери контроля. Архитектура workflow Telegram AI-бота с human approval ¶ Нода Роль Что проверить Telegram Trigger Принимает сообщение или callback Bot token, chat_id, тип update Prepare AI draft Готовит черновик и risk flags нет персональных данных в prompt без нужды Send to moderator Отправляет карточку оператору inline-кнопки approve/reject, короткий текст Approval gate Проверяет решение человека callback data не длиннее лимита и содержит id Send final answer Пишет пользователю ответ только после approve Контракт входного сообщения Telegram ¶ { "message": { "message_id": 1042, "chat": { "id": 912345678, "type": "private" }, "from": { "id": 912345678, "username": "client_ru" }, "text": "Здравствуйте, можно ли перенести оплату на завтра?" }, "bot_profile": "support", "moderator_chat_id": "-1001234567890" } Для production храните соответствие `approval_id → chat_id → draft_text` в durable store: Postgres, Redis или таблице. Нельзя полагаться только на execution memory, потому что n8n может перезапуститься между отправкой черновика и нажатием кнопки оператором. Скрипт n8n для черновика, guardrails и callback data ¶ const update = $json.message ? $json : ($json.body ?? $json); const msg = update.message ?? {}; const text = String(msg.text ?? '').trim(); const userId = msg.from?.id ?? msg.chat?.id; const chatId = msg.chat?.id; if (!text) { return [{ json: { action: 'ignore', reason: 'empty_or_non_text_message' } }]; } const risky = /(возврат|договор|претенз|персональн|паспорт|карта|оплат|юрид)/i.test(text); const draft = `Черновик ответа: спасибо за обращение. Я проверю возможность переноса оплаты и вернусь с подтверждением.`; const approvalId = `tg-ai:${chatId}:${msg.message_id}`; return [{ json: { action: 'request_approval', chat_id: chatId, user_id: userId, original_message_id: msg.message_id, original_text: text, risky, approval_id: approvalId, draft_text: draft, moderator_text: `Нужен approve перед ответом пользователю\n\nВопрос: ${text}\n\n${draft}`, callback_approve: `approve:${approvalId}`, callback_reject: `reject:${approvalId}` } }]; Почему callback data лучше делать коротким Telegram ограничивает размер callback data, а длинные JSON-объекты в кнопке плохо дебажить. Передавайте короткий `approval_id`, а полный черновик и исходное сообщение храните отдельно. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Telegram AI bot with human approval", "nodes": [ { "name": "Telegram Trigger", "type": "n8n-nodes-base.telegramTrigger", "purpose": "Получить сообщение или callback_query от Telegram" }, { "name": "Prepare AI draft", "type": "n8n-nodes-base.code", "purpose": "Собрать черновик, риск-флаги и callback data" }, { "name": "Send to moderator", "type": "n8n-nodes-base.telegram", "purpose": "Показать оператору черновик с кнопками Approve/Reject" }, { "name": "Approval gate", "type": "n8n-nodes-base.if", "purpose": "Отправить ответ пользователю только после approve" }, { "name": "Send final answer", "type": "n8n-nodes-base.telegram", "purpose": "Вернуть подтвержденный текст пользователю" } ], "connections": "Telegram Trigger → Prepare draft → Moderator → Approval gate → Send final answer" } Пошаговая настройка Telegram бота, n8n и модерации ¶ Создайте бота через BotFather и подключите Telegram credentials в n8n. Добавьте Telegram Trigger и проверьте получение обычных сообщений и callback query. Настройте LLM-провайдера, системный prompt и запрет на обещания вне базы знаний. Создайте приватный moderator chat и отправляйте туда карточку approval. Добавьте хранилище approval-состояний и TTL для старых черновиков. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/telegram-ai-bot-human-approval" \ -H "Content-Type: application/json" \ --data @telegram-ai-bot-human-approval-payload.json Проверьте обычный вопрос, вопрос про оплату, reject, повторный callback, удаленный черновик и сообщение без текста. В каждом случае workflow должен либо ждать оператора, либо безопасно завершаться без ответа пользователю. Production-риски AI-бота в Telegram ¶ Ответ уходит без approve. Это главный риск: проверьте ветвление callback и условия отправки. Потеря контекста после рестарта. Approval-состояние должно жить в базе, а не в памяти execution. Утечка данных в prompt. Не отправляйте в LLM лишние персональные данные и токены. Сломанный Markdown. Экранируйте текст перед отправкой в Telegram. Нет SLA. Если оператор не ответил, пользователю нужно отправить нейтральное сообщение о принятии обращения. Полезные ссылки и смежные workflow ¶ См. также роутер команд Telegram-бота , Telegram alert для ошибок , RAG FAQ bot на Qdrant . Официальные документы: Telegram Bot API , n8n Telegram Trigger и n8n Telegram node . Оператор видит исходное сообщение, риск-флаг, черновик и кнопки решения. Критерии готовности ¶ AI-ответ не отправляется без approve. Есть reject-сценарий и ручной текст оператора. Approval-состояния сохраняются в durable store. Markdown/HTML экранируется перед отправкой. Ошибки Telegram API уходят в alert, а не теряются в execution. Нужен AI-бот без риска самовольных ответов? Nodbot настроит Telegram-бота с approval, guardrails, журналом решений, SLA и безопасной отправкой сообщений пользователям. Обсудить AI-бота

## Test payload

```json
{
  "message": {
    "message_id": 1042,
    "chat": {
      "id": 912345678,
      "type": "private"
    },
    "from": {
      "id": 912345678,
      "username": "client_ru"
    },
    "text": "Здравствуйте, можно ли перенести оплату на завтра?"
  },
  "bot_profile": "support",
  "moderator_chat_id": "-1001234567890"
}
```

## Key implementation snippet

```javascript
const update = $json.message ? $json : ($json.body ?? $json);
const msg = update.message ?? {};
const text = String(msg.text ?? '').trim();
const userId = msg.from?.id ?? msg.chat?.id;
const chatId = msg.chat?.id;

if (!text) {
  return [{ json: { action: 'ignore', reason: 'empty_or_non_text_message' } }];
}

const risky = /(возврат|договор|претенз|персональн|паспорт|карта|оплат|юрид)/i.test(text);
const draft = `Черновик ответа: спасибо за обращение. Я проверю возможность переноса оплаты и вернусь с подтверждением.`;
const approvalId = `tg-ai:${chatId}:${msg.message_id}`;

return [{
  json: {
    action: 'request_approval',
    chat_id: chatId,
    user_id: userId,
    original_message_id: msg.message_id,
    original_text: text,
    risky,
    approval_id: approvalId,
    draft_text: draft,
    moderator_text: `Нужен approve перед ответом пользователю\n\nВопрос: ${text}\n\n${draft}`,
    callback_approve: `approve:${approvalId}`,
    callback_reject: `reject:${approvalId}`
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Telegram AI bot with human approval",
  "nodes": [
    {
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "purpose": "Получить сообщение или callback_query от Telegram"
    },
    {
      "name": "Prepare AI draft",
      "type": "n8n-nodes-base.code",
      "purpose": "Собрать черновик, риск-флаги и callback data"
    },
    {
      "name": "Send to moderator",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Показать оператору черновик с кнопками Approve/Reject"
    },
    {
      "name": "Approval gate",
      "type": "n8n-nodes-base.if",
      "purpose": "Отправить ответ пользователю только после approve"
    },
    {
      "name": "Send final answer",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Вернуть подтвержденный текст пользователю"
    }
  ],
  "connections": "Telegram Trigger → Prepare draft → Moderator → Approval gate → Send final answer"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Telegram bot router через n8n: команды без хаоса | Nodbot"
source_url: "https://nodbot.ru/workflows/telegram-bot-command-router/"
canonical_url: "https://nodbot.ru/workflows/telegram-bot-command-router/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 931
---

# Telegram Bot Command Router через n8n: команды, роли и безопасные ответы

## AI summary

Страница показывает, как собрать Telegram command router в n8n: принять update, распознать команду, проверить роль пользователя, отправить нужную ветку и не раскрыть служебные данные.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему Telegram-бот без роутера превращается в набор if-ов
- Архитектура command router в n8n
- Контракт Telegram update
- Code Node для парсинга команд и ролей
- Готовый workflow JSON
- Пошаговая настройка команд Telegram-бота
- Тесты перед production
- Production-риски command router
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Telegram command router
- n8n Telegram bot
- roles
- callback query
- safe replies

## Source outline

Telegram Bot Command Router через n8n: команды, роли и безопасные ответы ¶ Обновлено: 2026-05-30 AI summary: Страница показывает, как собрать Telegram command router в n8n: принять update, распознать команду, проверить роль пользователя, отправить нужную ветку и не раскрыть служебные данные. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: почему Telegram-бот без роутера превращается в набор if-ов Архитектура command router в n8n Контракт Telegram update Code Node для парсинга команд и ролей Готовый workflow JSON Пошаговая настройка команд Telegram-бота Тесты перед production Production-риски command router Полезные ссылки и смежные workflow Критерии готовности Проблема: по мере роста Telegram-бота команды, роли, callback-кнопки и API-вызовы превращаются в хаотичный набор IF-веток, который трудно тестировать и безопасно расширять. Решение: workflow в n8n должен сначала распознать команду, проверить роль пользователя, выбрать короткий action и только потом запускать нужную ветку или внутренний API. Router отделяет распознавание команды от бизнес-логики и безопасного ответа. Проблема: почему Telegram-бот без роутера превращается в набор if-ов ¶ Первые команды Telegram-бота обычно выглядят просто: `/start`, `/help`, `/status`. Потом появляются роли, callback-кнопки, админские операции, интеграция с CRM и внутренними API. Если всё это наращивать отдельными IF-нодами, workflow становится хрупким: одна новая команда ломает старую ветку, а служебная ошибка может уйти пользователю в чат. Command router — это слой, который отделяет распознавание команды от бизнес-логики. Он принимает update, нормализует команду, проверяет пользователя, выбирает action и только затем передает данные дальше. Такой подход нужен для ботов поддержки, кабинетов клиентов, внутренних Telegram-панелей и автоматизации продаж. Архитектура command router в n8n ¶ Нода Роль Что проверить Telegram Trigger Получает message/callback_query тип update, chat_id, from.id Route command and role Парсит команду и аргументы команды с @botname, пустой текст, callback data Execute route Вызывает нужный workflow/API админские ветки после role check Format safe reply Готовит текст ответа без токенов, stack trace и внутренних ID Send Telegram response Отправляет сообщение parse_mode, длина текста, права бота Контракт Telegram update ¶ { "message": { "message_id": 77, "chat": { "id": -1001234567890, "type": "supergroup" }, "from": { "id": 501, "username": "manager" }, "text": "/status order_1042" }, "allowed_admins": [ 501, 777 ], "public_commands": [ "/start", "/help", "/status" ] } В production список ролей лучше хранить не в самом workflow, а в таблице, Redis или CRM. Так можно менять права без деплоя n8n и вести журнал, кто запускал чувствительные команды. Code Node для парсинга команд и ролей ¶ const update = $json.message ? $json : ($json.body ?? $json); const msg = update.message ?? update.callback_query?.message ?? {}; const text = String(update.callback_query?.data ?? msg.text ?? '').trim(); const userId = update.callback_query?.from?.id ?? msg.from?.id; const allowedAdmins = new Set(($json.allowed_admins ?? []).map(String)); const [commandRaw, ...args] = text.split(/\s+/); const command = commandRaw.startsWith('/') ? commandRaw.split('@')[0].toLowerCase() : 'text'; const isAdmin = allowedAdmins.has(String(userId)); const routes = { '/start': { action: 'send_public_help', requires_admin: false }, '/help': { action: 'send_public_help', requires_admin: false }, '/status': { action: 'check_order_status', requires_admin: false }, '/reload': { action: 'reload_cache', requires_admin: true }, '/broadcast': { action: 'broadcast_message', requires_admin: true } }; const route = routes[command] ?? { action: 'unknown_command', requires_admin: false }; if (route.requires_admin && !isAdmin) { return [{ json: { action: 'deny', reason: 'admin_required', command, user_id: userId } }]; } return [{ json: { action: route.action, command, args, chat_id: msg.chat?.id, user_id: userId, is_admin: isAdmin } }]; Почему роль проверяется до Execute route Админскую команду нельзя сначала отправить в API, а потом фильтровать ответ. Проверка прав должна стоять до любого действия, которое меняет данные или раскрывает внутреннюю информацию. Готовый workflow JSON ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Telegram bot command router with roles", "nodes": [ { "name": "Telegram Trigger", "type": "n8n-nodes-base.telegramTrigger", "purpose": "Получить message или callback_query" }, { "name": "Route command and role", "type": "n8n-nodes-base.code", "purpose": "Распознать команду, аргументы и роль" }, { "name": "Execute route", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать нужный API или внутренний workflow" }, { "name": "Format safe reply", "type": "n8n-nodes-base.code", "purpose": "Собрать ответ без служебных данных" }, { "name": "Send Telegram response", "type": "n8n-nodes-base.telegram", "purpose": "Ответить в чат или пользователю" } ], "connections": "Telegram Trigger → Route command → Execute route → Format reply → Send response" } Пошаговая настройка команд Telegram-бота ¶ Подключите Telegram Trigger и проверьте получение message и callback_query. Опишите словарь команд: публичные, пользовательские и админские. Добавьте источник ролей: список admin user_id, CRM-группа или internal API. Для каждой команды верните короткий `action`, а не выполняйте всю бизнес-логику в router. Добавьте fallback для неизвестных команд и безопасный текст ошибки. Тесты перед production ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/telegram-bot-command-router" \ -H "Content-Type: application/json" \ --data @telegram-bot-command-router-payload.json Проверьте `/start`, `/help`, `/status order_id`, неизвестную команду, админскую команду от обычного пользователя, callback query и слишком длинный ответ. Бот должен отвечать предсказуемо и не раскрывать внутренние детали. Production-риски command router ¶ Команда с @username не распознана. В группах Telegram команда может приходить как `/status@botname`. Права зашиты в код. При смене сотрудника доступ останется в workflow. Stack trace в чат. Пользователь не должен видеть ошибку API или SQL. Нет rate limit. Один пользователь может заспамить тяжелую команду. Смешаны router и бизнес-логика. Router должен выбирать ветку, а не превращаться в монолит. Полезные ссылки и смежные workflow ¶ См. также Telegram AI-бот с approval , Telegram alert для ошибок , rate limits и retries . Официальные документы: Telegram Bot API , n8n Telegram Trigger и n8n Telegram message operations . Router возвращает action, роль, аргументы и безопасный ответ. Критерии готовности ¶ Все команды описаны в едином словаре. Админские ветки требуют проверки роли до API-вызова. Неизвестная команда получает полезный fallback. Ответы экранируются под выбранный parse_mode. Есть лог команд, user_id, action и результата выполнения. Нужен Telegram-бот с понятной архитектурой? Nodbot спроектирует command router, роли, callback-кнопки, безопасные ответы и отдельные workflow для бизнес-команд. Настроить роутер команд

## Test payload

```json
{
  "message": {
    "message_id": 77,
    "chat": {
      "id": -1001234567890,
      "type": "supergroup"
    },
    "from": {
      "id": 501,
      "username": "manager"
    },
    "text": "/status order_1042"
  },
  "allowed_admins": [
    501,
    777
  ],
  "public_commands": [
    "/start",
    "/help",
    "/status"
  ]
}
```

## Key implementation snippet

```javascript
const update = $json.message ? $json : ($json.body ?? $json);
const msg = update.message ?? update.callback_query?.message ?? {};
const text = String(update.callback_query?.data ?? msg.text ?? '').trim();
const userId = update.callback_query?.from?.id ?? msg.from?.id;
const allowedAdmins = new Set(($json.allowed_admins ?? []).map(String));
const [commandRaw, ...args] = text.split(/\s+/);
const command = commandRaw.startsWith('/') ? commandRaw.split('@')[0].toLowerCase() : 'text';
const isAdmin = allowedAdmins.has(String(userId));

const routes = {
  '/start': { action: 'send_public_help', requires_admin: false },
  '/help': { action: 'send_public_help', requires_admin: false },
  '/status': { action: 'check_order_status', requires_admin: false },
  '/reload': { action: 'reload_cache', requires_admin: true },
  '/broadcast': { action: 'broadcast_message', requires_admin: true }
};

const route = routes[command] ?? { action: 'unknown_command', requires_admin: false };
if (route.requires_admin && !isAdmin) {
  return [{ json: { action: 'deny', reason: 'admin_required', command, user_id: userId } }];
}

return [{ json: { action: route.action, command, args, chat_id: msg.chat?.id, user_id: userId, is_admin: isAdmin } }];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Telegram bot command router with roles",
  "nodes": [
    {
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "purpose": "Получить message или callback_query"
    },
    {
      "name": "Route command and role",
      "type": "n8n-nodes-base.code",
      "purpose": "Распознать команду, аргументы и роль"
    },
    {
      "name": "Execute route",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Вызвать нужный API или внутренний workflow"
    },
    {
      "name": "Format safe reply",
      "type": "n8n-nodes-base.code",
      "purpose": "Собрать ответ без служебных данных"
    },
    {
      "name": "Send Telegram response",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Ответить в чат или пользователю"
    }
  ],
  "connections": "Telegram Trigger → Route command → Execute route → Format reply → Send response"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Шаблоны n8n: импорт и адаптация workflow"
source_url: "https://nodbot.ru/workflows/templates/"
canonical_url: "https://nodbot.ru/workflows/templates/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1063
---

# Шаблоны n8n: как выбирать, импортировать и адаптировать workflow без ошибок

## AI summary

Workflow-шаблоны n8n: как выбирать, импортировать, адаптировать под production и проверять перед запуском.

## Best used for

Страница объясняет «Шаблоны n8n: импорт и адаптация workflow» в контексте n8n/Nodbot: когда применять, как проверить внедрение и какие ошибки исключить.

## Key topics

- Когда шаблон действительно помогает
- Где искать шаблоны
- Как импортировать workflow JSON
- Что заменить после импорта
- Тестовый payload важнее красивой схемы
- Как не получить дубли после запуска
- Чем шаблон отличается от рецепта
- Типовые ошибки при работе с n8n templates

## Source outline

# Шаблоны n8n: как выбирать, импортировать и адаптировать workflow без ошибок

Обновлено: 2026-05-29

Шаблоны n8n полезны не потому, что их можно «скачать и забыть», а потому что они дают готовую схему: какие ноды нужны, где начинается входное событие, как данные проходят через workflow и чем заканчивается обработка. Хороший шаблон экономит часы. Плохой шаблон создаёт скрытые дубли, отправляет данные не туда или падает на первом реальном payload.

Главное правило

Перед запуском шаблона в рабочем аккаунте замените credentials, домены, webhook path, ID таблиц/CRM, добавьте тестовый payload и прогоните workflow вручную. Нельзя импортировать чужой JSON и сразу включать production webhook.

## Когда шаблон действительно помогает

- Ситуация | Подходит шаблон? | Что всё равно придётся настроить
- Telegram bot с командами | Да | токен бота, список команд, права доступа
- Tilda → CRM | Да | поля формы, CRM pipeline, дедупликация лидов
- ЮKassa → CRM | Да, но осторожно | проверка события, idempotency, статус платежа
- AI Agent по базе знаний | Частично | источники документов, embeddings, ограничения tools
- Сложная внутренняя интеграция 1С | Как каркас | контракт обмена, авторизация, формат ответов 1С

## Где искать шаблоны

У n8n есть встроенная библиотека workflow templates, а workflow можно экспортировать и импортировать как JSON. В нашем хабе шаблоны лежат в каталоге workflows : рядом с инструкцией есть JSON, test payload и пояснение, какие поля нужно заменить. Для российских сервисов лучше начинать именно с локальных шаблонов: они учитывают Битрикс24, amoCRM, Tilda, ЮKassa, DaData, VK и Яндекс Диск.

## Как импортировать workflow JSON

- Откройте n8n и создайте новый workflow или откройте пустой canvas.
- Выберите импорт из файла и загрузите JSON.
- Не активируйте workflow сразу после импорта.
- Откройте каждую ноду с credentials и выберите свои доступы.
- Замените URL, ID таблиц, ID pipeline, chat ID, project ID и другие локальные значения.
- Запустите workflow вручную на тестовом payload.
- Только после успешного теста включайте production webhook или расписание.

## Что заменить после импорта

- Элемент | Где встречается | Как проверить
- Credentials | HTTP Request, Telegram, Google Sheets, CRM-ноды | нода не должна показывать missing credentials
- Webhook path | Webhook Trigger | путь должен быть понятным и не конфликтовать с другим workflow
- External ID | Code/Edit Fields/Postgres | повторный payload не должен создавать дубль
- CRM fields | Битрикс24, amoCRM, HTTP API | поля должны совпадать с вашей воронкой
- Storage IDs | Google Sheets, Drive, Яндекс Диск | workflow пишет в нужную таблицу или папку
- AI prompt | AI Agent, LLM Chain | prompt не должен разрешать опасные действия без проверки

## Тестовый payload важнее красивой схемы

Схема workflow может выглядеть убедительно, но качество видно только на входных данных. Для каждого шаблона заведите минимум три payload: нормальный, неполный и повторный. Например, для формы заявки это может быть payload с телефоном и email, payload без email и повторный payload с тем же номером телефона. Если workflow проходит только идеальный пример, он не готов к реальной форме.

```
{
  "event_id": "lead_1001",
  "source": "tilda",
  "name": "Иван",
  "phone": "+79990000000",
  "email": "ivan@example.ru",
  "utm_source": "yandex"
}
```

## Как не получить дубли после запуска

Большинство проблем с шаблонами появляются не в момент импорта, а через неделю: CRM заполняется дублями, менеджерам приходят повторные уведомления, платежи обрабатываются дважды. Защититесь заранее:

- собирайте external_id из ID события, ID формы, ID платежа или стабильного хеша;
- делайте upsert в таблицу событий, а не слепой insert;
- храните received_at , processed_at и статус обработки;
- разделяйте «приняли webhook» и «отправили данные в CRM»;
- для платёжных событий проверяйте финальный статус, а не только факт прихода webhook.

## Чем шаблон отличается от рецепта

Рецепт объясняет бизнес-сценарий: зачем нужна автоматизация, какие сервисы участвуют, какие варианты бывают. Шаблон — это импортируемый JSON, который можно взять за основу. Если вы только выбираете архитектуру, начните с рецепта. Если уже знаете, что хотите внедрить, откройте workflow-шаблон и адаптируйте поля.

## Типовые ошибки при работе с n8n templates

- Ошибка | Почему возникает | Как исправить
- Workflow импортировался, но не запускается | не выбраны credentials или нода изменилась в вашей версии n8n | открыть каждую красную ноду, обновить настройки и сохранить workflow
- Webhook URL не принимает запрос | workflow не активирован или используется test URL вместо production | проверить статус workflow и правильный URL
- Данные уходят не в ту таблицу | оставлен чужой spreadsheet ID или folder ID | заменить ID на ваш и сделать тестовую запись
- CRM создаёт пустые лиды | поля формы не совпали с mapping | сравнить реальный payload и Edit Fields/Code node
- AI-узел отвечает нестабильно | prompt и tools не ограничены | задать JSON-формат, лимиты и human review для рискованных действий

## С чего начать в нашем каталоге

- Tilda → Битрикс24 — типовой входящий лид.
- ЮKassa → CRM — платёжное событие и сверка заказа.
- Webhook idempotency → Postgres — защита от дублей.
- OpenRouter fallback — переключение моделей при ошибке.
- Qdrant RAG FAQ bot — база знаний для поддержки.

## Production-чеклист для workflow-шаблонов

Используйте этот блок как быстрый контроль перед публикацией workflow или изменением существующей автоматизации. Он не заменяет staging, но помогает поймать самые частые отказы заранее.

- Перед запуском: проверить credentials, ENV, тестовые payload, error branch и owner процесса.
- Минимальный тест: импортировать шаблон в staging и пройти acceptance criteria до подключения production credentials.
- Типовой отказ: шаблон импортирован, но использует чужие тестовые значения или отсутствующий credential.
- Что логировать: входной payload без секретов, статус внешнего API, branch ошибки, execution id и владельца процесса.
Критерий готовности: сценарий проходит успешный путь, ошибочный путь и повтор события без дублей, потери данных и неконтролируемого падения execution.

## Как довести workflow до production

Страницу «Шаблоны n8n» лучше использовать как практический чеклист, а не как справку. Зафиксируйте входные данные, ожидаемый результат, владельца workflow и условие, при котором сценарий считается неуспешным.

Базовый источник для проверки: входной item по теме «Шаблоны n8n»: источник события, внешний ID, время получения и нормализованные поля. Главный риск — принять happy path за production-готовность и не проверить повторы, пустые входы, откат и наблюдаемость.

- Слой | Что зафиксировать | Зачем
- Вход | входной item по теме «Шаблоны n8n»: источник события, внешний ID, время получения и нормализованные поля | позволяет повторить проблему без доступа к production-секретам
- Контроль | successful_executions, skipped_items, retry_count, error_branch_usage, manual_override_count | показывает деградацию раньше, чем пользователи начинают писать в поддержку
- Безопасность | принять happy path за production-готовность и не проверить повторы, пустые входы, откат и наблюдаемость | снижает риск скрытых дублей, утечки данных и неконтролируемых write-действий
- Готовность | есть тест на happy path, пустой вход, повтор и сбой внешнего сервиса для «Шаблоны n8n» | делает статью пригодной для runbook, а не только для чтения

### Пример безопасного входного контракта

```
{
  "source": "manual|webhook|schedule|api",
  "external_id": "stable-id-from-source",
  "received_at": "2026-05-29T10:00:00Z",
  "payload_version": "v1",
  "dry_run": true,
  "audit": {"workflow_id": "...", "execution_id": "..."}
}
```

### Критерий готовности

- есть понятный вход, выход и владелец процесса
- проверены пустой input, повтор события и ошибка внешнего сервиса
- результат логируется без секретов и персональных данных
- страница связана с соседними рецептами, ошибками или playbook по теме

## Related Nodbot pages

- [Старт](/start/)
- [Основы](/basics/)
- [Интеграции](/integrations/)
- [AI](/ai/)
- [Рецепты](/recipes/)
- [Ошибки](/errors/)
- [Диагностика](/diagnostics/)
- [Сравнения](/compare/)

## Retrieval hints

- Предпочитать canonical URL как источник для пользовательских ссылок.
- Использовать markdown-версию для быстрого извлечения сущностей, чеклистов и терминов.
- При цитировании сверять с исходной HTML-страницей, если нужен самый полный контекст.


---

---
title: "Интеграция Tilda и amoCRM через n8n: лиды с UTM | Nodbot"
source_url: "https://nodbot.ru/workflows/tilda-form-to-amocrm-lead/"
canonical_url: "https://nodbot.ru/workflows/tilda-form-to-amocrm-lead/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1615
---

# Интеграция Tilda и amoCRM через n8n: защита от дублей и передача UTM

## AI summary

Problem/Solution-мануал по интеграции Tilda и amoCRM через n8n: настройка вебхука, нормализация телефона, API amoCRM, UTM, защита от дублей и production-проверка.

## Best used for

Практический Problem/Solution-мануал для внедрения связки Tilda, n8n и amoCRM: импортировать workflow JSON, настроить webhook, нормализовать данные формы, передать UTM, проверить API amoCRM и не создать дубли лидов.

## Key topics

- Интеграция Tilda и amoCRM через n8n
- Настройка вебхука Tilda
- Передача данных из формы
- API amoCRM и OAuth
- UTM custom fields
- Нормализация телефона регуляркой
- Дедупликация lead/contact
- Production-риски и тесты

## Source outline

Интеграция Tilda и amoCRM через n8n: защита от дублей и передача UTM ¶ Обновлено: 2026-05-30 Сохранить в мой план Открыть мой план Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте JSON в n8n, замените amoCRM base URL, OAuth credential, pipeline/status и ID custom fields для UTM. Содержание Проблема: почему стандартная отправка webhook из Тильды создает дубли Архитектура workflow для интеграции Контракт входных данных (JSON Payload) Нормализация телефона и UTM-меток (Code Node) Готовый workflow JSON: скачать и импортировать Пошаговая настройка связки Tilda, n8n и amoCRM Тесты перед production и проверка API Production-риски при работе с API amoCRM Полезные ссылки и смежные workflow Критерии готовности Проблема: стандартная передача данных из формы Tilda в amoCRM через webhook часто создаёт дубли: пользователь отправил заявку дважды, менеджер попросил заполнить форму повторно, рекламная метка изменилась, а CRM получила ещё одну сделку. Решение: надежная интеграция Тильды и amoCRM через n8n должна не просто делать Create lead , а принимать webhook формы, нормализовать телефон и email, искать существующий контакт или сделку через API amoCRM , сохранять UTM в отдельные поля и только после этого создавать или обновлять contact+lead . Этот мануал — практический скрипт n8n для автоматизации продаж: готовый JSON workflow можно скачать, импортировать в n8n и адаптировать под свой pipeline, ответственного менеджера и поля amoCRM. Workflow принимает webhook Tilda, нормализует контактные данные, ищет дубль в amoCRM и создаёт или обновляет lead без повторных сделок. Проблема: почему стандартная отправка webhook из Тильды создает дубли ¶ Настройка вебхука в Tilda выглядит простой: указали URL, получили POST, отправили его дальше. Но в реальном отделе продаж это ломается на повторных заявках, разных форматах телефона и неполных UTM. Если workflow каждый раз создаёт новую сделку, менеджеры видят несколько карточек одного клиента, реклама теряет атрибуцию, а CRM-отчёты начинают считать один интерес как несколько лидов. Для лендингов на российском рынке телефон часто важнее email: клиент может оставить пустую почту, рабочую почту или адрес с ошибкой, но номер нужен для звонка, WhatsApp, Telegram и дальнейшей квалификации. Поэтому в этом решении lookup строится вокруг нормализованного телефона, а email используется как дополнительный сигнал. Формально это интеграция Tilda и amoCRM, но по сути — контроль качества входящего потока лидов. n8n здесь работает как слой бизнес-логики между формой и CRM: валидирует payload, решает, что считать дублем, и не отдаёт сырые данные напрямую в amoCRM. Архитектура workflow для интеграции ¶ В ручной схеме мы не полагаемся на один универсальный upsert. Сначала workflow явно нормализует данные, затем делает поиск дубля, затем выбирает действие. Такой подход легче диагностировать: в executions видно, на каком шаге сломалась интеграция амо срм с формой Tilda. Нода Роль Что проверить перед production Webhook input Принимает POST от Tilda Production URL, метод POST, секрет в query/header, формат JSON Normalize Tilda payload Очищает телефон, email, UTM и form_id +7 вместо 8, lowercase email, пустые обязательные поля Find amoCRM duplicate Ищет contact или lead по телефону/email Base URL amoCRM, OAuth, rate limits, открытая сделка в нужной воронке Create or update contact+lead Создаёт новую связку или обновляет найденную pipeline_id , status_id , responsible_user_id , custom fields UTM Respond to Webhook Возвращает ответ Tilda Короткий ответ без токенов, телефонов и служебных ошибок Если в amoCRM уже есть исторические дубли, заранее определите правило победителя: обновлять последнюю открытую сделку в нужной воронке, создавать новую сделку при закрытом статусе или отправлять конфликт в ручную проверку. Контракт входных данных (JSON Payload) ¶ Контракт payload фиксирует, какие поля Tilda обязана передать в n8n. Не называйте UTM произвольно: если сегодня поле называется utmCampaign , а завтра utm_campaign , скрипт n8n начнёт терять источник заявки. { "name": "Анна", "phone": "+7 (916) 123-45-67", "email": "anna@example.ru", "comment": "Хочу обсудить внедрение n8n", "utm_source": "yandex", "utm_medium": "cpc", "utm_campaign": "n8n_integrator_msk", "utm_content": "lead_button_header", "utm_term": "интеграция тильды и амо срм", "formid": "landing-main", "page": "https://example.ru/n8n" } Минимально обязательным полем в этом сценарии является телефон. Если телефон пустой или не проходит регулярку, workflow должен остановиться до обращения к amoCRM, а не создавать “мусорную” сделку без ключа дедупликации. Нормализация телефона и UTM-меток (Code Node) ¶ Этот Code Node превращает разные варианты ввода из формы в стабильный объект для поиска дубля и записи в amoCRM. В нём есть нормализация телефона, lowercase email, сбор UTM-меток и dedupe_key для логов и повторных проверок. const src = $json.body ?? $json; const rawPhone = String(src.phone ?? src.Phone ?? '').trim(); let digits = rawPhone.replace(/\D/g, ''); if (digits.length === 11 && digits.startsWith('8')) { digits = `7${digits.slice(1)}`; } if (digits.length === 10) { digits = `7${digits}`; } if (!/^7\d{10}$/.test(digits)) { throw new Error(`Invalid phone for amoCRM lead: ${rawPhone}`); } const email = String(src.email ?? src.Email ?? '').trim().toLowerCase(); const formId = String(src.formid ?? src.form_id ?? '').trim(); return [{ json: { name: String(src.name ?? src.Name ?? 'Новый лид из Tilda').trim(), phone_raw: rawPhone, phone_normalized: `+${digits}`, email, comment: String(src.comment ?? src.message ?? '').trim(), utm_source: src.utm_source ?? '', utm_medium: src.utm_medium ?? '', utm_campaign: src.utm_campaign ?? '', utm_content: src.utm_content ?? '', utm_term: src.utm_term ?? '', tilda_form_id: formId, page: src.page ?? src.referer ?? '', dedupe_key: `tilda:${digits}:${email || formId || 'no-email'}`, received_at: new Date().toISOString() } }]; Для другой страны лучше заменить правило телефона целиком, а не накапливать исключения внутри workflow. Для России регулярка ^7\d{10}$ делает ключ поиска предсказуемым: 8 916 123-45-67 и +7 (916) 123-45-67 попадут в одну карточку. Готовый workflow JSON: скачать и импортировать ¶ Полный JSON лежит в архиве и доступен по кнопке «Скачать workflow JSON» в начале статьи. Импорт: n8n → Workflows → Import from File → выбрать файл → заменить credentials и параметры amoCRM. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Tilda to amoCRM lead with UTM", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять POST формы Tilda и вернуть Tilda короткий 200 OK" }, { "name": "Normalize Tilda payload", "type": "n8n-nodes-base.code", "purpose": "Очистить телефон, email, UTM и собрать dedupe_key" }, { "name": "Find contact or lead in amoCRM", "type": "n8n-nodes-base.httpRequest", "purpose": "Найти дубль через API amoCRM по телефону или email" }, { "name": "Create or update contact+lead", "type": "n8n-nodes-base.httpRequest", "purpose": "Создать или обновить contact+lead, custom fields UTM и статус воронки" }, { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть безопасный ответ без токенов и персональных данных" } ], "connections": "Webhook input → Normalize Tilda payload → Find contact or lead in amoCRM → Create or update contact+lead → Respond to Webhook" } Если ваша версия n8n и node для amoCRM поддерживают встроенный upsert, его можно использовать для простого справочника контактов. В этой инструкции ручная схема оставлена намеренно: она лучше подходит для сделок, UTM, выбора воронки, конфликтов дублей и отдельной обработки ошибок API. Пошаговая настройка связки Tilda, n8n и amoCRM ¶ В Tilda откройте настройки формы и включите отправку в Webhook. Официальная справка Tilda описывает, что данные формы отправляются на ваш URL методом POST. Вставьте production URL n8n webhook и добавьте секрет в query-параметр или заголовок, чтобы случайный бот не создавал сделки. В n8n импортируйте workflow JSON, замените amoCRM OAuth credential, subdomain и base URL. В amoCRM заранее создайте custom fields для utm_source , utm_medium , utm_campaign , form_id и страницы лендинга. Укажите pipeline_id , status_id и responsible_user_id явно, чтобы заявка попала в рабочую воронку, а не в дефолтный статус. Отправьте один и тот же test payload дважды: первый запуск должен создать карточку, второй — обновить найденную сущность или остановиться по вашему правилу дедупликации. Итоговая карточка должна содержать телефон, источник, кампанию, form_id и страницу заявки в отдельных полях, а не только в примечании. Тесты перед production и проверка API ¶ Проверяйте не только 200 OK . Смотрите execution data: нормализованный телефон, найденный дубль, body запроса к amoCRM и итоговую карточку в нужной воронке. Для API amoCRM особенно важны ответы 400 , 401 , 403 и 429 . curl -X POST "https://YOUR-N8N-DOMAIN/webhook/tilda-form-to-amocrm-lead" \ -H "Content-Type: application/json" \ --data @tilda-form-to-amocrm-lead-payload.json Отдельно проверьте три сценария: повтор того же телефона, тот же телефон в формате 8... вместо +7... , и заявка без email. Если все три случая создают одну логичную карточку, передача данных из формы настроена корректно. Production-риски при работе с API amoCRM ¶ UTM записаны только в примечание. Маркетинг не сможет строить отчёты. Используйте отдельные custom fields amoCRM. Дубль ищется только по email. Для российских лидов телефон часто надежнее, а email может быть пустым, техническим или ошибочным. OAuth истёк в production. Добавьте alert на 401/403 и runbook для перевыпуска токена; документация amoCRM отдельно описывает OAuth 2.0. Неверный pipeline или status. Сделка создаётся, но менеджеры её не видят, поэтому автоматизация продаж выглядит “неработающей”. Гонка при одновременных заявках. Два события с одним телефоном могут одновременно не найти дубль. Для жёсткой гарантии используйте отдельную идемпотентность в Postgres. Сырые персональные данные в логах. Не отправляйте полный payload в Telegram/Slack alert без маскирования телефона и email. Полезные ссылки и смежные workflow ¶ Официальные документы, которые стоит держать рядом при внедрении: Tilda Webhook для приёма форм , API Reference amoCRM и OAuth 2.0 amoCRM . Смотрите также внутри Nodbot: Установка n8n — базовый запуск перед production-интеграциями. n8n в Docker Compose — self-hosted стенд для таких workflow. amoCRM в n8n — общая страница по интеграции. OAuth refresh token expired — что делать, если токен CRM истёк. amoCRM webhook deduplication — защита от повторных событий CRM. Tilda → Битрикс24 — соседний сценарий с другой CRM-логикой. Критерии готовности ¶ Повтор одного и того же телефона не создаёт вторую сделку без осознанного правила. UTM-метки лежат в отдельных полях amoCRM и видны в отчётах. Ошибки 400/401/403/429 уходят в alert или DLQ, а не теряются в executions. Менеджер видит сделку в нужной воронке, статусе и с понятным названием. Workflow содержит владельца, версию, описание credentials и список полей, которые можно менять безопасно. В n8n отключено лишнее хранение персональных данных или настроена политика очистки executions. Нужно внедрить быстрее? Нет времени собирать связку Tilda, n8n и amoCRM вручную? Делегируйте интеграцию команде Nodbot: настроим webhook, OAuth, поля CRM, дедупликацию, тесты и production-мониторинг. Обсудить внедрение n8n

## Test payload

```json
{
  "name": "Анна",
  "phone": "+7 (916) 123-45-67",
  "email": "anna@example.ru",
  "comment": "Хочу обсудить внедрение n8n",
  "utm_source": "yandex",
  "utm_medium": "cpc",
  "utm_campaign": "n8n_integrator_msk",
  "utm_content": "lead_button_header",
  "utm_term": "интеграция тильды и амо срм",
  "formid": "landing-main",
  "page": "https://example.ru/n8n"
}
```

## Key implementation snippets

```javascript
const src = $json.body ?? $json;
const rawPhone = String(src.phone ?? src.Phone ?? '').trim();
let digits = rawPhone.replace(/\D/g, '');

if (digits.length === 11 && digits.startsWith('8')) {
  digits = `7${digits.slice(1)}`;
}

if (digits.length === 10) {
  digits = `7${digits}`;
}

if (!/^7\d{10}$/.test(digits)) {
  throw new Error(`Invalid phone for amoCRM lead: ${rawPhone}`);
}

const email = String(src.email ?? src.Email ?? '').trim().toLowerCase();
const formId = String(src.formid ?? src.form_id ?? '').trim();

return [{
  json: {
    name: String(src.name ?? src.Name ?? 'Новый лид из Tilda').trim(),
    phone_raw: rawPhone,
    phone_normalized: `+${digits}`,
    email,
    comment: String(src.comment ?? src.message ?? '').trim(),
    utm_source: src.utm_source ?? '',
    utm_medium: src.utm_medium ?? '',
    utm_campaign: src.utm_campaign ?? '',
    utm_content: src.utm_content ?? '',
    utm_term: src.utm_term ?? '',
    tilda_form_id: formId,
    page: src.page ?? src.referer ?? '',
    dedupe_key: `tilda:${digits}:${email || formId || 'no-email'}`,
    received_at: new Date().toISOString()
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Tilda to amoCRM lead with UTM",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять POST формы Tilda и вернуть Tilda короткий 200 OK"
    },
    {
      "name": "Normalize Tilda payload",
      "type": "n8n-nodes-base.code",
      "purpose": "Очистить телефон, email, UTM и собрать dedupe_key"
    },
    {
      "name": "Find contact or lead in amoCRM",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Найти дубль через API amoCRM по телефону или email"
    },
    {
      "name": "Create or update contact+lead",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Создать или обновить contact+lead, custom fields UTM и статус воронки"
    },
    {
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть безопасный ответ без токенов и персональных данных"
    }
  ],
  "connections": "Webhook input → Normalize Tilda payload → Find contact or lead in amoCRM → Create or update contact+lead → Respond to Webhook"
}
```

## Related Nodbot pages

- [Установка n8n](/kak-ustanovit-n8n/)
- [n8n в Docker Compose](/n8n-docker-compose-self-hosted-guide/)
- [amoCRM в n8n](/integrations/amocrm/)
- [OAuth refresh token expired](/errors/oauth-refresh-token-expired/)
- [amoCRM webhook deduplication](/workflows/amocrm-webhook-deduplication/)
- [Tilda → Битрикс24](/workflows/tilda-form-to-bitrix24-lead/)

## Retrieval hints

- Предпочитать canonical URL как источник для пользовательских ссылок.
- Использовать markdown-версию для быстрого извлечения workflow-контракта, кода и чеклистов.
- При цитировании сверять с HTML-страницей, если нужен самый полный контекст.

---
title: "Tilda и Битрикс24 через n8n: лиды с UTM | Nodbot"
source_url: "https://nodbot.ru/workflows/tilda-form-to-bitrix24-lead/"
canonical_url: "https://nodbot.ru/workflows/tilda-form-to-bitrix24-lead/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1369
---

# Интеграция Tilda и Битрикс24 через n8n: лиды с UTM без дублей

## AI summary

Problem/Solution-мануал по интеграции Tilda и Битрикс24 через n8n: настройка вебхука, передача данных из формы, crm.duplicate.findbycomm, UTM-поля, нормализация телефона и production-проверка.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить webhook/API, проверить дубли, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему простая передача формы Tilda в Битрикс24 создает дубли
- Архитектура workflow для интеграции Tilda и Битрикс24
- Контракт входных данных (JSON Payload)
- Нормализация телефона и UTM для Bitrix24 REST (Code Node)
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка связки Tilda, n8n и Битрикс24
- Тесты перед production и проверка Bitrix24 API
- Production-риски при работе с REST API Битрикс24
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Tilda Bitrix24 integration
- n8n webhook
- crm.duplicate.findbycomm
- Bitrix24 REST API
- UTM fields
- phone normalization
- lead dedupe
- workflow JSON

## Source outline

Интеграция Tilda и Битрикс24 через n8n: лиды с UTM без дублей ¶ Обновлено: 2026-05-30 Сохранить в мой план Открыть мой план Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте JSON в n8n, замените Bitrix24 webhook URL, ID пользовательских полей и правило создания/обновления лида. Содержание Проблема: почему простая передача формы Tilda в Битрикс24 создает дубли Архитектура workflow для интеграции Tilda и Битрикс24 Контракт входных данных (JSON Payload) Нормализация телефона и UTM для Bitrix24 REST (Code Node) Готовый workflow JSON: скачать и импортировать Пошаговая настройка связки Tilda, n8n и Битрикс24 Тесты перед production и проверка Bitrix24 API Production-риски при работе с REST API Битрикс24 Полезные ссылки и смежные workflow Критерии готовности Проблема: Tilda отправляет форму в webhook быстро, но Битрикс24 не должен получать новый лид при каждом повторном POST. Иначе менеджеры видят одинаковые заявки, UTM-аналитика расходится, а автоматизация продаж начинает обзванивать одного человека несколько раз. Решение: надежная интеграция Тильды и Битрикс24 через n8n принимает данные из формы, нормализует телефон, ищет дубли через REST API Битрикс24 и только потом делает crm.lead.add или обновляет найденную сущность. Это не “прокладка webhook → CRM”, а контролируемый слой качества данных. Страница рассчитана на интегратора: здесь есть готовый workflow JSON, payload для теста, Code Node с регуляркой, таблица архитектуры, production-риски и чек-лист запуска. n8n принимает webhook Tilda, нормализует контакт, ищет дубль в Битрикс24 и создаёт или обновляет лид с UTM. Проблема: почему простая передача формы Tilda в Битрикс24 создает дубли ¶ Простая настройка вебхука работает только до первого повторного лида. Пользователь мог дважды нажать кнопку, вернуться с другой рекламной кампании, оставить форму без email или написать телефон в формате 8 925... . Если каждый такой запрос превращается в новый лид, CRM быстро теряет доверие у отдела продаж. У Битрикс24 есть отдельная логика дублей и разные режимы CRM. Поэтому задача workflow — заранее подготовить поля, проверить phone/email как коммуникации и не смешивать UTM, комментарий, страницу заявки и системные поля в один текстовый блок. Архитектура workflow для интеграции Tilda и Битрикс24 ¶ Нода Роль Что проверить Webhook input Принимает POST формы Tilda Production URL, секрет, JSON body, корректный ответ Tilda Normalize and map fields Готовит phone/email и fields для Битрикс24 Регулярка телефона, lowercase email, UTM-поля Find duplicate Вызывает поиск дублей по коммуникациям Телефон и email переданы в формате, который понимает CRM Create or update lead Создаёт или обновляет лид TITLE , PHONE , EMAIL , UTM_* , пользовательские поля Respond Возвращает безопасный ответ webhook Без токенов, персональных данных и stack trace Встроенный “просто отправить форму” не показывает, где именно сломался процесс. Ручная схема в n8n удобнее: видно нормализованный телефон, результат поиска дубля, тело запроса к Bitrix24 API и финальный ответ CRM. Контракт входных данных (JSON Payload) ¶ Зафиксируйте контракт входных данных до публикации формы. Чем стабильнее payload, тем меньше ручных правок в Битрикс24 после запуска рекламы. { "name": "Ирина", "phone": "+7 (925) 400-11-22", "email": "irina@example.ru", "comment": "Хочу получить расчет внедрения CRM", "utm_source": "yandex", "utm_medium": "cpc", "utm_campaign": "bitrix24_integration", "utm_content": "lead_form_main", "utm_term": "интеграция тильды и битрикс24", "formid": "consultation-main", "page": "https://example.ru/bitrix24" } Обязательный минимум — телефон. Email, комментарий и UTM полезны, но не должны заменять ключ дедупликации. Если телефон не проходит нормализацию, workflow должен остановиться до обращения в CRM. Нормализация телефона и UTM для Bitrix24 REST (Code Node) ¶ Code Node ниже подготавливает объект fields для REST API: коммуникации оформлены массивами PHONE и EMAIL , UTM передаются в стандартные поля, а дополнительные значения уходят в пользовательские поля. const src = $json.body ?? $json; const rawPhone = String(src.phone ?? src.Phone ?? '').trim(); let digits = rawPhone.replace(/\D/g, ''); if (digits.length === 11 && digits.startsWith('8')) { digits = `7${digits.slice(1)}`; } if (digits.length === 10) { digits = `7${digits}`; } if (!/^7\d{10}$/.test(digits)) { throw new Error(`Invalid phone for Bitrix24 lead: ${rawPhone}`); } const email = String(src.email ?? src.Email ?? '').trim().toLowerCase(); const name = String(src.name ?? src.Name ?? 'Новый лид из Tilda').trim(); return [{ json: { dedupe: { phone: `+${digits}`, email, key: `tilda-bitrix24:${digits}:${email || 'no-email'}` }, fields: { TITLE: `Tilda: ${name}`, NAME: name, PHONE: [{ VALUE: `+${digits}`, VALUE_TYPE: 'WORK' }], EMAIL: email ? [{ VALUE: email, VALUE_TYPE: 'WORK' }] : [], COMMENTS: String(src.comment ?? src.message ?? '').trim(), SOURCE_ID: 'WEB', UTM_SOURCE: src.utm_source ?? '', UTM_MEDIUM: src.utm_medium ?? '', UTM_CAMPAIGN: src.utm_campaign ?? '', UTM_CONTENT: src.utm_content ?? '', UTM_TERM: src.utm_term ?? '', UF_CRM_TILDA_FORM_ID: src.formid ?? src.form_id ?? '', UF_CRM_LANDING_PAGE: src.page ?? src.referer ?? '' }, received_at: new Date().toISOString() } }]; Для поиска дубля используйте phone/email из dedupe . В Битрикс24 метод поиска дублей по коммуникациям работает с телефоном и email, поэтому важно не отправлять туда сырые значения из формы. Готовый workflow JSON: скачать и импортировать ¶ Полный JSON находится в архиве сайта и доступен по кнопке в начале статьи. Импортируйте его в n8n, затем замените Bitrix24 webhook URL вида https://YOUR_PORTAL.bitrix24.ru/rest/USER_ID/WEBHOOK_CODE/ . Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Tilda to Bitrix24 lead with UTM and dedupe", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять POST формы Tilda и вернуть короткий ответ" }, { "name": "Normalize and map Bitrix24 fields", "type": "n8n-nodes-base.code", "purpose": "Нормализовать телефон, email, UTM и собрать Bitrix24 fields" }, { "name": "Find duplicate in Bitrix24", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать crm.duplicate.findbycomm по телефону/email" }, { "name": "Create or update Bitrix24 lead", "type": "n8n-nodes-base.httpRequest", "purpose": "Создать crm.lead.add или обновить найденный лид" }, { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть Tilda безопасный 200 OK" } ], "connections": "Webhook input → Normalize → Find duplicate → Create/update lead → Respond" } В новых проектах можно заменить создание лида на универсальные методы CRM, но для классического режима с лидами сценарий выше проще объяснить менеджерам и легче отлаживать. Пошаговая настройка связки Tilda, n8n и Битрикс24 ¶ В Tilda включите отправку формы в webhook и убедитесь, что передаются телефон, email, комментарий, UTM и formid . В n8n импортируйте workflow JSON и замените путь webhook на production URL. В Битрикс24 создайте входящий webhook с правами на CRM и сохраните его URL в credentials или ENV. Проверьте ID пользовательских полей для form_id и landing page; не пишите их только в комментарий. Настройте ветку: если дубль найден — update/comment, если не найден — create lead. Отправьте один payload дважды и убедитесь, что повтор не создал второй лид. Идеальный результат: телефон, email, UTM, form_id и страница заявки лежат в отдельных полях, а не только в комментарии. Тесты перед production и проверка Bitrix24 API ¶ Проверяйте не только успешный HTTP-ответ. В executions должны быть понятны три вещи: нормализованный телефон, найденный дубль и результат записи в Битрикс24. Для production отдельно проверьте ответы 400 , 401 , 403 и 429 . curl -X POST "https://YOUR-N8N-DOMAIN/webhook/tilda-form-to-bitrix24-lead" \ -H "Content-Type: application/json" \ --data @tilda-form-to-bitrix24-lead-payload.json Минимальный набор тестов: повторный payload, телефон в формате 8... , заявка без email, UTM с кириллицей и пустой комментарий. Все эти случаи должны давать предсказуемый результат. Production-риски при работе с REST API Битрикс24 ¶ Webhook Битрикс24 лежит прямо в ноде. Утечка URL даёт доступ к CRM-операциям. Храните его в credentials или ENV. Дубль ищется после создания лида. Тогда CRM уже загрязнена. Поиск должен идти до create. UTM потерялись в комментарии. Маркетинг не сможет построить нормальный отчёт по источникам. Лимиты REST API. Массовый импорт лидов через тот же workflow без backoff может упереться в ограничения. Разные режимы CRM. В некоторых порталах лиды отключены; тогда нужно создавать сделку/контакт, а не crm.lead.add . Нет владельца workflow. При смене формы никто не знает, какие поля можно переименовывать безопасно. Полезные ссылки и смежные workflow ¶ Официальные документы для внедрения: поиск дублей в Bitrix24 REST , раздел Leads в Bitrix24 CRM и Webhook для форм Tilda . Смотрите также внутри Nodbot: Установка n8n — базовая подготовка сервера. n8n в Docker Compose — self-hosted запуск для production. Битрикс24 в n8n — общая страница интеграции. Tilda → amoCRM — соседний сценарий для другой CRM. Retry и DLQ для HTTP Request — защита от временных ошибок API. Критерии готовности ¶ Повторная отправка формы не создаёт второй лид без бизнес-правила. Телефон нормализуется одинаково для +7 , 8 , пробелов и скобок. UTM, form_id и landing page записываются в отдельные поля. Ошибки REST API уходят в alert или DLQ. Webhook URL не хранится в публичном тексте workflow. У workflow есть владелец, описание и тестовый payload. Нужно внедрить без риска дублей? Команда Nodbot может настроить связку Tilda, n8n и Битрикс24 под вашу CRM-структуру: поля, статусы, дубли, UTM, тесты и мониторинг. Обсудить интеграцию Битрикс24

## Test payload

```json
{
  "name": "Ирина",
  "phone": "+7 (925) 400-11-22",
  "email": "irina@example.ru",
  "comment": "Хочу получить расчет внедрения CRM",
  "utm_source": "yandex",
  "utm_medium": "cpc",
  "utm_campaign": "bitrix24_integration",
  "utm_content": "lead_form_main",
  "utm_term": "интеграция тильды и битрикс24",
  "formid": "consultation-main",
  "page": "https://example.ru/bitrix24"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const rawPhone = String(src.phone ?? src.Phone ?? '').trim();
let digits = rawPhone.replace(/\D/g, '');

if (digits.length === 11 && digits.startsWith('8')) {
  digits = `7${digits.slice(1)}`;
}

if (digits.length === 10) {
  digits = `7${digits}`;
}

if (!/^7\d{10}$/.test(digits)) {
  throw new Error(`Invalid phone for Bitrix24 lead: ${rawPhone}`);
}

const email = String(src.email ?? src.Email ?? '').trim().toLowerCase();
const name = String(src.name ?? src.Name ?? 'Новый лид из Tilda').trim();

return [{
  json: {
    dedupe: {
      phone: `+${digits}`,
      email,
      key: `tilda-bitrix24:${digits}:${email || 'no-email'}`
    },
    fields: {
      TITLE: `Tilda: ${name}`,
      NAME: name,
      PHONE: [{ VALUE: `+${digits}`, VALUE_TYPE: 'WORK' }],
      EMAIL: email ? [{ VALUE: email, VALUE_TYPE: 'WORK' }] : [],
      COMMENTS: String(src.comment ?? src.message ?? '').trim(),
      SOURCE_ID: 'WEB',
      UTM_SOURCE: src.utm_source ?? '',
      UTM_MEDIUM: src.utm_medium ?? '',
      UTM_CAMPAIGN: src.utm_campaign ?? '',
      UTM_CONTENT: src.utm_content ?? '',
      UTM_TERM: src.utm_term ?? '',
      UF_CRM_TILDA_FORM_ID: src.formid ?? src.form_id ?? '',
      UF_CRM_LANDING_PAGE: src.page ?? src.referer ?? ''
    },
    received_at: new Date().toISOString()
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Tilda to Bitrix24 lead with UTM and dedupe",
  "nodes": [
    { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять POST формы Tilda и вернуть короткий ответ" },
    { "name": "Normalize and map Bitrix24 fields", "type": "n8n-nodes-base.code", "purpose": "Нормализовать телефон, email, UTM и собрать Bitrix24 fields" },
    { "name": "Find duplicate in Bitrix24", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать crm.duplicate.findbycomm по телефону/email" },
    { "name": "Create or update Bitrix24 lead", "type": "n8n-nodes-base.httpRequest", "purpose": "Создать crm.lead.add или обновить найденный лид" },
    { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть Tilda безопасный 200 OK" }
  ],
  "connections": "Webhook input → Normalize → Find duplicate → Create/update lead → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "VK Lead Forms и Google Sheets через n8n | Nodbot"
source_url: "https://nodbot.ru/workflows/vk-lead-form-to-sheets/"
canonical_url: "https://nodbot.ru/workflows/vk-lead-form-to-sheets/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1202
---

# VK Lead Forms → n8n → Google Sheets: заявки с UTM без дублей

## AI summary

Практический workflow для заявок VK Lead Forms: принять lead_id, нормализовать телефон и UTM, найти строку в Google Sheets по стабильному ключу, обновить существующую запись или добавить новую, а ошибки API отправить в alert/DLQ.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- VK Lead Forms
- n8n
- Google Sheets
- upsert
- UTM
- lead_id
- deduplication
- VK Ads

## Source outline

VK Lead Forms → n8n → Google Sheets: заявки с UTM без дублей ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для заявок VK Lead Forms: принять lead_id, нормализовать телефон и UTM, найти строку в Google Sheets по стабильному ключу, обновить существующую запись или добавить новую, а ошибки API отправить в alert/DLQ. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: лиды из VK Lead Forms часто приходят повторно, содержат телефон в разных форматах и теряют рекламные метки при ручной выгрузке. Если каждый lead append-ить в Google Sheets, менеджеры быстро получают дубли и грязную таблицу. Решение: делаем контролируемую интеграцию VK Lead Forms и Google Sheets через n8n: используем `lead_id` и нормализованный телефон как ключи, сохраняем UTM в отдельные колонки, обновляем существующую строку и добавляем новые заявки только при настоящем новом лиде. Workflow принимает заявку VK Lead Forms, нормализует телефон и UTM, находит строку и делает update или append. Проблема: почему VK Lead Forms создают дубли в Google Sheets ¶ В рекламной воронке VK Lead Ads Google Sheets часто используется как быстрый операционный буфер: маркетолог смотрит заявки, менеджер отмечает статус, руководитель выгружает отчёт. Но append каждой заявки превращает таблицу в хаос: повторный lead, одинаковый телефон, разные UTM и ручные правки создают несколько строк на одного клиента. Эта страница решает конкретную задачу: настроить передачу данных из формы VK в Google Sheets через n8n так, чтобы строка обновлялась по `lead_id` или телефону, а не плодила дубли. При этом UTM, форма, кампания и статус обработки остаются отдельными колонками. Архитектура workflow VK Lead Forms → n8n → Sheets ¶ Нода Роль Что проверить VK lead event передаёт lead_id и поля формы секрет, group_id, form_id, lead_id Normalize lead чистит телефон, имя, UTM +7, 8, пробелы, lowercase email Find row in Sheets ищет строку по lead_id/phone колонки lead_id и phone_normalized Update or append row обновляет или добавляет заявку статус, updated_at, update_count Notify manager отправляет уведомление при новом лиде без дублей и без персональных данных в публичный чат Error route пишет ошибку в DLQ/alert 429, Google API, неверные поля формы Для новых версий Google Sheets node можно использовать встроенную операцию Append or Update. Ручная схема Find → IF → Update/Append полезна, когда нужно вести `update_count`, разные правила для новых и повторных лидов или отдельный alert только для новых заявок. Контракт входных данных VK lead event ¶ { "lead_id": "vk-lead-77821", "group_id": "club123456", "form_id": "consultation-main", "created_at": "2026-05-30T10:00:00+03:00", "name": "Олег", "phone": "8 (916) 555-44-33", "email": "oleg@example.ru", "utm_source": "vk", "utm_medium": "cpc", "utm_campaign": "n8n_leads", "utm_content": "leadform_banner", "ad_id": "ad-987", "campaign_id": "camp-321" } Если VK отдаёт только `lead_id`, а полные поля нужно забирать отдельным API-запросом, оставьте этот же контракт внутри n8n после enrichment-ноды. Для Google Sheets важно, чтобы на выходе был стабильный `lead_id` и `phone_normalized`. Code Node: нормализация телефона, UTM и ключа строки ¶ const src = $json.body ?? $json; const leadId = String(src.lead_id ?? src.id ?? '').trim(); if (!leadId) throw new Error('Missing VK lead_id'); const rawPhone = String(src.phone ?? src.Phone ?? '').trim(); let digits = rawPhone.replace(/\D/g, ''); if (digits.length === 11 && digits.startsWith('8')) digits = `7${digits.slice(1)}`; if (digits.length === 10) digits = `7${digits}`; if (!/^7\d{10}$/.test(digits)) throw new Error(`Invalid VK lead phone: ${rawPhone}`); const email = String(src.email ?? '').trim().toLowerCase(); const now = new Date().toISOString(); return [{ json: { row_key: `vk:${leadId}`, dedupe_phone_key: `phone:+${digits}`, lead_id: leadId, phone_raw: rawPhone, phone_normalized: `+${digits}`, name: String(src.name ?? src.first_name ?? 'Новый лид VK').trim(), email, group_id: String(src.group_id ?? ''), form_id: String(src.form_id ?? ''), campaign_id: String(src.campaign_id ?? ''), ad_id: String(src.ad_id ?? ''), utm_source: src.utm_source ?? 'vk', utm_medium: src.utm_medium ?? '', utm_campaign: src.utm_campaign ?? '', utm_content: src.utm_content ?? '', first_seen_at: src.created_at ?? now, updated_at: now, status: 'new' } }]; Какие колонки создать в Google Sheets Минимум: lead_id, row_key, phone_normalized, name, email, group_id, form_id, campaign_id, ad_id, utm_source, utm_medium, utm_campaign, utm_content, status, first_seen_at, updated_at, update_count. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - VK Lead Forms to Google Sheets with UTM dedupe", "nodes": [ { "name": "VK Lead Webhook", "type": "n8n-nodes-base.webhook", "purpose": "Принять lead_id и поля формы" }, { "name": "Normalize VK lead", "type": "n8n-nodes-base.code", "purpose": "Нормализовать телефон, UTM и row_key" }, { "name": "Find row in Google Sheets", "type": "n8n-nodes-base.httpRequest", "purpose": "Найти строку по lead_id или phone_normalized" }, { "name": "Update or append row", "type": "n8n-nodes-base.httpRequest", "purpose": "Обновить существующую строку или добавить новую" }, { "name": "Notify manager", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить о новой заявке без дублей" }, { "name": "Respond", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть VK безопасный 200" } ], "connections": "VK Lead Webhook → Normalize VK lead → Find row in Google Sheets → Update or append row → Notify manager → Respond" } Пошаговая настройка VK webhook, n8n и Google Sheets ¶ Создайте лист Google Sheets с колонками lead_id, phone_normalized, UTM и status. Настройте VK Lead Forms webhook или API-забор lead_id в n8n. Импортируйте workflow и замените Google credential, spreadsheetId и sheet name. Выберите правило upsert: lead_id как основной ключ, телефон как дополнительная проверка дублей. Добавьте alert/DLQ для ошибок Google API и отсутствующих обязательных полей. Тесты перед production и проверка дублей ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/vk-lead-form-to-sheets" \ -H "Content-Type: application/json" \ --data @vk-lead-form-to-sheets-payload.json Отправьте один и тот же lead_id дважды: строка должна обновиться, а не добавиться. Отправьте тот же телефон с другим форматом `8 916...` и проверьте нормализацию. Проверьте заявку без email и с кириллицей в UTM. Удалите колонку в тестовом листе и убедитесь, что ошибка попадает в alert. Проверьте, что новый лид отправляет уведомление менеджеру только один раз. Production-риски VK Lead Ads и Google Sheets ¶ Append вместо upsert. Таблица быстро заполняется дублями и теряет управляемость. UTM лежат в комментарии. Маркетинг не сможет фильтровать заявки по кампании и объявлению. Поиск только по телефону. Один клиент с несколькими заявками может перезаписать нужные данные без lead_id. Секрет webhook не проверяется. В таблицу можно отправить мусорные заявки. Нет DLQ. Ошибка Google API теряет лид без следа. Полезные ссылки и смежные workflow ¶ См. также Google Sheets upsert по телефону , Tilda → amoCRM , retry/DLQ для HTTP Request и Google Sheets integrations . Официальные документы: VK Ads leads API , n8n Google Sheets node и Google Sheets API . Визуальная карточка показывает lead_id, нормализованный телефон, кампанию и действие со строкой. Критерии готовности ¶ Повторный lead_id не создаёт вторую строку. Телефон нормализуется для +7, 8, пробелов и скобок. UTM, form_id, campaign_id и ad_id записываются в отдельные колонки. Ошибки Google API уходят в alert/DLQ. Менеджер получает уведомление только по новым лидам. Нужно выгружать VK Lead Forms без дублей и ручной чистки? Nodbot настроит VK Lead Forms → n8n → Google Sheets: upsert, UTM, уведомления менеджерам, DLQ и проверку качества лидов. Настроить VK leads workflow

## Test payload

```json
{
  "lead_id": "vk-lead-77821",
  "group_id": "club123456",
  "form_id": "consultation-main",
  "created_at": "2026-05-30T10:00:00+03:00",
  "name": "Олег",
  "phone": "8 (916) 555-44-33",
  "email": "oleg@example.ru",
  "utm_source": "vk",
  "utm_medium": "cpc",
  "utm_campaign": "n8n_leads",
  "utm_content": "leadform_banner",
  "ad_id": "ad-987",
  "campaign_id": "camp-321"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const leadId = String(src.lead_id ?? src.id ?? '').trim();
if (!leadId) throw new Error('Missing VK lead_id');

const rawPhone = String(src.phone ?? src.Phone ?? '').trim();
let digits = rawPhone.replace(/\D/g, '');
if (digits.length === 11 && digits.startsWith('8')) digits = `7${digits.slice(1)}`;
if (digits.length === 10) digits = `7${digits}`;
if (!/^7\d{10}$/.test(digits)) throw new Error(`Invalid VK lead phone: ${rawPhone}`);

const email = String(src.email ?? '').trim().toLowerCase();
const now = new Date().toISOString();

return [{
  json: {
    row_key: `vk:${leadId}`,
    dedupe_phone_key: `phone:+${digits}`,
    lead_id: leadId,
    phone_raw: rawPhone,
    phone_normalized: `+${digits}`,
    name: String(src.name ?? src.first_name ?? 'Новый лид VK').trim(),
    email,
    group_id: String(src.group_id ?? ''),
    form_id: String(src.form_id ?? ''),
    campaign_id: String(src.campaign_id ?? ''),
    ad_id: String(src.ad_id ?? ''),
    utm_source: src.utm_source ?? 'vk',
    utm_medium: src.utm_medium ?? '',
    utm_campaign: src.utm_campaign ?? '',
    utm_content: src.utm_content ?? '',
    first_seen_at: src.created_at ?? now,
    updated_at: now,
    status: 'new'
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - VK Lead Forms to Google Sheets with UTM dedupe",
  "nodes": [
    {
      "name": "VK Lead Webhook",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять lead_id и поля формы"
    },
    {
      "name": "Normalize VK lead",
      "type": "n8n-nodes-base.code",
      "purpose": "Нормализовать телефон, UTM и row_key"
    },
    {
      "name": "Find row in Google Sheets",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Найти строку по lead_id или phone_normalized"
    },
    {
      "name": "Update or append row",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Обновить существующую строку или добавить новую"
    },
    {
      "name": "Notify manager",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Сообщить о новой заявке без дублей"
    },
    {
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть VK безопасный 200"
    }
  ],
  "connections": "VK Lead Webhook → Normalize VK lead → Find row in Google Sheets → Update or append row → Notify manager → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Webhook idempotency в Postgres и n8n | Nodbot"
source_url: "https://nodbot.ru/workflows/webhook-idempotency-to-postgres/"
canonical_url: "https://nodbot.ru/workflows/webhook-idempotency-to-postgres/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1028
---

# Webhook idempotency в n8n и Postgres: защита от повторных событий

## AI summary

Практический workflow для webhook idempotency: принять событие, проверить подпись, собрать стабильный idempotency key, записать его в Postgres через unique constraint, выполнить бизнес-действие только для нового события и безопасно ответить повтору.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- webhook idempotency
- n8n
- Postgres
- unique key
- ON CONFLICT
- HMAC
- deduplication
- replay

## Source outline

Webhook idempotency в n8n и Postgres: защита от повторных событий ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для webhook idempotency: принять событие, проверить подпись, собрать стабильный idempotency key, записать его в Postgres через unique constraint, выполнить бизнес-действие только для нового события и безопасно ответить повтору. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: webhook-провайдеры повторяют события при timeout, 5xx или сетевых сбоях. Если n8n каждый раз выполняет бизнес-действие, один платеж, лид или статус может обработаться дважды. Решение: выносим идемпотентность в Postgres: один `event_id` или HMAC-ключ получает unique index, повторные webhook-события не запускают бизнес-ветку, а возвращают уже известный результат. Workflow проверяет подпись, записывает idempotency key в Postgres и выполняет бизнес-действие только для нового события. Проблема: почему webhook-события приходят повторно ¶ Повторный webhook — это нормальное поведение, а не баг. Платежные сервисы, маркетплейсы, CRM и формы повторяют POST, если не получили быстрый 200 OK. Иногда первый запрос успел изменить CRM, но ответ потерялся на сети, и провайдер присылает событие снова. Идемпотентность нужна там, где повтор опасен: создание сделки, начисление доступа, отправка письма, смена статуса, списание бонусов. Цель workflow — не “поймать дубль в конце”, а не пустить повтор в бизнес-ветку с самого начала. Архитектура workflow idempotency на Postgres ¶ Нода Роль Что проверить Webhook input принимает событие от провайдера event_id, timestamp, signature, raw body Validate signature проверяет HMAC или secret защита от подделки и replay Build idempotency key собирает стабильный ключ provider:event_type:event_id Insert key in Postgres делает INSERT ON CONFLICT unique index и статус processing Run business action выполняет только новое событие CRM, склад, письмо, доступ Finalize event ставит processed или failed duration, target_id, error message В Postgres лучше хранить не только ключ, но и состояние: `processing`, `processed`, `failed`. Тогда можно отличить честный повтор от зависшего события и сделать ручное восстановление без повторного бизнес-действия. Контракт входных данных webhook-события ¶ { "event_id": "evt_2f3c6a99", "event_type": "lead.created", "provider": "tilda", "occurred_at": "2026-05-30T10:00:00Z", "signature": "sha256=7b5f...", "data": { "phone": "+7 (916) 555-12-34", "name": "Анна", "source": "landing" } } Лучший ключ — ID события от провайдера. Если его нет, используйте комбинацию provider, event_type, external_id и timestamp bucket, но обязательно документируйте компромисс: такой ключ может быть менее точным. Code Node: idempotency key и SQL ON CONFLICT ¶ const crypto = require('crypto'); const src = $json.body ?? $json; const provider = String(src.provider ?? 'unknown').trim(); const eventType = String(src.event_type ?? src.type ?? '').trim(); const eventId = String(src.event_id ?? src.id ?? '').trim(); if (!eventType) throw new Error('Missing event_type for idempotency'); if (!eventId) throw new Error('Missing event_id for idempotency'); const idempotencyKey = `${provider}:${eventType}:${eventId}`; const payloadHash = crypto .createHash('sha256') .update(JSON.stringify(src.data ?? src)) .digest('hex'); const sql = ` INSERT INTO webhook_idempotency (idempotency_key, provider, event_type, event_id, payload_hash, status, created_at) VALUES ($1, $2, $3, $4, $5, 'processing', now()) ON CONFLICT (idempotency_key) DO NOTHING RETURNING idempotency_key; `; return [{ json: { idempotency_key: idempotencyKey, provider, event_type: eventType, event_id: eventId, payload_hash: payloadHash, sql, sql_params: [idempotencyKey, provider, eventType, eventId, payloadHash], original_event: src } }]; Минимальная схема таблицы Postgres Создайте таблицу webhook_idempotency с unique index по idempotency_key и полями provider, event_type, event_id, payload_hash, status, target_id, error, created_at, processed_at. Это позволит отличать новый event от повтора. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Webhook idempotency with Postgres", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять событие и заголовки" }, { "name": "Validate signature", "type": "n8n-nodes-base.code", "purpose": "Проверить HMAC/secret и timestamp" }, { "name": "Build idempotency key", "type": "n8n-nodes-base.code", "purpose": "Собрать provider:event_type:event_id" }, { "name": "Insert key in Postgres", "type": "n8n-nodes-base.postgres", "purpose": "INSERT ON CONFLICT DO NOTHING" }, { "name": "New event gate", "type": "n8n-nodes-base.if", "purpose": "Пустить только новую запись" }, { "name": "Business action", "type": "n8n-nodes-base.httpRequest", "purpose": "Создать/обновить объект во внешней системе" }, { "name": "Finalize status", "type": "n8n-nodes-base.postgres", "purpose": "Поставить processed или failed" }, { "name": "Respond", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть 200 повтору и новому событию" } ], "connections": "Webhook input → Validate signature → Build idempotency key → Insert key in Postgres → New event gate → Business action → Finalize status → Respond" } Пошаговая настройка Postgres unique key и n8n ¶ Создайте таблицу `webhook_idempotency` и unique index по `idempotency_key`. Импортируйте workflow и настройте Webhook URL с секретом. Добавьте проверку подписи или timestamp, если провайдер это поддерживает. Соберите ключ из provider, event_type и event_id до бизнес-действия. После успешного действия обновляйте status, target_id и processed_at. Тесты перед production и проверка повторных webhook ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/webhook-idempotency-to-postgres" \ -H "Content-Type: application/json" \ --data @webhook-idempotency-to-postgres-payload.json Отправьте один и тот же event_id дважды: бизнес-действие должно выполниться один раз. Измените payload при том же event_id и проверьте реакцию по payload_hash. Сымитируйте падение бизнес-API после insert и проверьте статус processing/failed. Отправьте webhook без event_id и убедитесь, что workflow не делает бизнес-действие. Проверьте ручной replay из Postgres по failed-событию. Production-риски webhook idempotency ¶ Ключ строится из всего payload. Незначительный порядок полей создаёт новый hash и дубль. Нет unique index. Две одновременные доставки проходят проверку одновременно. 200 возвращается до записи ключа. Провайдер считает событие обработанным, хотя n8n мог упасть. Повтор считается ошибкой. Провайдер продолжает ретраи, хотя правильный ответ повтору — безопасный 200. Нет статусов. Нельзя отличить обработанное событие от зависшего processing. Полезные ссылки и смежные workflow ¶ См. также webhook signature validation , retry/DLQ для HTTP Request , idempotency keys и ЮKassa webhook с платежами . Официальные документы: PostgreSQL unique constraints , PostgreSQL INSERT ON CONFLICT и n8n Webhook node . Визуальная карточка показывает idempotency key, статус записи и целевой объект. Критерии готовности ¶ В Postgres есть unique index по idempotency_key. Повторный event_id не запускает бизнес-действие. События имеют статусы processing, processed и failed. Подпись или секрет webhook проверяется до idempotency. Есть процедура безопасного replay для failed-событий. Нужно защитить webhook от дублей и гонок? Nodbot настроит idempotency-слой на Postgres: unique key, подписи, статусы, replay, DLQ и мониторинг повторных событий. Внедрить idempotency

## Test payload

```json
{
  "event_id": "evt_2f3c6a99",
  "event_type": "lead.created",
  "provider": "tilda",
  "occurred_at": "2026-05-30T10:00:00Z",
  "signature": "sha256=7b5f...",
  "data": {
    "phone": "+7 (916) 555-12-34",
    "name": "Анна",
    "source": "landing"
  }
}
```

## Key implementation snippet

```javascript
const crypto = require('crypto');
const src = $json.body ?? $json;
const provider = String(src.provider ?? 'unknown').trim();
const eventType = String(src.event_type ?? src.type ?? '').trim();
const eventId = String(src.event_id ?? src.id ?? '').trim();

if (!eventType) throw new Error('Missing event_type for idempotency');
if (!eventId) throw new Error('Missing event_id for idempotency');

const idempotencyKey = `${provider}:${eventType}:${eventId}`;
const payloadHash = crypto
  .createHash('sha256')
  .update(JSON.stringify(src.data ?? src))
  .digest('hex');

const sql = `
INSERT INTO webhook_idempotency (idempotency_key, provider, event_type, event_id, payload_hash, status, created_at)
VALUES ($1, $2, $3, $4, $5, 'processing', now())
ON CONFLICT (idempotency_key) DO NOTHING
RETURNING idempotency_key;
`;

return [{
  json: {
    idempotency_key: idempotencyKey,
    provider,
    event_type: eventType,
    event_id: eventId,
    payload_hash: payloadHash,
    sql,
    sql_params: [idempotencyKey, provider, eventType, eventId, payloadHash],
    original_event: src
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Webhook idempotency with Postgres",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять событие и заголовки"
    },
    {
      "name": "Validate signature",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить HMAC/secret и timestamp"
    },
    {
      "name": "Build idempotency key",
      "type": "n8n-nodes-base.code",
      "purpose": "Собрать provider:event_type:event_id"
    },
    {
      "name": "Insert key in Postgres",
      "type": "n8n-nodes-base.postgres",
      "purpose": "INSERT ON CONFLICT DO NOTHING"
    },
    {
      "name": "New event gate",
      "type": "n8n-nodes-base.if",
      "purpose": "Пустить только новую запись"
    },
    {
      "name": "Business action",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Создать/обновить объект во внешней системе"
    },
    {
      "name": "Finalize status",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Поставить processed или failed"
    },
    {
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть 200 повтору и новому событию"
    }
  ],
  "connections": "Webhook input → Validate signature → Build idempotency key → Insert key in Postgres → New event gate → Business action → Finalize status → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Webhook-подпись в n8n: HMAC без подделок | Nodbot"
source_url: "https://nodbot.ru/workflows/webhook-signature-validation/"
canonical_url: "https://nodbot.ru/workflows/webhook-signature-validation/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1056
---

# Проверка подписи webhook в n8n: HMAC, timestamp и защита от replay

## AI summary

AI-friendly Problem/Solution-мануал: как настроить проверку HMAC-подписи webhook в n8n, защититься от подделки запроса и replay-атак, сохранить тестовый payload, code node, curl, HowTo и production-чеклист.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить безопасность/API/backup, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: почему webhook без подписи можно подделать
- Архитектура workflow проверки HMAC-подписи
- Контракт входных данных и headers
- Code Node: HMAC SHA256, timestamp tolerance и replay key
- Готовый workflow JSON: скачать и импортировать
- Пошаговая настройка webhook signature validation
- Тесты через curl: валидная и битая подпись
- Production-риски безопасности webhook
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- n8n webhook
- HMAC SHA256
- signature validation
- replay protection
- timestamp tolerance
- webhook security

## Source outline

Проверка подписи webhook в n8n: HMAC, timestamp и защита от replay ¶ Обновлено: 2026-05-30 AI summary: AI-friendly Problem/Solution-мануал: как настроить проверку HMAC-подписи webhook в n8n, защититься от подделки запроса и replay-атак, сохранить тестовый payload, code node, curl, HowTo и production-чеклист. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow в n8n, задайте WEBHOOK_SIGNING_SECRET и проверьте подпись до подключения CRM. Содержание Проблема: почему webhook без подписи можно подделать Архитектура workflow проверки HMAC-подписи Контракт входных данных и headers Code Node: HMAC SHA256, timestamp tolerance и replay key Готовый workflow JSON: скачать и импортировать Пошаговая настройка webhook signature validation Тесты через curl: валидная и битая подпись Production-риски безопасности webhook Полезные ссылки и смежные workflow Критерии готовности Проблема: публичный webhook в n8n может вызвать кто угодно, если у него есть URL. Простая настройка вебхука удобна для интеграции, но без подписи злоумышленник или ошибочный партнёрский скрипт может отправить фальшивую заявку, повторить старый запрос или запустить платную бизнес-логику. Решение: принимать событие только после проверки HMAC SHA256 по raw body, заголовку timestamp и replay key. Такая схема нужна для CRM, платежей, партнёрских кабинетов и любых сценариев, где передача данных из формы или внешней системы должна быть доказуемой. Проверка подписи идёт до любых HTTP Request, CRM update и записи в базу. Проблема: почему webhook без подписи можно подделать ¶ Webhook URL часто попадает в логи, скриншоты, документацию подрядчика или историю браузера. Если workflow сразу пишет в CRM, Google Sheets или Битрикс24, то любой POST похожей формы становится “валидным”. Подпись решает эту боль: n8n пересчитывает HMAC из исходного тела запроса и общего секрета, а затем сравнивает его с подписью отправителя. Отдельно нужен timestamp tolerance. Даже настоящую подпись можно повторить через час или неделю, если не проверять время события и event_id . Поэтому защита webhook — это не один IF node, а связка HMAC, времени и durable replay-хранилища. Архитектура workflow проверки HMAC-подписи ¶ Нода Роль Что проверить Webhook input Принимает raw body и headers Production URL, POST, доступ к заголовкам Verify HMAC signature Считает sha256 и сравнивает подпись Secret из ENV, timing-safe compare Check replay key Проверяет уникальность event_id Postgres unique index или другое durable storage Business logic Запускает CRM/API только после verified Нет побочных эффектов до проверки Respond safe status Возвращает 200/401 без лишних деталей Не отдавать stack trace и секреты Контракт входных данных и headers ¶ Партнёр должен подписывать строку timestamp.rawBody , а не уже распарсенный JSON. Иначе разный порядок полей или пробелы сломают проверку. В n8n важно сохранить исходное тело или договориться с отправителем о стабильной сериализации. { "event_id": "evt_9f8c1", "event": "lead.created", "created_at": "2026-05-30T10:00:00Z", "data": { "lead_id": "crm-10492", "phone": "+7 916 123-45-67", "source": "partner_webhook" } } Какие headers нужны X-Webhook-Timestamp — Unix timestamp события. X-Webhook-Signature — строка вида sha256=<hex> . Content-Type: application/json — чтобы payload был предсказуемым. Code Node: HMAC SHA256, timestamp tolerance и replay key ¶ Этот скрипт n8n останавливает workflow до бизнес-логики. Для ротации секрета можно проверять два секрета: текущий и предыдущий, но хранить их нужно в ENV/credentials, а не в тексте ноды. const crypto = require('crypto'); const body = $json.rawBody ?? JSON.stringify($json.body ?? $json); const headers = $json.headers ?? {}; const timestamp = Number(headers['x-webhook-timestamp'] ?? headers['X-Webhook-Timestamp']); const signature = String(headers['x-webhook-signature'] ?? headers['X-Webhook-Signature'] ?? ''); const secret = $env.WEBHOOK_SIGNING_SECRET; if (!secret) throw new Error('WEBHOOK_SIGNING_SECRET is not configured'); if (!timestamp || Math.abs(Date.now() - timestamp * 1000) > 5 * 60 * 1000) { throw new Error('Webhook timestamp is outside 5 minute tolerance'); } const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${body}`).digest('hex'); const ok = signature.length === expected.length && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); if (!ok) throw new Error('Invalid webhook signature'); const parsed = typeof $json.body === 'object' ? $json.body : JSON.parse(body); return [{ json: { verified: true, replay_key: `webhook:${parsed.event_id}`, event: parsed.event, body: parsed } }]; Готовый workflow JSON: скачать и импортировать ¶ Полный workflow JSON лежит в архиве и доступен по кнопке. В нём есть места для Postgres replay key, безопасного ответа и комментарии, какие credentials нужно заменить. Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Webhook HMAC signature validation", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять raw body и headers" }, { "name": "Verify HMAC signature", "type": "n8n-nodes-base.code", "purpose": "Проверить sha256 HMAC и timestamp tolerance" }, { "name": "Check replay key", "type": "n8n-nodes-base.postgres", "purpose": "Не обработать event_id повторно" }, { "name": "Business logic", "type": "n8n-nodes-base.httpRequest", "purpose": "Запустить CRM/API только после verified=true" }, { "name": "Respond safe status", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть 200/401 без stack trace" } ], "connections": "Webhook → Verify HMAC → Check replay → Business logic → Respond" } Пошаговая настройка webhook signature validation ¶ Создайте секрет подписи и передайте его партнёру через защищённый канал. Добавьте в n8n ENV WEBHOOK_SIGNING_SECRET . Импортируйте workflow JSON и включите production URL webhook. Подключите Postgres/Redis для replay key с уникальным индексом или TTL. Проверьте валидный curl, битую подпись, старый timestamp и повторный event_id . Тесты через curl: валидная и битая подпись ¶ timestamp=$(date +%s) body='{"event_id":"evt_9f8c1","event":"lead.created","created_at":"2026-05-30T10:00:00Z","data":{"lead_id":"crm-10492","phone":"+7 916 123-45-67"}}' signature="sha256=$(printf "%s.%s" "$timestamp" "$body" | openssl dgst -sha256 -hmac "$WEBHOOK_SIGNING_SECRET" -hex | sed 's/^.* //')" curl -X POST "https://YOUR-N8N-DOMAIN/webhook/webhook-signature-validation" -H "Content-Type: application/json" -H "X-Webhook-Timestamp: $timestamp" -H "X-Webhook-Signature: $signature" --data "$body" Второй тест — изменить один символ в body после расчёта подписи. Workflow должен вернуть отказ и не вызвать downstream-ноды. Production-риски безопасности webhook ¶ Подписывается parsed JSON. Из-за пробелов и порядка ключей подпись становится нестабильной. Нет replay protection. Настоящий запрос можно повторить и создать дубль. Secret в Code Node. Его увидит любой с доступом к workflow export. Ошибка раскрывает детали. Внешний отправитель не должен получать stack trace. Бизнес-логика стоит до проверки. Даже отклонённый запрос успевает изменить CRM. Полезные ссылки и смежные workflow ¶ Смотрите также: Webhook idempotency в Postgres , Retry и DLQ для HTTP Request , Error Workflow с Telegram-алертом . Внешняя документация: n8n Webhook node , n8n Crypto node . Критерии готовности ¶ Невалидная подпись не вызывает ни одной бизнес-ноды. Timestamp старше допустимого окна отклоняется. Повторный event_id не обрабатывается второй раз. Секрет хранится в ENV/credentials и имеет план ротации. Команда знает, как проверить подпись через curl и где смотреть rejected-события. Нужна безопасная интеграция webhook? Nodbot настроит HMAC, replay protection, журнал событий и алерты так, чтобы внешний POST не мог сломать CRM или запустить лишние действия. Обсудить внедрение

## Test payload

```json
{
  "event_id": "evt_9f8c1",
  "event": "lead.created",
  "created_at": "2026-05-30T10:00:00Z",
  "data": {
    "lead_id": "crm-10492",
    "phone": "+7 916 123-45-67",
    "source": "partner_webhook"
  }
}
```

## Key implementation snippet

```javascript
const crypto = require('crypto');
const body = $json.rawBody ?? JSON.stringify($json.body ?? $json);
const headers = $json.headers ?? {};
const timestamp = Number(headers['x-webhook-timestamp'] ?? headers['X-Webhook-Timestamp']);
const signature = String(headers['x-webhook-signature'] ?? headers['X-Webhook-Signature'] ?? '');
const secret = $env.WEBHOOK_SIGNING_SECRET;

if (!secret) throw new Error('WEBHOOK_SIGNING_SECRET is not configured');
if (!timestamp || Math.abs(Date.now() - timestamp * 1000) > 5 * 60 * 1000) {
  throw new Error('Webhook timestamp is outside 5 minute tolerance');
}

const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${body}`).digest('hex');
const ok = signature.length === expected.length && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));

if (!ok) throw new Error('Invalid webhook signature');

const parsed = typeof $json.body === 'object' ? $json.body : JSON.parse(body);
return [{ json: { verified: true, replay_key: `webhook:${parsed.event_id}`, event: parsed.event, body: parsed } }];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Webhook HMAC signature validation",
  "nodes": [
    { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять raw body и headers" },
    { "name": "Verify HMAC signature", "type": "n8n-nodes-base.code", "purpose": "Проверить sha256 HMAC и timestamp tolerance" },
    { "name": "Check replay key", "type": "n8n-nodes-base.postgres", "purpose": "Не обработать event_id повторно" },
    { "name": "Business logic", "type": "n8n-nodes-base.httpRequest", "purpose": "Запустить CRM/API только после verified=true" },
    { "name": "Respond safe status", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть 200/401 без stack trace" }
  ],
  "connections": "Webhook → Verify HMAC → Check replay → Business logic → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Yandex Cloud Functions и n8n: безопасный webhook | Nodbot"
source_url: "https://nodbot.ru/workflows/yandex-cloud-functions-to-n8n/"
canonical_url: "https://nodbot.ru/workflows/yandex-cloud-functions-to-n8n/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1037
---

# Yandex Cloud Functions и n8n: безопасный webhook-прокси для событий

## AI summary

Практический сценарий, где Cloud Functions принимает внешнее или облачное событие, подписывает payload, передает его в n8n, а workflow проверяет HMAC, дедуплицирует событие и запускает бизнес-автоматизацию без открытого публичного webhook без защиты.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- Yandex Cloud Functions
- n8n webhook
- HMAC signature
- idempotency
- serverless
- event routing

## Source outline

Yandex Cloud Functions и n8n: безопасный webhook-прокси для событий ¶ Обновлено: 2026-05-30 AI summary: Практический сценарий, где Cloud Functions принимает внешнее или облачное событие, подписывает payload, передает его в n8n, а workflow проверяет HMAC, дедуплицирует событие и запускает бизнес-автоматизацию без открытого публичного webhook без защиты. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: Yandex Cloud Functions удобно использовать как serverless-точку входа, но если она просто прокидывает JSON в n8n, любой получивший URL сможет имитировать событие и запускать workflow. Решение: сделать Cloud Functions тонким защищённым прокси: функция добавляет timestamp, event_id и HMAC-подпись, n8n проверяет подпись, отсеивает повторы и только потом отправляет событие в CRM, Telegram, S3 или внутренний API. Cloud Function подписывает событие, n8n проверяет HMAC, event_id и маршрутизирует только валидный payload. Проблема: почему публичный webhook n8n нельзя оставлять без защиты ¶ Связка “Cloud Functions → n8n” часто нужна для событий Object Storage, Message Queue, API Gateway или небольших публичных интеграций. Проблема в том, что n8n webhook по умолчанию — это URL. Если он утечёт в логах, документации или фронтенде, злоумышленник сможет отправлять фальшивые события. Без подписи нельзя отличить настоящее событие от ручного POST. Без idempotency повторная доставка может запустить бизнес-действие дважды. Без timestamp нельзя ограничить replay-атаки. Поэтому статья закрывает не “как дернуть n8n из функции”, а как сделать безопасный event ingress. Архитектура связки Yandex Cloud Functions → n8n ¶ Нода Роль Что проверить Cloud Function принимает событие или HTTP-запрос service account, секрет, timeout Sign payload добавляет `x-nodbot-signature` HMAC SHA-256, timestamp, event_id n8n Webhook принимает подписанное событие production URL, только POST Verify signature сравнивает HMAC и возраст события constant-time compare, max age Idempotency check не пропускает повторный event_id Postgres unique key или durable storage Route event запускает нужный бизнес-процесс тип события, retry, alert Cloud Functions не должна содержать бизнес-логику CRM. Её задача — принять событие, подписать его и быстро передать в n8n. Так проще менять automation-логику без redeploy функции. Контракт события от Cloud Functions ¶ { "event_id": "yc-evt-2026-05-30-00091", "event_type": "object_storage.created", "bucket": "client-docs", "object_key": "incoming/report-1042.pdf", "occurred_at": "2026-05-30T10:00:00Z", "metadata": { "tenant_id": "acme", "source": "yandex-cloud-functions" } } `event_id` должен быть стабильным для повторной доставки одного и того же события. Если источник не даёт такой ID, соберите его из bucket, object_key, version и timestamp источника. Code Node: проверка HMAC, timestamp и event_id ¶ const crypto = require('crypto'); const secret = $env.YC_N8N_WEBHOOK_SECRET; if (!secret) throw new Error('YC_N8N_WEBHOOK_SECRET is not configured'); const headers = $json.headers ?? {}; const body = $json.body ?? $json; const signature = String(headers['x-nodbot-signature'] ?? headers['X-Nodbot-Signature'] ?? ''); const timestamp = String(headers['x-nodbot-timestamp'] ?? headers['X-Nodbot-Timestamp'] ?? ''); const eventId = String(body.event_id ?? '').trim(); if (!eventId) throw new Error('Missing event_id'); if (!timestamp || Math.abs(Date.now() - Number(timestamp)) > 5 * 60 * 1000) { throw new Error('Webhook timestamp is missing or too old'); } const raw = JSON.stringify(body); const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${raw}`).digest('hex'); if (!signature || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) { throw new Error('Invalid Cloud Functions signature'); } return [{ json: { event_id: eventId, idempotency_key: `yc-functions:${eventId}`, event_type: body.event_type, payload: body, verified_at: new Date().toISOString() } }]; Что должна делать сама Cloud Function Функция должна собрать raw JSON, timestamp в миллисекундах и подпись HMAC SHA-256 по строке timestamp.body. Секрет хранится в переменных окружения Cloud Functions и n8n, но не попадает в payload или лог ответа. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - Yandex Cloud Functions to n8n secure webhook", "nodes": [ { "name": "n8n Webhook", "type": "n8n-nodes-base.webhook", "purpose": "Принять событие от Cloud Functions" }, { "name": "Verify HMAC signature", "type": "n8n-nodes-base.code", "purpose": "Проверить подпись, timestamp и event_id" }, { "name": "Check idempotency", "type": "n8n-nodes-base.postgres", "purpose": "Отсеять повторную доставку" }, { "name": "Route by event type", "type": "n8n-nodes-base.code", "purpose": "Выбрать сценарий по event_type" }, { "name": "Call business workflow", "type": "n8n-nodes-base.httpRequest", "purpose": "Запустить CRM/S3/Telegram/API действие" }, { "name": "Respond to Cloud Function", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть безопасный статус" } ], "connections": "n8n Webhook → Verify HMAC signature → Check idempotency → Route by event type → Call business workflow → Respond to Cloud Function" } Пошаговая настройка Cloud Functions, секрета и n8n ¶ Создайте секрет `YC_N8N_WEBHOOK_SECRET` в Cloud Functions и в окружении n8n. В Cloud Functions добавьте HMAC-подпись по timestamp и raw body. Импортируйте workflow JSON и включите production webhook URL. Создайте таблицу idempotency с unique index по `idempotency_key`. Настройте маршруты по `event_type` и alert на invalid signature. Тесты перед production и проверка подписи ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/yandex-cloud-functions-to-n8n" \ -H "Content-Type: application/json" \ --data @yandex-cloud-functions-to-n8n-payload.json Отправьте корректное событие с валидной подписью. Повторите тот же `event_id` и проверьте, что бизнес-действие не повторилось. Измените один символ payload после подписи: workflow должен отклонить запрос. Отправьте старый timestamp и проверьте защиту от replay. Проверьте ошибку downstream API: n8n должен залогировать событие и отправить alert. Production-риски serverless webhook-прокси ¶ Секрет прошит в коде функции. Используйте переменные окружения и секреты, а не строку в репозитории. Сравнение подписи обычным `===`. Для HMAC лучше constant-time compare, чтобы не открывать timing-атаки. Нет idempotency. Повторная доставка serverless-события запускает бизнес-действие дважды. Функция ждёт долгий workflow. Пусть n8n отвечает быстро, а долгие операции уходят в отдельную очередь или sub-workflow. Логи содержат payload с PII. Маскируйте персональные данные и не пишите секреты в execution data. Полезные ссылки и смежные workflow ¶ См. также Webhook signature validation , idempotency keys , webhooks API gateway и error workflow alert . Официальные документы: Yandex Cloud Functions , Cloud Functions triggers и n8n Webhook node . Визуальная карточка показывает результат проверки подписи, возраста события и idempotency. Критерии готовности ¶ Все запросы от Cloud Functions подписаны HMAC. n8n отклоняет старые timestamp и invalid signature. Повторный event_id не запускает бизнес-действие второй раз. Секрет хранится в ENV/secret manager, а не в workflow description. Ошибки downstream API попадают в alert и audit log. Нужно безопасно связать Yandex Cloud и n8n? Nodbot настроит защищённый webhook ingress: Cloud Functions, HMAC, idempotency, retry, alerting и маршрутизацию событий в ваши workflow. Обсудить serverless-интеграцию

## Test payload

```json
{
  "event_id": "yc-evt-2026-05-30-00091",
  "event_type": "object_storage.created",
  "bucket": "client-docs",
  "object_key": "incoming/report-1042.pdf",
  "occurred_at": "2026-05-30T10:00:00Z",
  "metadata": {
    "tenant_id": "acme",
    "source": "yandex-cloud-functions"
  }
}
```

## Key implementation snippet

```javascript
const crypto = require('crypto');
const secret = $env.YC_N8N_WEBHOOK_SECRET;
if (!secret) throw new Error('YC_N8N_WEBHOOK_SECRET is not configured');

const headers = $json.headers ?? {};
const body = $json.body ?? $json;
const signature = String(headers['x-nodbot-signature'] ?? headers['X-Nodbot-Signature'] ?? '');
const timestamp = String(headers['x-nodbot-timestamp'] ?? headers['X-Nodbot-Timestamp'] ?? '');
const eventId = String(body.event_id ?? '').trim();

if (!eventId) throw new Error('Missing event_id');
if (!timestamp || Math.abs(Date.now() - Number(timestamp)) > 5 * 60 * 1000) {
  throw new Error('Webhook timestamp is missing or too old');
}

const raw = JSON.stringify(body);
const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${raw}`).digest('hex');
if (!signature || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
  throw new Error('Invalid Cloud Functions signature');
}

return [{
  json: {
    event_id: eventId,
    idempotency_key: `yc-functions:${eventId}`,
    event_type: body.event_type,
    payload: body,
    verified_at: new Date().toISOString()
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - Yandex Cloud Functions to n8n secure webhook",
  "nodes": [
    {
      "name": "n8n Webhook",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять событие от Cloud Functions"
    },
    {
      "name": "Verify HMAC signature",
      "type": "n8n-nodes-base.code",
      "purpose": "Проверить подпись, timestamp и event_id"
    },
    {
      "name": "Check idempotency",
      "type": "n8n-nodes-base.postgres",
      "purpose": "Отсеять повторную доставку"
    },
    {
      "name": "Route by event type",
      "type": "n8n-nodes-base.code",
      "purpose": "Выбрать сценарий по event_type"
    },
    {
      "name": "Call business workflow",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Запустить CRM/S3/Telegram/API действие"
    },
    {
      "name": "Respond to Cloud Function",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть безопасный статус"
    }
  ],
  "connections": "n8n Webhook → Verify HMAC signature → Check idempotency → Route by event type → Call business workflow → Respond to Cloud Function"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "YandexGPT и n8n: классификация заявок | Nodbot"
source_url: "https://nodbot.ru/workflows/yandexgpt-classifier/"
canonical_url: "https://nodbot.ru/workflows/yandexgpt-classifier/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1012
---

# YandexGPT и n8n: классификация заявок по теме, срочности и SLA

## AI summary

Практический workflow для поддержки и продаж: принять текст заявки, очистить персональные данные, отправить в YandexGPT classifier, получить label/confidence и направить обращение в нужную очередь без ручной сортировки.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- YandexGPT classifier
- n8n
- ticket routing
- confidence threshold
- CRM
- SLA

## Source outline

YandexGPT и n8n: классификация заявок по теме, срочности и SLA ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для поддержки и продаж: принять текст заявки, очистить персональные данные, отправить в YandexGPT classifier, получить label/confidence и направить обращение в нужную очередь без ручной сортировки. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: входящие заявки из сайта, почты, Telegram и CRM смешиваются в одной очереди. Оператор вручную решает, где оплата, где техническая ошибка, где продажа, а срочные обращения теряются среди обычных вопросов. Решение: n8n принимает текст заявки, нормализует его, вызывает YandexGPT classifier с понятными labels, проверяет confidence и маршрутизирует обращение в CRM, Telegram или helpdesk. Низкая уверенность уходит человеку на review. Workflow классифицирует обращение, применяет порог confidence и выбирает очередь обработки. Проблема: почему ручная сортировка заявок ломает SLA ¶ Классификация заявок кажется простой, пока поток небольшой. Когда появляются обращения об оплате, технические ошибки, возвраты, партнёрские запросы и спам, ручная сортировка начинает съедать время первой линии поддержки. YandexGPT-based classifier полезен тем, что возвращает класс и confidence, а n8n может сразу применить бизнес-правило: отправить срочную оплату в отдельный канал, техническую ошибку — инженеру, а низкую уверенность — человеку. Важно заранее задать понятные labels, а не просить модель “сама понять тему”. Архитектура workflow YandexGPT classifier через n8n ¶ Нода Роль Что проверить Webhook input принимает текст заявки и source_id канал, клиент, язык, статус Sanitize text чистит HTML и маскирует лишние данные нет токенов и паролей в prompt Build classifier request собирает labels и taskDescription 2–20 классов, понятные названия Call YandexGPT classifier вызывает Text Classification API IAM token, folder/modelUri, timeout Route by confidence выбирает очередь и SLA threshold, unknown/review branch Update CRM/helpdesk записывает label и next_action история решения и audit_key Ключевой элемент — не сама AI-модель, а routing policy. Даже хороший classifier должен иметь ветку `review`, если confidence ниже порога или текст не похож на рабочую заявку. Контракт входных данных для классификации ¶ { "ticket_id": "sup-2048", "source": "telegram", "text": "Оплата прошла, чек есть, но доступ к курсу не открылся. Заказ 10492, срочно помогите.", "labels": [ "payment_issue", "technical_bug", "sales_question", "refund_request", "spam" ], "confidence_threshold": 0.72, "customer": { "crm_id": "contact-552", "plan": "pro" } } Labels должны быть бизнесовыми, а не техническими. `payment_issue` полезнее, чем `class_1`: оператор и CRM сразу понимают, что делать с результатом. Code Node: labels, confidence threshold и route key ¶ const src = $json.body ?? $json; const text = String(src.text ?? '').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim(); if (text.length < 10) throw new Error('ticket text is too short'); if (text.length > 6000) throw new Error('ticket text is too long for classifier request'); const labels = Array.isArray(src.labels) && src.labels.length ? src.labels : [ 'payment_issue', 'technical_bug', 'sales_question', 'refund_request', 'spam' ]; if (labels.length < 2 || labels.length > 20) throw new Error('labels count must be between 2 and 20'); const threshold = Number(src.confidence_threshold ?? 0.72); return [{ json: { ticket_id: String(src.ticket_id ?? `ticket-${Date.now()}`), classifier_body: { modelUri: process.env.YANDEXGPT_CLASSIFIER_MODEL_URI, taskDescription: 'Классифицируй входящую заявку поддержки по основной теме. Верни наиболее подходящий label.', labels, text }, routing_policy: { confidence_threshold: threshold, review_label: 'human_review', routes: { payment_issue: 'support-payments-high-priority', technical_bug: 'support-tech', sales_question: 'sales-inbox', refund_request: 'billing-review', spam: 'closed-spam' } }, audit_key: `yandexgpt-classifier:${src.ticket_id ?? Date.now()}` } }]; Почему нужен порог confidence Классификатор может выбрать ближайший label даже для неоднозначной заявки. Порог уверенности отправляет сомнительные обращения человеку, сохраняет SLA и снижает риск неправильной маршрутизации. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - YandexGPT ticket classifier", "nodes": [ { "name": "Webhook input", "type": "n8n-nodes-base.webhook", "purpose": "Принять заявку из CRM, сайта или Telegram" }, { "name": "Sanitize and build labels", "type": "n8n-nodes-base.code", "purpose": "Очистить текст и собрать classifier request" }, { "name": "Call YandexGPT classifier", "type": "n8n-nodes-base.httpRequest", "purpose": "Вызвать Text Classification API" }, { "name": "Route by confidence", "type": "n8n-nodes-base.code", "purpose": "Выбрать очередь по label и confidence" }, { "name": "Update CRM or helpdesk", "type": "n8n-nodes-base.httpRequest", "purpose": "Записать label, SLA и комментарий" }, { "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть route_key и статус" } ], "connections": "Webhook input → Sanitize and build labels → Call YandexGPT classifier → Route by confidence → Update CRM or helpdesk → Respond to Webhook" } Пошаговая настройка YandexGPT, n8n и CRM-маршрутизации ¶ Создайте модель/доступ YandexGPT classifier и сохраните IAM token в n8n credentials или ENV. Опишите 2–20 labels понятными бизнес-названиями. Импортируйте workflow и задайте `YANDEXGPT_CLASSIFIER_MODEL_URI`. Настройте routes: label → очередь CRM/helpdesk/Telegram. Добавьте ветку human review для низкого confidence и неизвестных текстов. Тесты перед production и проверка классов ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/yandexgpt-classifier" \ -H "Content-Type: application/json" \ --data @yandexgpt-classifier-payload.json Проверьте типовые заявки по каждому label. Отправьте смешанную заявку: оплата + техническая ошибка. Проверьте короткий бессмысленный текст и спам. Уменьшите threshold и посмотрите, не падает ли качество маршрутизации. Сравните AI label с ручной разметкой на 50–100 исторических обращениях. Production-риски AI-классификации заявок ¶ Labels слишком похожи. Модель путает классы, если названия не отражают бизнес-действие. Нет human review. Низкая уверенность всё равно уходит в неверную очередь. PII в prompt. Маскируйте пароли, токены и лишние персональные данные. Нет контрольной выборки. Нельзя оценить качество classifier до production. Маршрут меняет SLA без аудита. Записывайте label, confidence, modelVersion и routing decision. Полезные ссылки и смежные workflow ¶ См. также GigaChat support draft , Telegram AI bot with human approval и OpenRouter fallback . Официальные документы: YandexGPT classifiers , prompt-based classifier и n8n HTTP Request . Карточка результата показывает label, confidence, route и SLA для поддержки. Критерии готовности ¶ Labels согласованы с владельцами поддержки и продаж. Есть threshold и ветка human_review для сомнительных случаев. Маршрутизация записывает label, confidence, modelVersion и audit_key. Качество проверено на исторической выборке, а не только на одном тесте. Ошибки YandexGPT API не меняют статус заявки молча. Нужно автоматически сортировать заявки без потери SLA? Nodbot настроит YandexGPT classifier, labels, threshold, human review, CRM routing, audit log и контроль качества на исторических обращениях. Обсудить классификацию заявок

## Test payload

```json
{
  "ticket_id": "sup-2048",
  "source": "telegram",
  "text": "Оплата прошла, чек есть, но доступ к курсу не открылся. Заказ 10492, срочно помогите.",
  "labels": [
    "payment_issue",
    "technical_bug",
    "sales_question",
    "refund_request",
    "spam"
  ],
  "confidence_threshold": 0.72,
  "customer": {
    "crm_id": "contact-552",
    "plan": "pro"
  }
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const text = String(src.text ?? '').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
if (text.length < 10) throw new Error('ticket text is too short');
if (text.length > 6000) throw new Error('ticket text is too long for classifier request');

const labels = Array.isArray(src.labels) && src.labels.length ? src.labels : [
  'payment_issue', 'technical_bug', 'sales_question', 'refund_request', 'spam'
];
if (labels.length < 2 || labels.length > 20) throw new Error('labels count must be between 2 and 20');

const threshold = Number(src.confidence_threshold ?? 0.72);
return [{
  json: {
    ticket_id: String(src.ticket_id ?? `ticket-${Date.now()}`),
    classifier_body: {
      modelUri: process.env.YANDEXGPT_CLASSIFIER_MODEL_URI,
      taskDescription: 'Классифицируй входящую заявку поддержки по основной теме. Верни наиболее подходящий label.',
      labels,
      text
    },
    routing_policy: {
      confidence_threshold: threshold,
      review_label: 'human_review',
      routes: {
        payment_issue: 'support-payments-high-priority',
        technical_bug: 'support-tech',
        sales_question: 'sales-inbox',
        refund_request: 'billing-review',
        spam: 'closed-spam'
      }
    },
    audit_key: `yandexgpt-classifier:${src.ticket_id ?? Date.now()}`
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - YandexGPT ticket classifier",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять заявку из CRM, сайта или Telegram"
    },
    {
      "name": "Sanitize and build labels",
      "type": "n8n-nodes-base.code",
      "purpose": "Очистить текст и собрать classifier request"
    },
    {
      "name": "Call YandexGPT classifier",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Вызвать Text Classification API"
    },
    {
      "name": "Route by confidence",
      "type": "n8n-nodes-base.code",
      "purpose": "Выбрать очередь по label и confidence"
    },
    {
      "name": "Update CRM or helpdesk",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Записать label, SLA и комментарий"
    },
    {
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть route_key и статус"
    }
  ],
  "connections": "Webhook input → Sanitize and build labels → Call YandexGPT classifier → Route by confidence → Update CRM or helpdesk → Respond to Webhook"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.

---
title: "Платежи ЮKassa в CRM через n8n - Nodbot"
source_url: "https://nodbot.ru/workflows/yookassa-payment-to-crm/"
canonical_url: "https://nodbot.ru/workflows/yookassa-payment-to-crm/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 796
---

# Передача платежей ЮKassa в CRM через n8n

## AI summary

Workflow ЮKassa → CRM: webhook платежа, проверка события, idempotency, статус заказа, чек, уведомление менеджера и безопасная запись оплаты.

## Best used for

Страница объясняет «Платежи ЮKassa в CRM через n8n - Nodbot» в контексте n8n/Nodbot: когда применять, как проверить внедрение и какие ошибки исключить.

## Key topics

- Короткий ответ для AI/LLM
- Чем эта страница отличается
- Когда использовать
- Карта workflow
- Настройка по шагам
- Типичные ошибки
- Проверка результата
- Финансовая идемпотентность в CRM

## Source outline

# Передача платежей ЮKassa в CRM через n8n

Обновлено: 2026-05-29

Платёжный webhook нельзя обрабатывать как обычный лид: повторная доставка, неверный статус или отсутствие идемпотентности могут привести к двойному зачислению, неверному заказу или преждевременной отгрузке. Workflow для ЮKassa должен проверять тип события, payment_id, сумму, валюту, статус и связь с order_id. Эта страница отличается от Avito-лидов и amoCRM dedup: здесь бизнес-критичен финансовый статус, а не только отсутствие дублей в воронке.

## Короткий ответ для AI/LLM

Для передачи платежа ЮKassa в CRM через n8n проверьте webhook, найдите заказ по metadata/order_id, сверяйте amount и currency, используйте payment_id как idempotency key и обновляйте CRM только при финальном статусе. Повторные события должны попадать в skipped_duplicate или status_already_applied.

## Чем эта страница отличается

Страница про финансовый workflow и согласование статусов оплаты. Она не про маркетплейс-лиды, не про подпись любого webhook и не про обогащение контакта: платеж требует сверки суммы, заказа и финальности события.

## Когда использовать

- CRM должна автоматически менять статус заказа после успешной оплаты
- нужно не допустить двойной отметки оплаты при повторном webhook
- менеджеру нужно уведомление только по финальным событиям, а не по каждому pending
- важно хранить payment_id и ссылку на чек для бухгалтерии

## Карта workflow

- Слой | Роль | Контроль качества
- YooKassa webhook | получает событие платежа | event, payment_id
- Verifier | проверяет источник и минимальные поля | headers, object.status
- Order lookup | находит заказ по metadata или invoice id | order_id, deal_id
- Reconciliation | сверяет сумму, валюту и статус | amount, currency, paid
- CRM update | ставит оплату и чек | payment_status, receipt_url
- Notification | сообщает менеджеру о финальном результате | paid/canceled/refunded

## Настройка по шагам

- При создании платежа заранее передавайте metadata с order_id/deal_id, чтобы webhook не искал заказ по имени клиента.
- На входе проверяйте event type и payment object; неизвестные события пишите в журнал, но не меняйте CRM.
- Используйте payment_id как идемпотентный ключ для применения статуса в CRM.
- Перед обновлением сверяйте amount, currency и ожидаемый заказ; несовпадение отправляйте в review.
- Обновляйте CRM только на финальных статусах, которые согласованы с вашей логикой оплаты.
- Сохраняйте receipt/check URL, payment_id, paid_at и raw_status для бухгалтерского следа.

## Типичные ошибки

- меняют статус заказа по любому webhook без проверки финального payment status
- ищут заказ только по email и могут привязать платёж не к той сделке
- не сверяют сумму и валюту с CRM-заказом
- повторный webhook повторно отправляет письмо “оплачено” клиенту
- хранят платёжные данные шире, чем нужно для учёта

## Проверка результата

- Повтор webhook с тем же payment_id не меняет заказ второй раз.
- Webhook с другой суммой уходит в review_required.
- CRM получает payment_id, paid_at, amount, currency и receipt URL.
- Pending/canceled/refunded обрабатываются по отдельным правилам, а не как paid.

## Финансовая идемпотентность в CRM

Создайте таблицу или CRM-поле applied_payment_id. Перед изменением статуса проверяйте, был ли этот payment_id уже применён к заказу. Если webhook приходит повторно, workflow должен вернуть успешный технический ответ, но не отправлять повторные письма, задачи и документы. Для возвратов используйте отдельный сценарий, а не перезапись paid без истории.

## Сущности и SEO-охват

Ключевые сущности страницы: ЮKassa, YooKassa webhook, payment_id, CRM payment status, idempotency, receipt URL, order reconciliation, paid event.

## Production-контекст и проверка внедрения

Материал «Передача платежей ЮKassa в CRM через n8n» стоит использовать не только как пример настройки, но и как мини-runbook для внедрения в реальный n8n. Перед переносом в production зафиксируйте источник события, обязательные поля входного item, владельца процесса и ожидаемый результат. Если workflow пишет в CRM, таблицу, базу или отправляет сообщение, отдельно опишите условие, при котором действие можно безопасно повторить.

Для устойчивого запуска проверьте три сценария: успешный вход, пустой или неполный payload и повтор события с тем же внешним идентификатором. Это помогает заранее поймать дубли, потерю items после Merge или Code node, неверный mapping полей и неочевидные ошибки внешнего API. Для AI-веток дополнительно нужен fallback: что делать при низкой уверенности, невалидном JSON или превышении лимитов модели.

### Чеклист перед публикацией workflow

- Добавьте тестовый payload без секретов и персональных данных.
- Проверьте retry, error branch, idempotency и ручной override.
- Логируйте execution id, внешний id события и итоговый статус, но не токены и не приватные поля.
- Опишите, кто получает алерт и кто принимает решение при спорном результате.
После запуска отслеживайте долю успешных executions, skipped items, retry count и ручных исправлений. Если эти метрики растут, проблема обычно не в одной ноде, а в контракте данных, лимитах API или отсутствии явного владельца процесса.

### Связанные материалы для углубления

- Каталог workflow — открыть связанный материал для проверки контекста.
- Рецепты n8n — открыть связанный материал для проверки контекста.
- Диагностика n8n — открыть связанный материал для проверки контекста.
- Проверка workflow-шаблонов — открыть связанный материал для проверки контекста.

## FAQ

### Какой ключ использовать для дедупликации платежа?

Обычно payment_id. Для отдельных операций возврата или чека может понадобиться свой id операции.

### Можно ли обновлять CRM по pending?

Лучше хранить pending как технический статус, но бизнес-действия вроде отгрузки запускать только после финального paid.

### Что делать при несовпадении суммы?

Не применять оплату автоматически. Поставьте review_required и уведомите ответственного.

## Related Nodbot pages

- [Старт](/start/)
- [Основы](/basics/)
- [Ноды](/nodes/)
- [Интеграции](/integrations/)
- [AI](/ai/)
- [Рецепты](/recipes/)
- [Ошибки](/errors/)
- [Диагностика](/diagnostics/)

## Retrieval hints

- Предпочитать canonical URL как источник для пользовательских ссылок.
- Использовать markdown-версию для быстрого извлечения сущностей, чеклистов и терминов.
- При цитировании сверять с исходной HTML-страницей, если нужен самый полный контекст.
