Зачем нужны кастомные ноды?
Стандартный набор 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.







