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

Интеграция МойСклад и n8n: товары, остатки и заказы без дублей

Проблема: МойСклад становится источником товаров, остатков и заказов, но простая синхронизация по расписанию быстро создаёт дубли контрагентов, скачущие остатки и конфликт между интернет-магазином, маркетплейсом и складом.

Решение: Решение — строить integration layer в n8n: нормализовать SKU и контрагентов, использовать внешний ключ заказа, проверять idempotency, обновлять только изменившиеся остатки и вести audit-log каждого write-действия в МойСклад.

Материал закрывает практический интент: интеграция МойСклад и n8n, JSON API МойСклад, синхронизация остатков, автоматизация склада, заказы без дублей, idempotency key. Внутри есть импортируемый workflow JSON, тестовый payload, Code Node, таблица архитектуры, Schema.org HowTo, LLM-разметка, визуальная схема и production-чеклист.

Готовые файлы для запуска:
Скачать workflow JSON Скачать test payload
Схема интеграции Интеграция МойСклад и n8n: товары, остатки и заказы без дублей в n8n
Схема показывает production-цепочку: приём события, нормализация, идемпотентность, вызов API и аудит результата.

Проблема и решение: почему простой webhook ломает учёт

В n8n легко собрать happy path: принять webhook, сделать HTTP Request и получить зелёный execution. Но backoffice-интеграции ломаются не на первом успешном запросе, а на повторной доставке, неполном payload, изменении схемы API, ручной правке в учётной системе и частичном сбое после write-операции.

Поэтому эта страница описывает не абстрактную связку сервисов, а готовую production-модель. Сначала фиксируется контракт данных, затем проверяются ключи, потом включается idempotency, и только после этого workflow меняет заказ, остаток, цену или документ. Такой подход снижает количество дублей, делает replay безопасным и помогает поддержке объяснить каждое изменение.

Архитектура workflow для интеграции

НодаРольЧто проверить
Webhook / ScheduleПринимает событие заказа или запускает сверку остатковevent_id, период, источник данных
Normalize order and SKUПриводит SKU, телефон, ИНН и суммы к стабильному видуSKU не пустой, qty > 0, сумма совпадает
Check idempotencyИщет обработанный external_order_id или event_idPostgres unique key или custom field
MoySklad API requestСоздаёт/обновляет заказ, контрагента или остатокJSON API 1.2, auth, timeout, retry
Audit and alertПишет результат и отправляет ошибки владельцуpayload_hash, status, href, reviewer
Почему не стоит начинать с “синхронизировать всё”

У каждой системы есть зоны ответственности. Сначала автоматизируйте один поток: заказ, остаток, цена или уведомление. После стабильных тестов добавляйте второй поток и общую сверку. Иначе ошибки разных процессов смешаются в одном execution.

Контракт входных данных

Контракт нужен для тестов, replay и передачи задачи между разработчиком, интегратором и владельцем процесса. Не завязывайтесь на текстовое название товара или клиента: используйте стабильные внешние ID, артикулы, event_id, timestamp и idempotency key.

{
  "event_id": "ms-order-10492-updated",
  "event_type": "customerorder.updated",
  "source": "moysklad",
  "external_order_id": "shop-10492",
  "moysklad_href": "https://api.moysklad.ru/api/remap/1.2/entity/customerorder/uuid",
  "customer": {
    "name": "ООО Ромашка",
    "inn": "7700000000",
    "phone": "+7 916 123-45-67"
  },
  "items": [
    {
      "sku": "SKU-001",
      "qty": 2,
      "price": 1490
    },
    {
      "sku": "SKU-002",
      "qty": 1,
      "price": 3900
    }
  ],
  "warehouse": "main-msk",
  "payment_status": "paid",
  "updated_at": "2026-05-30T10:00:00+03:00"
}

Нормализация и проверка данных в Code Node

Code Node ниже не заменяет всю бизнес-логику, но задаёт безопасный вход: выбрасывает пустые обязательные поля, приводит идентификаторы к единому виду и формирует ключ идемпотентности. В production этот блок лучше покрыть отдельными тестовыми payload.

const src = $json.body ?? $json;
const orderId = String(src.external_order_id ?? src.id ?? '').trim();
if (!orderId) throw new Error('No external_order_id for MoySklad sync');
const items = Array.isArray(src.items) ? src.items : [];
if (!items.length) throw new Error(`Order ${orderId} has no items`);
const normalizedItems = items.map((item) => ({
  sku: String(item.sku ?? item.article ?? '').trim().toUpperCase(),
  quantity: Number(item.qty ?? item.quantity ?? 0),
  price: Number(item.price ?? 0)
}));
for (const item of normalizedItems) {
  if (!item.sku || item.quantity <= 0) throw new Error(`Invalid item in ${orderId}`);
}
return [{ json: {
  idempotency_key: `moysklad:customerorder:${orderId}`,
  external_order_id: orderId,
  customer_phone: String(src.customer?.phone ?? '').replace(/[^0-9+]/g, ''),
  customer_inn: String(src.customer?.inn ?? '').replace(/\D/g, ''),
  items: normalizedItems,
  warehouse: src.warehouse ?? 'main',
  operation: 'upsert_customer_order',
  audit: { event_id: src.event_id, received_at: new Date().toISOString() }
}}];

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

Файл /assets/workflows/integration-moysklad-n8n-stock-order-sync.json можно импортировать в n8n как основу. После импорта замените credentials, endpoint, ID склада/магазина/инфобазы и правила mapping под ваш контур.

{
  "name": "Nodbot - MoySklad stock and order sync with idempotency",
  "nodes": [
    {
      "name": "Webhook / Schedule",
      "purpose": "Принимает событие заказа или запускает сверку остатков"
    },
    {
      "name": "Normalize order and SKU",
      "purpose": "Приводит SKU, телефон, ИНН и суммы к стабильному виду"
    },
    {
      "name": "Check idempotency",
      "purpose": "Ищет обработанный external_order_id или event_id"
    },
    {
      "name": "MoySklad API request",
      "purpose": "Создаёт/обновляет заказ, контрагента или остаток"
    },
    {
      "name": "Audit and alert",
      "purpose": "Пишет результат и отправляет ошибки владельцу"
    }
  ],
  "connections": "Webhook → Normalize → Idempotency → API Request → Audit/Respond"
}

Пошаговая настройка

  1. Создайте технического пользователя МойСклад с минимальными правами на заказы, товары и остатки.
  2. Опишите source of truth: кто главный по SKU, остаткам, ценам и статусам заказа.
  3. Импортируйте workflow JSON, замените credential и URL JSON API МойСклад.
  4. Запустите тестовый payload дважды и убедитесь, что второй запуск не создаёт дубль заказа.
  5. Включите audit-log, alert на 401/403/429/5xx и ручную очередь для неизвестных SKU.
Что проверить после импорта workflow

Откройте каждую ноду, замените credentials, включите dry-run там, где есть write-действия, и выполните тест на отдельной сущности. Не запускайте массовую синхронизацию до проверки дублей, лимитов API и rollback-плана.

Тесты перед production

Минимальный smoke test:

curl -X POST "https://YOUR-N8N-DOMAIN/webhook/moysklad-stock-order-sync" \
  -H "Content-Type: application/json" \
  --data @integration-moysklad-n8n-stock-order-sync-payload.json
  1. повторный заказ с тем же external_order_id
  2. неизвестный SKU
  3. отрицательный или нулевой остаток
  4. изменение цены больше допустимого процента
  5. ошибка API МойСклад 401/403/429
  6. частичный сбой после создания контрагента

Отдельно проверьте, что retry n8n не создаёт повторную запись. Для критичных действий используйте durable storage: Postgres, custom field, audit table или другой слой с уникальным ключом.

Production-риски

  • Двусторонняя синхронизация без source of truth заставляет остатки “прыгать”.
  • Дедупликация по названию клиента создаёт дубли контрагентов при каждом новом написании.
  • Массовое обновление остатков без diff перегружает API и усложняет расследование.
  • Секреты JSON API попадают в публичный workflow или execution data.
  • Нет ручной очереди для неизвестных SKU, поэтому workflow списывает не тот товар.
Карточка результата Интеграция МойСклад и n8n: товары, остатки и заказы без дублей: idempotency, status, audit и replay
Визуальный блок результата показывает, какие поля должны появиться после успешного запуска: статус, ключ идемпотентности, audit и ссылка на replay.

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

  1. Повторный external_order_id не создаёт второй заказ.
  2. Каждый SKU сопоставлен с кодом номенклатуры или отправлен в review.
  3. Остатки обновляются через diff и имеют safety stock.
  4. Ошибки API попадают в alert или DLQ с понятным сообщением.
  5. Есть владелец workflow, audit-log и инструкция replay.
Нужно внедрить без риска? Nodbot может собрать production workflow под вашу инфраструктуру: credentials, mapping, idempotency, retry/DLQ, мониторинг, LLM-разметка и понятный runbook для команды.