Follow these recommendations to build robust, efficient integrations.
Choosing Request Mode
| Mode | Best For | Pros | Cons |
|---|
| Async (Polling) | Client apps, simple scripts | Easy to implement | Requires polling logic |
| Callback (Webhooks) | Production servers | Real-time, no polling | Requires public endpoint |
Start with async mode for development, switch to callback for production.
Polling Strategy
For async mode, implement smart polling to balance responsiveness and efficiency.
Recommended Intervals
| Model Type | Initial Wait | Poll Interval | Max Wait |
|---|
| Image (fast) | 5s | 3s | 2 min |
| Image (quality) | 10s | 5s | 3 min |
| Video | 60s | 15s | 10 min |
| Audio | 30s | 10s | 5 min |
Exponential 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');
}
Error Handling
Always Handle Failures
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;
}
}
Implement Retries
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
Image Generation Tips
| Do | Don’t |
|---|
| Be specific: “A golden retriever puppy playing in autumn leaves” | Be vague: “A dog” |
| Include style: “watercolor painting, soft lighting” | Assume defaults |
| Specify composition: “close-up portrait, centered” | Leave composition to chance |
| Use positive descriptions | Use negatives like “no background” |
Effective Prompt Structure
[Subject] + [Action/Pose] + [Environment] + [Style] + [Technical details]
Example:
A young woman reading a book in a cozy cafe,
warm afternoon sunlight through windows,
impressionist oil painting style,
soft focus background, golden hour lighting
Resource Management
Download Results Promptly
// 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
}
Store Task IDs
// 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(),
});
Cost Optimization
Choose the Right Model
| Use Case | Recommended Model | Notes |
|---|
| Prototyping | Nano Banana | Fast iteration for quick feedback |
| Production quality | Flux-2 Pro | Balanced fidelity and control |
| Premium quality | Midjourney | Strong artistic style |
| Video (short) | Wan 2.5 | Efficient short-form generation |
| Video (cinematic) | Sora 2 | Highest-end video quality |
For current pricing, always refer to the Pricing page.
Batch Similar Requests
If generating multiple variations, use image-to-image mode instead of generating from scratch each time.
Monitor Usage
// 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');
}
Security
Protect Your API Key
// 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();
}
Use Connection Pooling
// Reuse HTTP connections
const agent = new https.Agent({ keepAlive: true });
const response = await fetch(url, {
agent,
// ...
});
Parallelize When Possible
// 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))
);
Monitoring
Log API Calls
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,
});
}
Set Up Alerts
Monitor for:
- High error rates
- Unusual latency
- Cost spikes
- Rate limit hits