amoCRM и n8n: интеграция форм, сделок и webhook без дублей ¶
Обновлено: 2026-05-30
Используйте JSON как основу: замените credentials, URL порталов, поля CRM и правила дедупликации.
Проблема: amoCRM легко подключить к форме, но сложнее сделать так, чтобы повторный лид не создавал вторую сделку, OAuth не падал в production, webhook не зацикливал workflow, а менеджер видел правильный pipeline и источник заявки.
Решение: выносить бизнес-логику в n8n: единый payload, нормализация phone/email, поиск контакта и открытой сделки, контролируемый create/update, отдельные поля для UTM, retry на API и журнал idempotency для webhook-событий.
Проблема: почему связка 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 fields | phone +7, email lowercase, pipeline_id |
| Find contact/deal | ищет существующую карточку | открытые сделки, контакт по телефону/email |
| Upsert amoCRM | создаёт или обновляет contact+lead | custom_fields_values, tags, responsible_user_id |
| Webhook guard | фильтрует исходящие события amoCRM | event 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 ¶
- Создайте OAuth-интеграцию amoCRM и сохраните subdomain, client_id, client_secret и refresh token в credentials.
- Заведите custom fields для UTM, external_id и source, а не храните их в примечании.
- Импортируйте workflow JSON и задайте pipeline_id/status_id через ENV или параметры.
- Настройте поиск контакта по телефону/email и открытую сделку в нужной воронке.
- Добавьте 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
- Повторите один payload дважды и проверьте, что не появилась вторая открытая сделка.
- Измените UTM при том же телефоне и проверьте, какое поле обновляется.
- Смоделируйте истёкший OAuth и убедитесь, что alert понятен.
- Отправьте webhook изменения сделки и проверьте, что нет бесконечного цикла.
- Проверьте, что notes не содержат токены и лишние персональные данные.
Production-риски ¶
- OAuth не обновляется. Workflow работает в тесте, но падает через несколько дней; нужен runbook обновления токена.
- Поиск только по контакту. У клиента может быть открытая сделка без обновлённого contact; проверяйте бизнес-правило.
- Смешаны воронки. Тестовые заявки попадают в production pipeline.
- Webhook loop. Изменение карточки из n8n снова вызывает входящее событие.
- UTM в note. Маркетинг теряет аналитику по каналам.
Полезные ссылки и смежные материалы ¶
- amoCRM API Reference
- amoCRM Webhooks
- Workflow Tilda → amoCRM
- Дедупликация amoCRM webhook через Postgres
Критерии готовности ¶
- Повторный лид обновляет существующую карточку или создаёт новую по явному правилу.
- OAuth credentials хранятся безопасно, есть инструкция обновления.
- UTM, source и external_id записаны в отдельные поля.
- Webhook события имеют idempotency и не создают цикл.
- Ошибки API уходят в alert или DLQ с ссылкой на execution.
Nodbot спроектирует n8n-слой под вашу воронку: OAuth, поля, дедупликация, webhooks, alerts и тесты.
Обсудить интеграцию amoCRM