Поиск

Поиск навыков и категорий

Webhook интеграция

Webhooks — способ связи между Polydo и вашим n8n workflow через HTTP POST запросы.

Как это работает

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│  Пользователь │  POST   │   Polydo    │  POST   │ Ваш n8n     │
│  нажимает    │ ──────> │   сервер    │ ──────> │ webhook     │
│  "Запустить" │         │             │         │             │
└─────────────┘         └─────────────┘         └─────────────┘
                                                      │
                                                      │ Обработка
                                                      v
┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│  Пользователь │ <────── │   Polydo    │ <────── │ POST на     │
│  получает   │         │   сервер    │         │ callbackUrl │
│  результат  │         │             │         │             │
└─────────────┘         └─────────────┘         └─────────────┘

Формат входящего запроса

Когда пользователь запускает ваш навык, на webhook приходит POST запрос:

Headers

POST /your-webhook-path HTTP/1.1
Content-Type: application/json
X-Polydo-Signature: sha256=abc123...
X-Polydo-Execution-Id: exec_abc123

Body

{
  "executionId": "exec_abc123def456",
  "skillId": "skill_xyz789",
  "userId": "user_123",
  "inputData": {
    "text": "Пример входных данных от пользователя",
    "option": true
  },
  "callbackUrl": "https://api.polydo.ru/v1/executions/exec_abc123def456/callback",
  "metadata": {
    "timestamp": "2024-01-15T10:30:00Z",
    "version": "1.0"
  }
}

Описание полей

ПолеТипОписание
executionIdstringУникальный ID этого запуска
skillIdstringID вашего навыка
userIdstringID пользователя (анонимизирован)
inputDataobjectДанные, введённые пользователем
callbackUrlstringURL для отправки результата
metadata.timestampstringВремя запуска (ISO 8601)
metadata.versionstringВерсия API

Формат ответа

После обработки отправьте POST запрос на callbackUrl:

Успешный ответ

POST {callbackUrl} HTTP/1.1
Content-Type: application/json
{
  "success": true,
  "output": {
    "result": "Обработанный текст",
    "count": 42,
    "fileUrl": "https://storage.example.com/file.pdf"
  }
}

Ответ с ошибкой

{
  "success": false,
  "error": "Не удалось обработать файл: неподдерживаемый формат"
}

Описание полей ответа

ПолеТипОбязательноеОписание
successbooleanДаtrue если выполнено успешно
outputobjectПри success=trueРезультат выполнения
errorstringПри success=falseОписание ошибки

Настройка в n8n

Шаг 1: Webhook нода

// Настройки Webhook ноды в n8n
{
  "httpMethod": "POST",
  "path": "your-skill-name",
  "responseMode": "responseNode", // или "lastNode"
  "options": {}
}

Шаг 2: Обработка данных

// Code нода для извлечения данных
const body = $input.first().json.body;
const { executionId, inputData, callbackUrl } = body;

// Ваша логика обработки
const result = processData(inputData);

return [{
  json: {
    callbackUrl,
    executionId,
    result
  }
}];

Шаг 3: Отправка результата

// HTTP Request нода
{
  "method": "POST",
  "url": "={{ $json.callbackUrl }}",
  "headers": {
    "Content-Type": "application/json"
  },
  "body": {
    "success": true,
    "output": "={{ $json.result }}"
  }
}

Таймауты и повторные попытки

Таймауты

ЭтапТаймаут
Первичный ответ webhook30 секунд
Ожидание callback5 минут

Если webhook не отвечает в течение 30 секунд, запрос считается неудачным.

Повторные попытки

При ошибках сети Polydo автоматически повторяет запрос:

  • 1-я попытка: сразу
  • 2-я попытка: через 5 секунд
  • 3-я попытка: через 30 секунд

После 3 неудачных попыток выполнение помечается как failed, а пользователю возвращаются токены.

Безопасность

Проверка подписи

Каждый запрос содержит заголовок X-Polydo-Signature для верификации:

// Проверка подписи в n8n
const crypto = require('crypto');

const signature = $input.first().headers['x-polydo-signature'];
const body = JSON.stringify($input.first().json.body);
const secret = 'your_webhook_secret'; // из настроек навыка

const expectedSignature = 'sha256=' + crypto
  .createHmac('sha256', secret)
  .update(body)
  .digest('hex');

if (signature !== expectedSignature) {
  throw new Error('Invalid signature');
}

Рекомендации

  1. Всегда проверяйте подпись в production
  2. Используйте HTTPS для webhook URL
  3. Не логируйте чувствительные данные пользователей
  4. Валидируйте входные данные перед обработкой

Примеры

Простой текстовый процессор

// n8n Code нода
const { inputData, callbackUrl } = $input.first().json.body;
const text = inputData.text || '';

// Обработка
const words = text.split(/\s+/).filter(w => w).length;
const chars = text.length;

// Отправка результата
const response = await fetch(callbackUrl, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    success: true,
    output: { words, chars }
  })
});

return [{ json: { sent: true } }];

Обработка файлов

// n8n Code нода
const { inputData, callbackUrl } = $input.first().json.body;
const fileUrl = inputData.file;

try {
  // Скачиваем файл
  const fileResponse = await fetch(fileUrl);
  const fileBuffer = await fileResponse.arrayBuffer();

  // Обрабатываем (пример: получаем размер)
  const fileSize = fileBuffer.byteLength;

  // Отправляем результат
  await fetch(callbackUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      success: true,
      output: {
        fileSize,
        fileName: fileUrl.split('/').pop()
      }
    })
  });
} catch (error) {
  await fetch(callbackUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      success: false,
      error: error.message
    })
  });
}

return [{ json: { processed: true } }];

Асинхронная обработка с прогрессом

Для длительных операций можно отправлять промежуточные статусы:

const { executionId, callbackUrl } = $input.first().json.body;

// Отправка промежуточного статуса (опционально)
await fetch(callbackUrl, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    success: true,
    status: 'processing',
    progress: 50,
    message: 'Обрабатываем данные...'
  })
});

// ... длительная обработка ...

// Финальный результат
await fetch(callbackUrl, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    success: true,
    output: { /* результат */ }
  })
});

Отладка

Логирование в n8n

Используйте console.log для отладки:

console.log('Received:', JSON.stringify($input.first().json, null, 2));

Логи видны в истории выполнений n8n.

Тестирование webhook

Протестируйте webhook без Polydo:

curl -X POST https://your-n8n.cloud/webhook/your-path \
  -H "Content-Type: application/json" \
  -d '{
    "executionId": "test_123",
    "skillId": "skill_test",
    "userId": "user_test",
    "inputData": {"text": "Hello"},
    "callbackUrl": "https://webhook.site/your-id"
  }'

Используйте webhook.site для просмотра callback запросов.

Частые ошибки

ОшибкаПричинаРешение
TimeoutWebhook не отвечаетПроверьте, что workflow активен
Invalid callbackcallbackUrl не используетсяОтправляйте результат на callbackUrl
Parse errorНеверный формат JSONПроверьте формат ответа
Missing outputsuccess=true, но нет outputДобавьте поле output

Следующие шаги