Tareas
Crea una tarea, sigue su estado, lee el resultado y usa wait, la lista de tareas, retry y purge.
Cada generación es una tarea. La creas con una llamada, se ejecuta sola y recoges el resultado cuando está listo: preguntando por él, esperando en la primera llamada o recibiendo un webhook.
POST /jobs/createTasktaskIdGET /jobs/recordInfostateGET output.assets[].url
Crea una tarea
curl -X POST "https://api.popnow.ai/api/v1/jobs/createTask" \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "alibaba/wan-3.0/image-to-video",
"input": {
"image_url": "https://media.popnow.ai/movie/lighthouse.webp",
"prompt": "Waves roll in slowly, the camera drifts toward the lighthouse",
"resolution": "480p",
"duration_seconds": 5
},
"callBackUrl": "https://your-app.example.com/hooks/popnow"
}'Cuerpo
| Campo | Obligatorio | Qué es |
|---|---|---|
model | Sí | El ID del modelo, en Modelos |
input | Sí | Los campos del modelo, validados con su esquema de entrada |
callBackUrl | No | URL HTTPS pública que recibe la tarea terminada. Mira Webhooks |
quoteId, expectedCredits | No | Fija un precio que confirmaste con jobs/quote |
Cabeceras
| Cabecera | Qué es |
|---|---|
Authorization: Bearer sk-popnow-… | Tu clave de API |
Idempotency-Key | Muy recomendable. Reintentar con la misma clave devuelve la tarea original. Mira Idempotencia |
X-PopNow-Retention | Opcional. Segundos que se guardan los resultados y el prompt de esta tarea. Solo puede acortar la conservación, nunca alargarla |
Accept-Language | Opcional. Idioma de los mensajes de error. Mira Errores |
Respuesta
Una tarea nueva vuelve como HTTP 202:
{
"code": 200,
"msg": "success",
"data": {
"taskId": "job_01JH8Z4Q5W2N7R3K9M6P1C0VXD",
"state": "queued",
"estimatedCredits": 34,
"estimatedCost": "0.34",
"deadlineAt": "2026-10-16T09:40:00Z"
},
"request_id": "req_…"
}202 significa aceptada, no terminada. estimatedCredits es lo que se retiene de tu saldo: lo máximo que puede costar esta tarea (estimatedCost es el mismo importe en dólares). Si la creación falla, no se crea nada ni se retiene nada; el code te dice por qué (Errores).
Estados
queuedrunningsucceededfailedexpired| Estado | ¿Final? | Significado |
|---|---|---|
queued | No | Aceptada, esperando para empezar |
running | No | Generándose |
succeeded | Sí | Hecha; los archivos están en output.assets |
failed | Sí | No pudo terminar; mira errorCode y errorMessage. La retención se libera |
expired | Sí | Pasó su plazo sin terminar. La retención se libera |
canceled | Sí | Solo en registros antiguos. Hoy una tarea aceptada no se puede cancelar |
Trata cualquier estado que no reconozcas como «todavía no ha terminado» y sigue consultando.
Sáltate el sondeo con wait
Añade ?wait=<segundos> (hasta 60) a createTask y la conexión se queda abierta hasta que la tarea termine o se acabe el tiempo:
- Terminó a tiempo → HTTP
200con el registro completo de la tarea, con la misma forma que devuelverecordInfo. Revisadata.state: final no siempre significa con éxito. - No terminó → el
202de siempre, y sigues sondeando o esperas al webhook.
Úsalo para imágenes y audio corto; el video casi siempre pasa de 60 segundos. Cortar la conexión antes no detiene ni cancela la tarea.
Lee una tarea
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=job_01JH8Z4Q5W2N7R3K9M6P1C0VXD" \
-H "Authorization: Bearer $POPNOW_API_KEY"| Campo | Significado |
|---|---|
taskId, model, state | Qué tarea, qué modelo y en qué punto está |
input | La entrada tal como se ejecutó, incluida la seed elegida si no enviaste una |
output.assets[] | Los archivos. Cada uno tiene url, expiresAt, mime y, cuando aplica, width, height, durationSeconds, bytes, role |
errorCode, errorMessage | Por qué falló una tarea. Decide con errorCode y muestra errorMessage |
credits, cost, settled | Mientras settled sea false, credits es la retención; con true, es el cargo final. cost es el mismo importe en dólares |
createdAt, completedAt, deadlineAt | Marcas de tiempo; deadlineAt es cuando caduca una tarea sin terminar |
retention.outputsExpireAt | Cuándo se borrarán los archivos de esta tarea |
contentState | present, o expired / purged cuando se ha borrado el contenido |
Tres caducidades distintas
deadlineAt: cuánto puede tardar la tarea. Pasado ese momento, queda enexpiredy se libera la retención.output.assets[].expiresAt: cuánto dura ese enlace firmado, unos 20 minutos. Lee la tarea otra vez para tener uno nuevo; el archivo sigue ahí.retention.outputsExpireAt: cuándo se borra el archivo guardado. Descarga antes lo que quieras conservar o guárdalo en tu biblioteca de recursos.
Qué trae output
La mayoría de las tareas devuelven un archivo. Algunas devuelven más: varias imágenes cuando el modelo genera variaciones, el clip unido y luego el tramo nuevo al extender un video (role: "video" y después role: "segment"), o una imagen base más capas transparentes al separar capas (cada una con un objeto layer). La transcripción de voz llega en output.text.
Los enlaces de los archivos son de portador: cualquiera que tenga la URL puede descargar el archivo hasta que caduque. No envíes tu clave de API al descargarlos.
Primero webhooks, el sondeo como respaldo
Sondear funciona, pero un webhook sale más barato para ambos lados: te enteras del resultado en cuanto existe y no gastas solicitudes mientras tanto. Una integración sólida usa las dos cosas: webhooks para el camino normal y, de vez en cuando, un repaso con recordInfo de las tareas cuyo webhook no llegó.
Si sondeas, ve con calma: cada 2–3 segundos para imágenes, cada 10–15 segundos para video, y para en deadlineAt.
La lista de tareas
GET /api/v1/jobs devuelve las tareas que creó esta clave, las más recientes primero, sin entradas ni resultados:
curl "https://api.popnow.ai/api/v1/jobs?state=failed&from=2026-10-01&limit=50" \
-H "Authorization: Bearer $POPNOW_API_KEY"Filtros: from y to (fechas UTC, como mucho 92 días de diferencia; por defecto los últimos siete días), state, model, limit (hasta 100). Si hasMore es true, devuelve nextCursor como cursor con los mismos filtros.
Reintenta una tarea fallida
POST /api/v1/jobs/retry con { "taskId": "…" } crea una tarea nueva a partir de una failed o expired, con su entrada original y al precio de hoy. La tarea original no cambia. Responde 409 mientras la tarea de origen no haya terminado, y no puede reintentar una tarea que salió bien: crea una nueva.
Borra el contenido de una tarea
POST /api/v1/jobs/purge con { "taskId": "…" } borra los archivos, el resultado y el prompt guardado de la tarea. El registro de facturación se queda: el cargo, el modelo, el estado y las marcas de tiempo se mantienen, y la respuesta lo confirma con billingRetained: true. Solo se pueden purgar tareas terminadas, y repetir la llamada es seguro.

