Перейти к основному содержанию
APIXO предлагает два способа получения результатов: polling (режим async) и webhooks (режим callback). Это руководство поможет выбрать подходящий подход и внедрить его.

Краткое сравнение

AspectPolling (Async)Webhooks (Callback)
SetupПростойТребуется публичный эндпоинт
Real-timeПочти в реальном времениМгновенно
API CallsНесколько на задачуОдин на задачу
Best ForРазработка, клиентские приложенияProduction-серверы
InfrastructureНе требуетсяHTTPS-эндпоинт

Когда использовать Polling

Выбирайте polling, когда:
  • Создаёте клиентское приложение
  • Прототипируете или тестируете
  • Нет публичного сервера
  • Обрабатываете небольшой объём задач

Базовая реализация polling

async function pollForResult(model, taskId, apiKey) {
  const interval = 3000; // 3 seconds
  const maxAttempts = 60;
  
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `https://api.apixo.ai/api/v1/statusTask/${model}?taskId=${taskId}`,
      { headers: { 'Authorization': `Bearer ${apiKey}` } }
    );
    
    const { data } = await response.json();
    
    if (data.state === 'success') {
      return JSON.parse(data.resultJson).resultUrls;
    }
    if (data.state === 'failed') {
      throw new Error(data.failMsg);
    }
    
    await new Promise(r => setTimeout(r, interval));
  }
  
  throw new Error('Timeout');
}

Экспоненциальная задержка

Для большей эффективности используйте экспоненциальную задержку:
async function pollWithBackoff(model, taskId, apiKey) {
  let interval = 3000; // Start at 3s
  const maxInterval = 30000; // Max 30s
  const maxTime = 300000; // 5 min timeout
  let elapsed = 0;
  
  while (elapsed < maxTime) {
    const response = await fetch(
      `https://api.apixo.ai/api/v1/statusTask/${model}?taskId=${taskId}`,
      { headers: { 'Authorization': `Bearer ${apiKey}` } }
    );
    
    const { data } = await response.json();
    
    if (data.state === 'success') {
      return JSON.parse(data.resultJson).resultUrls;
    }
    if (data.state === 'failed') {
      throw new Error(data.failMsg);
    }
    
    await new Promise(r => setTimeout(r, interval));
    elapsed += interval;
    interval = Math.min(interval * 1.5, maxInterval);
  }
  
  throw new Error('Timeout');
}

Рекомендуемые интервалы по типу модели

Model TypeInitial WaitPoll IntervalMax Wait
Image (fast)5s3s2 min
Image (quality)10s5s3 min
Video60s15s10 min
Audio30s10s5 min

Когда использовать Webhooks

Выбирайте webhooks, когда:
  • Есть production-сервер
  • Обрабатываете большой объём задач
  • Нужны уведомления в реальном времени
  • Важно минимизировать количество API-вызовов

Настройка Webhook

1. Создайте эндпоинт:
const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook/apixo', (req, res) => {
  const { taskId, state, resultJson, failCode, failMsg } = req.body.data;
  
  if (state === 'success') {
    const urls = JSON.parse(resultJson).resultUrls;
    console.log('Generated:', urls);
    // Process your images/videos
  } else if (state === 'failed') {
    console.error(`Task ${taskId} failed: ${failCode}`);
  }
  
  res.status(200).send('OK');
});

app.listen(3000);
2. Отправьте задачу с callback:
const response = await fetch('https://api.apixo.ai/api/v1/generateTask/nano-banana', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    request_type: 'callback',
    callback_url: 'https://your-domain.com/webhook/apixo',
    input: {
      mode: 'text-to-image',
      prompt: 'A beautiful landscape',
    },
  }),
});

Требования к webhook

  • Должен быть публично доступен по HTTPS
  • Должен отвечать HTTP 200 в течение 30 секунд
  • Должен обрабатывать повторные доставки (используйте taskId для идемпотентности)

Retry Policy

При сбое webhook:
AttemptDelay
1st retry30 seconds
2nd retry2 minutes
3rd retry10 minutes
После 3 неудачных попыток webhook отменяется. Статус можно проверить через status endpoint.

Гибридный подход

Для максимальной надёжности можно сочетать оба подхода:
class TaskManager {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.pendingTasks = new Map();
  }
  
  async submit(model, input, callbackUrl = null) {
    const response = await fetch(
      `https://api.apixo.ai/api/v1/generateTask/${model}`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          request_type: callbackUrl ? 'callback' : 'async',
          callback_url: callbackUrl,
          input,
        }),
      }
    );
    
    const { data } = await response.json();
    
    if (!callbackUrl) {
      // Fallback to polling if no webhook
      return this.poll(model, data.taskId);
    }
    
    // Track task for webhook
    this.pendingTasks.set(data.taskId, { model, status: 'pending' });
    return data.taskId;
  }
  
  handleWebhook(body) {
    const { taskId, state, resultJson, failMsg } = body.data;
    
    if (state === 'success') {
      this.pendingTasks.delete(taskId);
      return JSON.parse(resultJson).resultUrls;
    }
    
    if (state === 'failed') {
      this.pendingTasks.delete(taskId);
      throw new Error(failMsg);
    }
  }
  
  async poll(model, taskId) {
    // Fallback polling implementation
    return pollWithBackoff(model, taskId, this.apiKey);
  }
}

Локальная разработка с ngrok

Для тестирования webhooks локально:
# Install ngrok
npm install -g ngrok

# Start your local server
node server.js  # runs on port 3000

# Tunnel to local server
ngrok http 3000
# Returns: https://abc123.ngrok.io

# Use ngrok URL as callback_url

Итог

ScenarioRecommendation
Development / TestingPolling
Client-side appPolling
Production backendWebhooks
High volumeWebhooks
Maximum reliabilityHybrid (webhooks + polling fallback)
Начните с polling для простоты, затем переходите на webhooks по мере роста приложения.