Перейти к содержанию

amoCRM и n8n: интеграция форм, сделок и webhook без дублей

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

AI summary: Практический гайд по amoCRM и n8n: как принимать заявки из форм и мессенджеров, нормализовать данные, искать контакт/сделку, создавать связку contact+lead, сохранять UTM, обрабатывать webhooks и не ломать воронку дублями.
Готовый blueprint для внедрения

Используйте JSON как основу: замените credentials, URL порталов, поля CRM и правила дедупликации.

Проблема: amoCRM легко подключить к форме, но сложнее сделать так, чтобы повторный лид не создавал вторую сделку, OAuth не падал в production, webhook не зацикливал workflow, а менеджер видел правильный pipeline и источник заявки.

Решение: выносить бизнес-логику в n8n: единый payload, нормализация phone/email, поиск контакта и открытой сделки, контролируемый create/update, отдельные поля для UTM, retry на API и журнал idempotency для webhook-событий.

Схема интеграции amoCRM и n8n с upsert контакта и webhook guard
Схема показывает, как n8n принимает лид, проверяет дубли и защищается от webhook loop.

Проблема: почему связка amoCRM и n8n быстро создаёт хаос в воронке

Частая боль отдела продаж — одна и та же заявка приходит из Tilda, Telegram, email и рекламной формы, а amoCRM получает несколько открытых сделок по одному человеку. Менеджер не понимает, какую карточку вести, а отчёт по источникам становится недостоверным.

Вторая проблема — webhook из amoCRM. Если workflow слушает изменение сделки и сам же меняет эту сделку, легко получить цикл обновлений. Поэтому интеграция должна иметь idempotency key, фильтр событий, журнал обработанных webhook и понятный список полей, которые n8n имеет право менять.

Архитектура интеграции amoCRM, n8n, форм и webhook

БлокЗадачаProduction-проверка
Inbound sourceполучает форму, чат или письмоsource, external_id, consent, UTM
Normalize payloadготовит contact, lead и custom fieldsphone +7, email lowercase, pipeline_id
Find contact/dealищет существующую карточкуоткрытые сделки, контакт по телефону/email
Upsert amoCRMсоздаёт или обновляет contact+leadcustom_fields_values, tags, responsible_user_id
Webhook guardфильтрует исходящие события amoCRMevent type, entity id, idempotency key
Monitoringуведомляет о сбоях401/403 OAuth, 429, 5xx, DLQ

Для простых форм можно начать с HTTP Request. Для сложной логики — community node, но контракт данных и дедупликацию всё равно лучше держать явно в workflow.

Контракт заявки для amoCRM API

{
  "source": "telegram",
  "external_id": "tg-88421",
  "name": "Илья",
  "phone": "+7 916 200-44-55",
  "email": "ilya@example.ru",
  "pipeline_id": 123456,
  "status_id": 654321,
  "utm_source": "telegram",
  "utm_medium": "bot",
  "comment": "Интересуется внедрением amoCRM и n8n"
}

Не пытайтесь парсить pipeline и статус из комментария. Для amoCRM они должны быть явными параметрами: иначе тестовая воронка и production-вронка быстро смешаются.

Code Node: нормализация и контроль качества

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}`;
if (!/^7\d{10}$/.test(digits)) throw new Error(`Invalid amoCRM phone: ${rawPhone}`);
const email = String(src.email ?? '').trim().toLowerCase();
const pipelineId = Number(src.pipeline_id || $env.AMOCRM_DEFAULT_PIPELINE_ID);
const statusId = Number(src.status_id || $env.AMOCRM_DEFAULT_STATUS_ID);
return [{ json: {
  dedupe_key: `amocrm:${digits}:${email || 'no-email'}`,
  contact: { name: src.name || 'Новый контакт', phone: `+${digits}`, email },
  lead: {
    name: `Заявка: ${src.name || '+7 lead'}`,
    pipeline_id: pipelineId,
    status_id: statusId,
    price: Number(src.budget || 0),
    custom: { utm_source: src.utm_source || '', utm_medium: src.utm_medium || '', utm_campaign: src.utm_campaign || '', external_id: src.external_id || '' }
  },
  note: String(src.comment ?? '').slice(0, 2000)
}}];
Как не получить webhook loop

Не обрабатывайте все события подряд. Фильтруйте только нужные изменения, храните idempotency key по entity_id + event_type + updated_at и не реагируйте на собственные технические теги.

Готовый workflow JSON: скачать и импортировать

Скачать готовый workflow JSON Скачать тестовый payload

{
  "name": "Nodbot - amoCRM integration blueprint with contact lead upsert",
  "nodes": [
    {
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять заявку или amoCRM webhook"
    },
    {
      "name": "Normalize amoCRM payload",
      "type": "n8n-nodes-base.code",
      "purpose": "Собрать contact, lead, note и dedupe key"
    },
    {
      "name": "Find contact and open lead",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Искать контакт/сделку до создания"
    },
    {
      "name": "Create or update amoCRM",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Записать contact+lead и custom fields"
    },
    {
      "name": "Webhook loop guard",
      "type": "n8n-nodes-base.code",
      "purpose": "Отсечь повторные события"
    },
    {
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть безопасный ответ"
    }
  ],
  "connections": "Webhook input → Normalize amoCRM payload → Find contact and open lead → Create or update amoCRM → Webhook loop guard → Respond"
}

Пошаговая настройка amoCRM OAuth, pipeline и n8n

  1. Создайте OAuth-интеграцию amoCRM и сохраните subdomain, client_id, client_secret и refresh token в credentials.
  2. Заведите custom fields для UTM, external_id и source, а не храните их в примечании.
  3. Импортируйте workflow JSON и задайте pipeline_id/status_id через ENV или параметры.
  4. Настройте поиск контакта по телефону/email и открытую сделку в нужной воронке.
  5. Добавьте webhook guard для событий amoCRM, чтобы workflow не реагировал на собственные изменения.

Тесты перед production

curl -X POST "https://YOUR-N8N-DOMAIN/webhook/integration-amocrm-n8n" \
  -H "Content-Type: application/json" \
  --data @integration-amocrm-n8n-payload.json
  1. Повторите один payload дважды и проверьте, что не появилась вторая открытая сделка.
  2. Измените UTM при том же телефоне и проверьте, какое поле обновляется.
  3. Смоделируйте истёкший OAuth и убедитесь, что alert понятен.
  4. Отправьте webhook изменения сделки и проверьте, что нет бесконечного цикла.
  5. Проверьте, что notes не содержат токены и лишние персональные данные.

Production-риски

  • OAuth не обновляется. Workflow работает в тесте, но падает через несколько дней; нужен runbook обновления токена.
  • Поиск только по контакту. У клиента может быть открытая сделка без обновлённого contact; проверяйте бизнес-правило.
  • Смешаны воронки. Тестовые заявки попадают в production pipeline.
  • Webhook loop. Изменение карточки из n8n снова вызывает входящее событие.
  • UTM в note. Маркетинг теряет аналитику по каналам.
Карточка amoCRM со сделкой, контактом, UTM и idempotency guard
Пример результата: контакт и сделка связаны, UTM в полях, webhook guard исключает повторную обработку.

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

  1. Повторный лид обновляет существующую карточку или создаёт новую по явному правилу.
  2. OAuth credentials хранятся безопасно, есть инструкция обновления.
  3. UTM, source и external_id записаны в отдельные поля.
  4. Webhook события имеют idempotency и не создают цикл.
  5. Ошибки API уходят в alert или DLQ с ссылкой на execution.
Нужна amoCRM-интеграция без дублей и webhook loop?

Nodbot спроектирует n8n-слой под вашу воронку: OAuth, поля, дедупликация, webhooks, alerts и тесты.

Обсудить интеграцию amoCRM