La API de generación de video de Kling no es una interfaz síncrona que devuelve un video en una sola solicitud: primero crea una tarea, luego consulta su estado y al final descarga el resultado. Si la tratas como una llamada de Chat Completions, normalmente te quedarás atascado en el primer paso: la solicitud responde correctamente, pero no obtienes un video, solo un registro de tarea.
Este artículo sigue el orden real de integración para explicar las generaciones de interfaz, la autenticación, el envío, el polling, los callbacks, la descarga, la idempotencia y la migración en la API de Kling en 2026. Las rutas y los campos pueden cambiar entre versiones; antes de integrar, consulta la documentación oficial.
Nota: Kling, Kuaishou y sus marcas asociadas son propiedad de sus respectivos titulares. Este artículo solo ofrece información técnica y no implica afiliación ni representación con las empresas mencionadas.
1. Distingue primero las dos generaciones de interfaz
Kling mantiene hoy dos formas de interfaz, y mezclarlas es una fuente habitual de errores.
Las interfaces nuevas incluyen la versión del modelo en la ruta, por ejemplo POST /text-to-video/kling-3.0-turbo o POST /text-to-video/kling-2.6. El cuerpo ya no necesita model_name, la autenticación usa el encabezado Bearer con una API Key y los campos de respuesta son data.id y data.status.
Las interfaces antiguas suelen estar bajo /v1/videos/...; el cuerpo indica el modelo con model_name, la autenticación usa un JWT generado con AccessKey/SecretKey y los campos de respuesta son task_id y task_status. Las interfaces antiguas siguen funcionando, pero no se recomienda empezar un proyecto nuevo con ellas.
Los ejemplos de este artículo se centran en las interfaces nuevas; al final incluimos una lista de migración entre ambas generaciones.
2. Base URL y autenticación
La documentación de Kling ofrece estas direcciones de servicio:
https://api-singapore.klingai.com: para servidores fuera de China continental; la documentación oficial indica que sustituye a la antiguaapi.klingai.com.https://api-beijing.klingai.com: dirección de Beijing que aparece en ejemplos de la documentación y que conviene a despliegues dentro de China.
Las regiones disponibles, el ámbito de la cuenta y la disponibilidad de modelos dependen de la consola. No cambies de región sin motivo: las tareas y los resultados suelen pertenecer a la región donde se enviaron.
El encabezado de autenticación es Authorization: Bearer <API_KEY>, con un espacio entre Bearer y la clave. Un detalle que se pasa por alto con facilidad: las consultas de las interfaces nuevas también exigen Content-Type: application/json, aunque sean GET.
La clave solo debe estar en el servidor. Si el navegador, una app o un miniprograma la llaman directamente, exponen la credencial y además se topan con CORS y con callbacks inaccesibles. Lo recomendable es que el backend envíe las tareas y que el frontend solo reciba el estado.
3. Envía tu primera tarea de video
Primero valida el flujo completo con la duración más corta y la resolución más baja; después añade parámetros poco a poco.
export KLING_API_KEY="tu_clave"
export KLING_BASE_URL="https://api-singapore.klingai.com"
curl -sS -X POST "$KLING_BASE_URL/text-to-video/kling-3.0-turbo" \
-H "Authorization: Bearer $KLING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Calle urbana después de la lluvia, la cámara avanza lentamente, estilo cinematográfico, 16:9",
"settings": {
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5
},
"options": {
"external_task_id": "demo-20261019-001",
"callback_url": "https://example.com/kling/callback"
}
}'
Una respuesta correcta devuelve el código de negocio 0, el ID de tarea en data.id y un estado inicial que suele ser submitted:
{
"code": 0,
"message": "",
"request_id": "…",
"data": {
"id": "…",
"status": "submitted",
"create_time": 0,
"update_time": 0,
"external_id": "demo-20261019-001"
}
}
Hay varios límites que conviene tener presentes: en 3.0 Turbo, duration admite de 3 a 15 segundos y el valor predeterminado es 5; en 2.6 lo habitual es 5 o 10 segundos; prompt admite unos 3072 caracteres y la recomendación oficial es mantenerse por debajo de 2500. La resolución, la relación de aspecto y las capacidades de audio varían según el modelo, así que no apliques los parámetros de un modelo a otro.
4. Consulta el estado de la tarea
Cuando tengas el ID, consulta el estado con estas rutas:
GET /tasks?task_ids=<ID_DE_TAREA>
GET /tasks?external_task_ids=<ID_PROPIO>
task_ids y external_task_ids son mutuamente excluyentes; si hay varios IDs, sepáralos con comas. El campo data de la respuesta es un arreglo de tareas y cada tarea incluye id, status, message, create_time, update_time, external_id, outputs y billing.
Hay cuatro estados:
submitted: recibida, todavía no iniciada.processing: en generación.succeeded: correcta; ya se puede leeroutputs.failed: fallida; revisamessagey el motivo de moderación.
No consultes en un bucle de alta frecuencia. Se recomienda empezar con 5 segundos y aplicar un retroceso gradual hasta 15 o 30 segundos, con un tiempo máximo total. Las tareas de video pueden hacer cola; si tardan más de lo previsto, revisa primero la concurrencia y el paquete de recursos en lugar de reenviar la tarea de inmediato.
Si necesitas conciliar o recuperar tareas, usa la consulta por cursor con POST /tasks, filtrando por start_time, end_time, status y product_type; cada página admite hasta 500 registros.
5. Callbacks y validación de firmas
Al enviar la tarea puedes incluir callback_url, y la plataforma enviará una notificación cuando cambie el estado. Los callbacks consumen menos recursos que el polling, pero exigen una interfaz accesible desde internet, una respuesta 200 rápida y el procesamiento real en una cola.
En las interfaces nuevas, el cuerpo del callback incluye id, status, message, outputs, external_id y billing; en las antiguas incluye task_id, task_status y task_result, y el estado correcto se escribe succeed. No compartas el mismo analizador para ambas generaciones.
En seguridad, puedes crear un Webhook Secret en la consola (empieza por whsec_). El callback trae los encabezados webhook-id, webhook-timestamp y webhook-signature; el contenido firmado es {webhook-id}.{webhook-timestamp}.{rawBody}, el algoritmo es HMAC-SHA256 y el resultado se codifica en Base64. Al validar, cuida tres puntos: la marca de tiempo debe estar dentro de más o menos 5 minutos, la firma se calcula sobre el cuerpo original de la solicitud y la comparación debe usar una función de tiempo constante. La plataforma admite que el secreto antiguo y el nuevo coexistan durante un periodo de gracia de 7 días, lo que facilita una rotación sin cortes.
Los callbacks pueden repetirse o llegar fuera de orden. El procesamiento debe ser idempotente por ID de tarea, y el estado solo debe avanzar: no sobrescribas processing con submitted.
6. Descarga y guarda los resultados
Los videos de las tareas correctas aparecen en el arreglo outputs; el elemento con type igual a video contiene url, watermark_url, duration e id. La url es una dirección de descarga con protección contra hotlinking, y es posible que se rechace si la incrustas directamente en una página web o en un sistema de terceros.
Hay dos restricciones firmes:
- Los enlaces de resultado se limpian unos 30 días después de la generación; no los trates como una dirección CDN permanente.
- La protección contra hotlinking implica que debes descargar en el servidor y volver a guardar el archivo en tu propio almacenamiento de objetos.
El flujo recomendado es: en cuanto la tarea tenga éxito, descarga el video, valida el Content-Type y el tamaño, calcula una suma de verificación, guárdalo en el almacenamiento de objetos y asocia tu propia dirección con el ID de tarea. Para distribuir al exterior, usa URL firmadas propias con tiempo de expiración.
7. Idempotencia, reintentos y concurrencia
El error más caro en tareas de video es "reenviar después de un timeout". Que una solicitud agote el tiempo de espera no significa que la tarea no se haya creado; puede que solo se haya perdido la respuesta.
external_task_id es el principal mecanismo de idempotencia: genera un ID estable antes de enviar y guárdalo en la base de datos; si hay timeout, consulta con GET /tasks?external_task_ids=... y reintenta solo cuando confirmes que no existe ninguna tarea. Ese ID debe ser único dentro de la misma cuenta. No uses UUID aleatorios como clave de reintento, porque cada reintento crearía una tarea nueva.
Sobre la concurrencia, la documentación oficial indica que solo "crear tarea" cuenta para el límite; las consultas no. La plataforma no hace la cola por ti: si superas las ranuras del paquete de recursos, devuelve 1303. Todas las API Keys comparten el pool de concurrencia de la misma cuenta. La estrategia recomendada es un retroceso exponencial que empiece en al menos 1 segundo y una cola de envío en la aplicación que libere solicitudes según las ranuras disponibles.
8. Tabla de errores comunes
| Código de negocio | HTTP | Significado | Qué hacer |
|---|---|---|---|
| 1002 | 401 | Credencial no válida | Revisa la clave, la región y los encabezados |
| 1103 | 403 | Sin permiso para la interfaz o el modelo | Confirma que la cuenta y el paquete tengan el modelo habilitado |
| 1101 | 429 | Deuda en pago por uso | Recarga y vuelve a intentar |
| 1102 | 429 | Paquete agotado o vencido | Compra un paquete o cambia el modo de facturación |
| 1201 | 400 | Valor de parámetro no válido | Lee message y revisa duración, relación de aspecto y resolución |
| 1301 | 400 | Moderación de contenido no superada | Cambia el prompt o el material; no reintentes igual |
| 1302 | 429 | Demasiadas solicitudes | Baja la frecuencia y aplica retroceso exponencial |
| 1303 | 429 | Concurrencia excedida | Encola el envío y espera a que se libere una ranura |
| 1203 | 404 | Recurso o modelo inexistente | Verifica la ruta y la versión del modelo |
| 5002 | 500 | Timeout interno del servicio | Conserva el ID de tarea y consulta más tarde; no reenvíes |
Al diagnosticar, revisa primero el estado HTTP, después el código de negocio y al final el request_id. Registra los tres juntos en el log; al contactar al soporte, esto reduce mucho el tiempo de localización.
9. Lista de verificación para migrar desde la versión antigua
- Cambia la autenticación de JWT con AccessKey/SecretKey a API Key Bearer; las interfaces antiguas conservan la compatibilidad con JWT.
- Cambia las rutas de
/v1/videos/...a formas por modelo como/text-to-video/kling-3.0-turbo. - Elimina
model_namedel cuerpo; el modelo se determina por la ruta. - Cambia los campos de respuesta de
task_idytask_statusaidystatus. - Cambia el estado correcto de
succeedasucceeded. - Cambia la consulta por ruta GET de tarea a
GET /tasks?task_ids=.... - Cambia los resultados de
task_result.videosa los elementos contype=videodentro deoutputs. - Separa los analizadores de callbacks por formato nuevo y antiguo para evitar desajustes de campos.
- Añade la limpieza a los 30 días y la lógica de retransferencia por la protección contra hotlinking.
- Completa la idempotencia con
external_task_idy haz un simulacro de fallos por timeout, callbacks duplicados y moderación rechazada.
Durante la migración conviene ejecutar ambas versiones en paralelo: envía tráfico gradual a la interfaz nueva, mantén la antigua como ventana de reversión y desactívala cuando confirmes que la tasa de éxito, la latencia y la facturación cumplen lo esperado.
10. Puntos de control al integrar a través de un gateway
Si usas el gateway de IA de ZSQH para unificar el acceso, además de la clave y la Base URL debes confirmar si el canal de video está habilitado, si las tareas asíncronas se reenvían sin alteraciones, si se conservan external_task_id y los callbacks y cómo se entregan las URL de resultado. Una interfaz de texto compatible con OpenAI no sirve directamente para tareas de video.
Puedes consultar primero modelos y precios y luego registrarte y crear una clave de prueba. Valida el envío, la consulta y la descarga con una tarea de 5 segundos antes de decidir cómo migrar el tráfico de producción.
Preguntas frecuentes
¿La API de Kling es síncrona o asíncrona?
Es asíncrona. El envío solo devuelve un ID de tarea; hay que consultar GET /tasks o recibir un callback y, cuando la tarea termine correctamente, descargar el video desde outputs.
¿Debo usar la Base URL de Singapur o la de Beijing?
Depende de la ubicación del servidor, de la cuenta y de la región donde estén disponibles los modelos. La documentación oficial muestra ambas direcciones; confirma en la consola antes de integrar y mantén la misma región para el envío y la consulta.
La tarea se queda en processing. ¿Qué hago?
Revisa primero si hay ranuras de concurrencia y paquete de recursos suficientes, y luego si la tarea está en cola. Si tarda más de lo esperado, consulta por ID en lugar de reenviar; si es necesario, contacta al soporte y proporciona el request_id.
¿Puedo poner la URL del resultado directamente en mi sitio o en un miniprograma?
No es recomendable. El enlace tiene formato de protección contra hotlinking y se limpia alrededor de 30 días después. Descarga en el servidor, guarda el archivo en tu almacenamiento de objetos y distribúyelo con URL firmadas propias.
¿Un reintento después de un fallo cobra dos veces?
Depende del motivo del fallo y de las reglas de facturación de la plataforma. Un rechazo de moderación no debería reintentarse igual; ante un timeout de red, consulta primero por external_task_id y envía solo si confirmas que la tarea no se creó. Antes de salir a producción, lee las condiciones de facturación y valida con tareas de bajo costo.
Lecturas relacionadas:
