Przejdź do głównej treści
APIXO oferuje dwa sposoby odbierania wyników zadań: polling (tryb async) i webhooks (tryb callback). Ten przewodnik pomaga wybrać właściwe podejście i wdrożyć je efektywnie.

Szybkie porównanie

AspektPolling (Async)Webhooks (Callback)
KonfiguracjaProstaWymaga publicznego endpointu
Real-timeBliskie real-timeNatychmiastowe
Wywołania APIWiele na zadanieJedno na zadanie
Najlepsze dlaRozwój, aplikacje klienckieSerwery produkcyjne
InfrastrukturaBrakEndpoint HTTPS

Kiedy używać pollingu

Wybierz polling gdy:
  • Budujesz aplikacje po stronie klienta
  • Prototypujesz lub testujesz
  • Nie masz publicznego serwera
  • Przetwarzasz mały wolumen zadań

Podstawowa implementacja pollingu

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');
}

Exponential backoff

Dla lepszej wydajności użyj exponential backoff:
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');
}

Zalecane odstępy według typu modelu

Typ modeluPoczątkowe oczekiwanieOdstęp pollinguMaks. oczekiwanie
Obraz (szybki)5s3s2 min
Obraz (jakość)10s5s3 min
Wideo60s15s10 min
Audio30s10s5 min

Kiedy używać webhooków

Wybierz webhooki gdy:
  • Prowadzisz serwer produkcyjny
  • Przetwarzasz duży wolumen zadań
  • Potrzebujesz powiadomień w czasie rzeczywistym
  • Chcesz zminimalizować wywołania API

Konfiguracja webhooka

1. Utwórz endpoint:
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. Zgłoś zadanie z callbackiem:
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',
    },
  }),
});

Wymagania webhooka

  • Musi być publicznie dostępny przez HTTPS
  • Musi odpowiadać HTTP 200 w ciągu 30 sekund
  • Powinien obsługiwać duplikaty dostaw (użyj taskId dla idempotencji)

Polityka ponowień

Jeśli webhook się nie powiedzie:
PróbaOpóźnienie
1. ponowienie30 sekund
2. ponowienie2 minuty
3. ponowienie10 minut
Po 3 nieudanych próbach webhook jest porzucany. Nadal możesz sprawdzić status przez endpoint statusu.

Podejście hybrydowe

Dla maksymalnej niezawodności połącz oba podejścia:
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);
  }
}

Lokalny rozwój z ngrok

Do testowania webhooków lokalnie:
# 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

Podsumowanie

ScenariuszRekomendacja
Rozwój / TestowaniePolling
Aplikacja klienckaPolling
Backend produkcyjnyWebhooks
Duży ruchWebhooks
Maksymalna niezawodnośćHybrydowe (webhooks + polling jako zapasowy)
Zacznij od pollingu dla prostoty, potem przejdź na webhooki wraz ze skalowaniem aplikacji.