Sigue estas recomendaciones para construir integraciones robustas y eficientes.
Elegir modo de solicitud
| Modo | Ideal para | Pros | Contras |
|---|
| Async (Polling) | Apps cliente, scripts simples | Fácil de implementar | Requiere lógica de polling |
| Callback (Webhooks) | Servidores de producción | Tiempo real, sin polling | Requiere endpoint público |
Comienza con modo async en desarrollo, cambia a callback para producción.
Estrategia de polling
Para modo async, implementa polling inteligente para equilibrar capacidad de respuesta y eficiencia.
Intervalos recomendados
| Tipo de modelo | Espera inicial | Intervalo de polling | Espera máxima |
|---|
| Imagen (rápido) | 5s | 3s | 2 min |
| Imagen (calidad) | 10s | 5s | 3 min |
| Video | 60s | 15s | 10 min |
| Audio | 30s | 10s | 5 min |
Backoff exponencial
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');
}
Manejo de errores
Siempre gestiona los fallos
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;
}
}
Implementa reintentos
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.
}
}
}
Ingeniería de prompts
Consejos para generación de imágenes
| Haz | No hagas |
|---|
| Sé específico: “Un cachorro golden retriever jugando en hojas otoñales” | Sé vago: “Un perro” |
| Incluye estilo: “pintura acuarela, iluminación suave” | Da por hecho los valores por defecto |
| Especifica composición: “retrato primer plano, centrado” | Deja la composición al azar |
| Usa descripciones positivas | Usa negativos como “sin fondo” |
Estructura efectiva del prompt
[Sujeto] + [Acción/Pose] + [Entorno] + [Estilo] + [Detalles técnicos]
Ejemplo:
Una joven leyendo un libro en una acogedora cafetería,
luz cálida de tarde a través de ventanas,
estilo pintura al óleo impresionista,
fondo con enfoque suave, iluminación hora dorada
Gestión de recursos
Descarga los resultados con prontitud
// 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
}
Almacena los IDs de tarea
// 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(),
});
Optimización de costes
Elige el modelo adecuado
| Caso de uso | Modelo recomendado | Notas |
|---|
| Prototipado | Nano Banana | Iteración rápida para feedback |
| Calidad producción | Flux-2 Pro | Fidelidad y control equilibrados |
| Calidad premium | Midjourney | Estilo artístico potente |
| Video (corto) | Wan 2.5 | Generación corta eficiente |
| Video (cinematográfico) | Sora 2 | Mayor calidad de video |
Para precios actuales, consulta siempre la página de Precios.
Agrupa solicitudes similares
Si generas múltiples variaciones, usa modo image-to-image en lugar de generar desde cero cada vez.
Monitorea el uso
// 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');
}
Seguridad
Protege tu clave 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
Valida la entrada del usuario
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();
}
Rendimiento
Usa conexiones reutilizables
// Reuse HTTP connections
const agent = new https.Agent({ keepAlive: true });
const response = await fetch(url, {
agent,
// ...
});
Paraleliza cuando sea posible
// 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))
);
Monitoreo
Registra las llamadas a la 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,
});
}
Configura alertas
Monitoriza:
- Tasa de errores alta
- Latencia inusual
- Picos de costo
- Impactos en el límite de tasa