Следуйте этим рекомендациям для построения надёжной и эффективной интеграции.
Выбор режима запроса
| Режим | Лучше для | Плюсы | Минусы |
|---|
| Async (Polling) | Клиентские приложения, простые скрипты | Легко реализовать | Нужна логика polling |
| Callback (Webhooks) | Продакшен-серверы | Real-time, без polling | Нужен публичный эндпоинт |
Используйте режим async при разработке, переключайтесь на callback для продакшена.
Стратегия polling
Для режима async реализуйте умный polling, чтобы балансировать отзывчивость и эффективность.
Рекомендуемые интервалы
| Тип модели | Начальная пауза | Интервал опроса | Макс. ожидание |
|---|
| Image (быстрая) | 5 с | 3 с | 2 мин |
| Image (качество) | 10 с | 5 с | 3 мин |
| Video | 60 с | 15 с | 10 мин |
| Audio | 30 с | 10 с | 5 мин |
Экспоненциальный backoff
async function pollWithBackoff(model, taskId, apiKey) {
let interval = 3000; // Start at 3s
const maxInterval = 30000; // Max 30s
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));
interval = Math.min(interval * 1.5, maxInterval);
}
throw new Error('Timeout');
}
Обработка ошибок
Всегда обрабатывайте сбои
const result = await pollForResult(taskId);
if (!result) {
// Handle null/undefined
}
// Check for specific error codes
if (result.state === 'failed') {
switch (result.failCode) {
case 'CONTENT_VIOLATION':
// Prompt needs modification
break;
case 'PROCESSING_TIMEOUT':
// Retry the request
break;
case 'INSUFFICIENT_CREDITS':
// Alert user to add credits
break;
}
}
Реализуйте повторы
async function generateWithRetry(params, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await generateImage(params);
} catch (error) {
if (attempt === maxRetries - 1) throw error;
// Only retry on transient errors
if (error.failCode === 'PROCESSING_TIMEOUT') {
await new Promise(r => setTimeout(r, 5000));
continue;
}
throw error; // Don't retry content violations etc.
}
}
}
Prompt Engineering
Советы по генерации изображений
| Рекомендуется | Не рекомендуется |
|---|
| Конкретно: «Щенок золотистого ретривера играет в осенних листьях» | Расплывчато: «Собака» |
| Указывать стиль: «акварель, мягкий свет» | Полагаться на значения по умолчанию |
| Состав: «крупный портрет, по центру» | Оставлять композицию на волю случая |
| Использовать позитивные описания | Негативы вроде «без фона» |
Эффективная структура prompt
[Объект] + [Действие/Поза] + [Окружение] + [Стиль] + [Технические детали]
Пример:
Молодая женщина читает книгу в уютном кафе,
тёплый дневной свет через окна,
импрессионистский масляный стиль,
мягкий фокус на фоне, освещение golden hour
Управление ресурсами
Скачивайте результаты вовремя
// Result URLs expire after 24 hours
const urls = await generateImage(prompt);
// Download immediately
for (const url of urls) {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
// Save to your storage
}
Сохраняйте ID задач
// Log task IDs for debugging
console.log(`Task submitted: ${taskId}`);
// Store in database for reference
await db.tasks.create({
taskId,
userId: user.id,
model,
prompt,
status: 'pending',
createdAt: new Date(),
});
Оптимизация стоимости
Выбор модели
| Использование | Рекомендуемая модель | Примечания |
|---|
| Прототипирование | Nano Banana | Быстрая итерация |
| Продакшен-качество | Flux-2 Pro | Баланс качества и контроля |
| Премиум-качество | Midjourney | Выразительный художественный стиль |
| Видео (короткие) | Wan 2.5 | Эффективная короткая генерация |
| Видео (кинематограф) | Sora 2 | Максимальное качество видео |
Актуальные цены — на странице Цены.
Группируйте похожие запросы
Для нескольких вариаций используйте режим image-to-image вместо генерации с нуля каждый раз.
Мониторьте использование
// Track costs per user/project
await db.usage.create({
userId: user.id,
model,
cost: MODEL_COSTS[model],
timestamp: new Date(),
});
// Set up alerts for unusual usage
if (dailyCost > threshold) {
sendAlert('High API usage detected');
}
Безопасность
Защита API-ключа
// DO: Use environment variables
const apiKey = process.env.APIXO_API_KEY;
// DON'T: Hardcode in source
const apiKey = 'sk-abc123'; // Never do this!
// DON'T: Expose in client-side code
// API calls should go through your backend
Валидация пользовательского ввода
function validatePrompt(prompt) {
if (!prompt || typeof prompt !== 'string') {
throw new Error('Invalid prompt');
}
if (prompt.length > 5000) {
throw new Error('Prompt too long');
}
// Sanitize before sending to API
return prompt.trim();
}
Производительность
Connection pooling
// Reuse HTTP connections
const agent = new https.Agent({ keepAlive: true });
const response = await fetch(url, {
agent,
// ...
});
Параллелизация
// Generate multiple images in parallel
const prompts = ['prompt1', 'prompt2', 'prompt3'];
const tasks = await Promise.all(
prompts.map(prompt => submitTask(prompt))
);
const results = await Promise.all(
tasks.map(task => pollForResult(task.taskId))
);
Мониторинг
Логирование вызовов API
const startTime = Date.now();
try {
const result = await generateImage(prompt);
logger.info('Generation successful', {
taskId: result.taskId,
duration: Date.now() - startTime,
model,
});
} catch (error) {
logger.error('Generation failed', {
error: error.message,
duration: Date.now() - startTime,
model,
});
}
Настройка алертов
Отслеживайте:
- Высокий процент ошибок
- Необычную задержку
- Резкие скачки стоимости
- Срабатывания лимитов