Recibe los resultados de las tareas mediante callbacks HTTP en lugar de polling.
Resumen
Cuando usas el modo callback, APIXO envía una solicitud POST a tu URL especificada cuando una tarea finaliza. Esto elimina la sobrecarga del polling y proporciona notificaciones inmediatas — ideal para aplicaciones de producción con alto volumen.
Configuración
Crear un endpoint webhook
Tu endpoint debe aceptar solicitudes POST, responder con HTTP 200 en 30 segundos y ser accesible públicamente vía HTTPS.Si tu endpoint no responde con HTTP 200 en 30 segundos, APIXO reintentará la entrega hasta 3 veces con retrasos crecientes.
Express.js
FastAPI
Next.js
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);
} else if (state === 'failed') {
console.error(`Task ${taskId} failed: ${failCode} - ${failMsg}`);
}
res.status(200).send('OK');
});
app.listen(3000);
from fastapi import FastAPI, Request
import json
app = FastAPI()
@app.post('/webhook/apixo')
async def handle_webhook(request: Request):
body = await request.json()
data = body['data']
if data['state'] == 'success':
urls = json.loads(data['resultJson'])['resultUrls']
print(f"Generated: {urls}")
elif data['state'] == 'failed':
print(f"Task {data['taskId']} failed: {data['failCode']} - {data['failMsg']}")
return {'status': 'ok'}
// app/api/webhook/apixo/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const body = await request.json();
const { taskId, state, resultJson, failCode, failMsg } = body.data;
if (state === 'success') {
const urls = JSON.parse(resultJson).resultUrls;
console.log('Generated:', urls);
} else if (state === 'failed') {
console.error(`Task ${taskId} failed: ${failCode} - ${failMsg}`);
}
return NextResponse.json({ status: 'ok' });
}
Enviar una tarea con callback
Incluye request_type: "callback" y tu callback_url en la solicitud:curl -X POST https://api.apixo.ai/api/v1/generateTask/nano-banana \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request_type": "callback",
"callback_url": "https://your-domain.com/webhook/apixo",
"input": {
"mode": "text-to-image",
"prompt": "A beautiful landscape"
}
}'
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',
},
}),
});
response = requests.post(
'https://api.apixo.ai/api/v1/generateTask/nano-banana',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'request_type': 'callback',
'callback_url': 'https://your-domain.com/webhook/apixo',
'input': {
'mode': 'text-to-image',
'prompt': 'A beautiful landscape',
},
}
)
Payload del webhook
Success
{
"code": 200,
"message": "success",
"data": {
"taskId": "task_abc123xyz",
"state": "success",
"resultJson": "{\"resultUrls\":[\"https://cdn.apixo.ai/output/abc.jpg\"]}",
"costTime": 12500,
"createTime": 1704067200000,
"completeTime": 1704067212500
}
}
Failure
{
"code": 200,
"message": "success",
"data": {
"taskId": "task_abc123xyz",
"state": "failed",
"failCode": "CONTENT_VIOLATION",
"failMsg": "Content violates usage policy",
"createTime": 1704067200000,
"completeTime": 1704067205000
}
}
Campos del payload
Identificador único de la tarea.
Estado final de la tarea: success o failed.
Cadena JSON que contiene el array resultUrls. Solo presente en éxito.
Tiempo de procesamiento en milisegundos.
Código de error. Solo presente en fallo.
Mensaje de error legible. Solo presente en fallo.
Política de reintentos
Si tu endpoint webhook no responde con HTTP 200:
| Intento | Retraso |
|---|
| 1.º reintento | 30 segundos |
| 2.º reintento | 2 minutos |
| 3.º reintento | 10 minutos |
Después de 3 intentos fallidos, el webhook se abandona. Aún puedes consultar el estado de la tarea vía el endpoint Estado de tarea.
Recomendaciones de seguridad
Implementar idempotencia
Los webhooks pueden entregarse más de una vez. Usa taskId para desduplicar y evitar procesar el mismo resultado dos veces.
const processedTasks = new Set();
app.post('/webhook/apixo', (req, res) => {
const { taskId } = req.body.data;
if (processedTasks.has(taskId)) {
return res.status(200).send('Already processed');
}
processedTasks.add(taskId);
// Process the task...
res.status(200).send('OK');
});
Usar solo HTTPS
Siempre usa HTTPS para tu endpoint webhook para garantizar que los datos se cifren en tránsito.
Probar webhooks
Usa ngrok para exponer tu servidor local durante el desarrollo:
ngrok http 3000
# Devuelve: https://abc123.ngrok.io — usa esto como tu callback_url
También puedes consultar el estado de la tarea vía la API incluso en modo callback, lo cual es útil para depuración.