Зачем нужны кастомные ноды?
Стандартный набор n8n включает HTTP Request, Function, Webhook и другие. Однако при интеграции с современными API часто возникают задачи, которые сложно решить встроенными средствами: сложная пагинация, retry с экспоненциальной задержкой, поддержка нескольких версий API, встроенный OAuth2 с refresh-токенами. Кастомная нода — это TypeScript-пакет, который регистрируется в n8n и работает как нативная. Она даёт полный контроль над логикой и переиспользуется в любом workflow.
Возьмём реальный кейс: интеграция с CRM с rate limit 100 запросов/мин и необходимостью обработки ошибок 429 и 500. В кастомной ноде мы реализовали очередь запросов с задержкой, retry с backoff и собственный мониторинг. Результат — стабильная синхронизация десятков тысяч контактов без ручного вмешательства. Наш опыт — более 20 интеграций для CRM, платёжных систем и пагинированных API. Работаем с актуальными версиями n8n и TypeScript.
«Custom nodes are TypeScript packages that extend n8n’s functionality» — n8n docs
Как мы разрабатываем кастомные ноды?
Разработка начинается с анализа документации API: определяем ресурсы, операции, лимиты. Затем проектируем схему credentials, структуру ноды и параметры. Реализация на TypeScript с учётом всех сценариев, включая обработку ошибок. После — тестирование с моками и интеграционные тесты. Финальный этап — упаковка и поставка через npm registry или архив.
Типовая структура проекта
my-n8n-nodes/ ├── nodes/ │ └── MyService/ │ ├── MyService.node.ts │ ├── MyService.node.json │ └── myservice.svg ├── credentials/ │ └── MyServiceApi.credentials.ts ├── package.json └── tsconfig.json Credentials и основная нода
package.json:
{ "name": "n8n-nodes-myservice", "version": "1.0.0", "description": "n8n nodes for MyService API", "main": "index.js", "n8n": { "n8nNodesApiVersion": 1, "credentials": ["dist/credentials/MyServiceApi.credentials.js"], "nodes": ["dist/nodes/MyService/MyService.node.js"] }, "devDependencies": { "n8n-workflow": "*", "typescript": "^5.0.0" } } Credentials:
// credentials/MyServiceApi.credentials.ts import { ICredentialType, INodeProperties } from 'n8n-workflow'; export class MyServiceApi implements ICredentialType { name = 'myServiceApi'; displayName = 'MyService API'; documentationUrl = 'https://docs.myservice.com/api'; properties: INodeProperties[] = [ { displayName: 'API Key', name: 'apiKey', type: 'string', typeOptions: { password: true }, default: '', }, { displayName: 'Base URL', name: 'baseUrl', type: 'string', default: 'https://api.myservice.com/v1', }, ]; } Основная нода:
// nodes/MyService/MyService.node.ts import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, NodeApiError, } from 'n8n-workflow'; export class MyService implements INodeType { description: INodeTypeDescription = { displayName: 'MyService', name: 'myService', icon: 'file:myservice.svg', group: ['transform'], version: 1, description: 'Interact with MyService API', defaults: { name: 'MyService' }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'myServiceApi', required: true } ], properties: [ { displayName: 'Resource', name: 'resource', type: 'options', options: [ { name: 'Contact', value: 'contact' }, { name: 'Deal', value: 'deal' }, ], default: 'contact', }, { displayName: 'Operation', name: 'operation', type: 'options', displayOptions: { show: { resource: ['contact'] } }, options: [ { name: 'Create', value: 'create', action: 'Create a contact' }, { name: 'Get', value: 'get', action: 'Get a contact' }, { name: 'Update', value: 'update', action: 'Update a contact' }, ], default: 'create', }, { displayName: 'Email', name: 'email', type: 'string', displayOptions: { show: { resource: ['contact'], operation: ['create'] } }, default: '', required: true, }, ], }; async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { const items = this.getInputData(); const returnData: INodeExecutionData[] = []; const credentials = await this.getCredentials('myServiceApi'); const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; for (let i = 0; i < items.length; i++) { try { let responseData: unknown; if (resource === 'contact' && operation === 'create') { const email = this.getNodeParameter('email', i) as string; responseData = await this.helpers.request({ method: 'POST', url: `${credentials.baseUrl}/contacts`, headers: { 'Authorization': `Bearer ${credentials.apiKey}`, 'Content-Type': 'application/json', }, body: { email }, json: true, }); } returnData.push({ json: responseData as object }); } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message }, pairedItem: i }); continue; } throw new NodeApiError(this.getNode(), error); } } return [returnData]; } } Как установить кастомную ноду в n8n?
Установка осуществляется через npm: npm install /path/to/my-n8n-nodes или из публичного registry. При использовании Docker монтируйте директорию с нодами через volume и укажите переменную окружения N8N_CUSTOM_EXTENSIONS. После установки нода появляется в редакторе и готова к использованию.
Кастомная нода против цепочки HTTP + Function: что выбрать?
| Характеристика | Кастомная нода | Цепочка HTTP + Function |
|---|---|---|
| Обработка ошибок | Встроенная, с кастомной логикой | Требует дополнительных нод |
| Пагинация | Автоматическая, без настройки | Ручная реализация c циклами |
| Производительность | В 10-50 раз быстрее | Снижается на больших объёмах |
| Повторное использование | Один раз разработал — используй во всех workflow | Копируй блоки каждый раз |
| Сопровождение | Единая кодовая база | Фрагменты разбросаны |
Типы credentials для кастомных нод
Кастомные ноды позволяют реализовать любые типы авторизации: API Key, OAuth2, Basic Auth, Bearer Token, Session Cookie. Для OAuth2 поддерживается автоматическое обновление refresh-токенов. В credentials можно добавить кастомную проверку и документацию.
| Тип credentials | Сложность реализации | Пример использования |
|---|---|---|
| API Key | Низкая | Внешние REST API |
| OAuth2 | Средняя | Google, Facebook, GitHub |
| Basic Auth | Низкая | Корпоративные системы |
| Session Cookie | Высокая | CMS без REST API |
Объём работ и сроки
В услугу входит: исходный код ноды (TypeScript) с комментариями, credentials-класс, инструкция по установке (npm/docker), документация по использованию и тестовое покрытие (модульные + интеграционные тесты). Также предоставляем консультацию по интеграции с существующими workflow.
Сроки: простая нода с 2–3 операциями и credentials — 2–4 дня. Сложная нода с polling trigger, пагинацией, binary data — 1–2 недели. Стоимость рассчитывается индивидуально после анализа вашего API. Инвестиция в кастомную ноду окупается за счёт автоматизации. Свяжитесь с нами для оценки — пришлём смету в течение дня. Закажите разработку, и ваша интеграция перестанет требовать ручного вмешательства.
Почему стоит инвестировать в кастомную ноду?
Кастомная нода — это не просто удобство, это снижение operational overhead. Вместо десятков одинаковых workflow вы получаете единую, протестированную интеграцию. Мы гарантируем стабильную работу и предоставляем поддержку. Наши инженеры имеют опыт работы с самыми разными API — от платёжных до CRM. Получите консультацию инженера — напишите нам.
Как происходит тестирование кастомных нод?
Мы проводим модульное и интеграционное тестирование. Внедряем моки для HTTP-запросов, тестируем граничные случаи и обработку ошибок. Это гарантирует стабильную работу в боевых сценариях. Типичное покрытие — около 80% строк кода.
Типичные ошибки при разработке custom nodes
- Неправильная типизация параметров displayOptions
- Отсутствие обработки ошибок для каждого вызова API
- Неправильное использование credentials в execute
- Игнорирование rate limit и пагинации
- Отсутствие тестов
Подробнее о создании custom nodes читайте в официальной документации n8n.







