Навіщо потрібні кастомні ноди?
Стандартний набір 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 |
|---|---|---|
| Обробка помилок | Вбудована, з кастомною логікою | Вимагає додаткових нод |
| Пагінація | Автоматична, без налаштування | Ручна реалізація з циклами |
| Продуктивність | У 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.







