kling/3.0/image-to-videoDesde 51 créditos por un clip de 5 segundos· Imagen a video

El image-to-video de Kling 3.0 parte de tu cuadro de apertura y renderiza de 3 a 15 segundos a 720p, 1080p o 4K. Añade un cuadro de cierre opcional, activa o desactiva el audio nativo y elige una sola toma o un montaje de varios planos.

Llámalo con el nombre de modelo kling/3.0/image-to-video en POST /jobs/createTask, desde 51 créditos por un clip de 5 segundos (0,51 US$). Las cuentas nuevas reciben 30 créditos gratis para que lo pruebes primero en el Playground.

  • Crear video
  • Imagen a video
  • Control de movimiento
  • Hasta 4K
  • Clips de 3 a 15 s
  • Con sonido
  • Fotograma inicial y final
  • 3 relaciones de aspecto
Nombre del modelokling/3.0/image-to-video
EndpointPOST https://api.popnow.ai/api/v1/jobs/createTask
# 1. Create the task. Keep the Idempotency-Key if you retry after a network error.
export IDEMPOTENCY_KEY="$(uuidgen)"
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: $IDEMPOTENCY_KEY" \
  -d '{
  "model": "kling/3.0/image-to-video",
  "input": {
    "prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
    "image_url": "https://media.popnow.ai/influencer/examples/marco.webp",
    "resolution": "720p",
    "duration_seconds": 5,
    "shot_type": "single"
  }
}'

# 2. Copy data.taskId from the response, then poll until state is succeeded, failed, canceled or expired.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
  -H "Authorization: Bearer $POPNOW_API_KEY"

El input se genera a partir del esquema de abajo, así que pasa la validación tal cual. Cambia el prompt y los enlaces por los tuyos.

Precio

OpciónCréditos por segundo≈ USD
generate_audio falseresolution 720p10,080,10 US$
generate_audio falseresolution 1080p13,440,13 US$
generate_audio trueresolution 720p15,120,15 US$
generate_audio trueresolution 1080p20,160,20 US$
generate_audio falseresolution 4K50,40,50 US$
generate_audio trueresolution 4K50,40,50 US$

1 crédito = 0,01 $ · Todas las opciones y su precio: GET /models/kling/3.0/image-to-video

Cada tarea se redondea al alza a créditos enteros, así que una ejecución en el nivel más bajo cuesta 51 créditos por un clip de 5 segundos (0,51 US$).

Límites

Duración del clip
3–15 s
Resoluciones
720p · 1080p · 4K
Longitud del prompt (caracteres)
2,500
Subida máxima
10 MB

Parámetros

Estos campos salen del mismo esquema con el que validamos cada petición. Los campos que no aparecen se rechazan.

Algunos campos dependen entre sí (por ejemplo, al menos una referencia). El esquema completo de abajo tiene las reglas exactas.

  • promptstringObligatorio

    Describe what happens after the opening frame: the action, the camera and, with sound on, the sounds.

    Rango
    1 – 2500 chars
  • image_urlstringObligatorio

    La imagen de partida.

    Rango
    image/jpeg, image/png, image/webp, image/gif · ≤ 10 MB
  • negative_promptstringOpcional

    Lo que no quieres ver.

    Rango
    0 – 2500 chars
  • last_image_urlstringOpcional

    Fotograma final opcional, para que el clip termine justo donde quieres.

    Rango
    image/jpeg, image/png, image/webp, image/gif · ≤ 10 MB
  • resolutionstringOpcionalCambia el precio

    Tamaño de salida. Más grande es más nítido y cuesta más.

    Por defecto
    "720p"
    Valores permitidos
    "720p""1080p""4k"
  • generate_audiobooleanOpcionalCambia el precio

    Añade sonido acorde a la imagen: voces, ambiente y efectos.

    Por defecto
    false
  • duration_secondsintegerOpcionalCambia el precio

    Cuánto dura el clip. Se cobra por segundo.

    Por defecto
    5
    Rango
    3 – 15
  • shot_typestringOpcional

    single keeps one continuous shot; multi lets the model cut the prompt into several shots on its own; customize follows the shot list you give in multi_prompt.

    Por defecto
    "single"
    Valores permitidos
    "single""multi""customize"
  • multi_promptarray<object>A veces obligatorio

    Shot list for shot_type customize: one entry per shot, in order, each with its own prompt and length in seconds. The lengths must add up to duration_seconds.

    Rango
    1 – 6 items
    Campos internos
    • multi_prompt[].duration_secondsintegerObligatorio

      Length of this shot in whole seconds, 1 to 15.

      Rango
      1 – 15
    • multi_prompt[].promptstringObligatorio

      What happens in this shot, up to 512 characters.

      Rango
      1 – 512 chars
  • guidance_scalenumberOpcional

    Con qué rigor sigue el modelo el prompt.

    Por defecto
    0.5
    Rango
    0 – 1
Esquema JSON sin procesar
{
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "properties": {
          "shot_type": {
            "const": "customize"
          }
        },
        "required": [
          "shot_type"
        ]
      },
      "then": {
        "required": [
          "multi_prompt"
        ]
      }
    }
  ],
  "properties": {
    "duration_seconds": {
      "default": 5,
      "description": "Output length in whole seconds, from 3 to 15. Billed per second.",
      "maximum": 15,
      "minimum": 3,
      "type": "integer"
    },
    "generate_audio": {
      "default": false,
      "description": "Generate a native soundtrack (voices, effects, ambience) with the picture. Audio costs more per second.",
      "type": "boolean"
    },
    "guidance_scale": {
      "default": 0.5,
      "description": "How closely the clip follows the prompt, from 0 to 1. Higher sticks to the prompt more; lower gives the model more freedom.",
      "maximum": 1,
      "minimum": 0,
      "type": "number"
    },
    "image_url": {
      "contentMediaType": [
        "image/jpeg",
        "image/png",
        "image/webp",
        "image/gif"
      ],
      "description": "Opening frame. The clip starts from this image.",
      "format": "uri",
      "type": "string"
    },
    "last_image_url": {
      "contentMediaType": [
        "image/jpeg",
        "image/png",
        "image/webp",
        "image/gif"
      ],
      "description": "Optional closing frame the clip should end on.",
      "format": "uri",
      "type": "string"
    },
    "multi_prompt": {
      "description": "Shot list for shot_type customize: one entry per shot, in order, each with its own prompt and length in seconds. The lengths must add up to duration_seconds.",
      "items": {
        "additionalProperties": false,
        "properties": {
          "duration_seconds": {
            "description": "Length of this shot in whole seconds, 1 to 15.",
            "maximum": 15,
            "minimum": 1,
            "type": "integer"
          },
          "prompt": {
            "description": "What happens in this shot, up to 512 characters.",
            "maxLength": 512,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "prompt",
          "duration_seconds"
        ],
        "type": "object"
      },
      "maxItems": 6,
      "minItems": 1,
      "type": "array"
    },
    "negative_prompt": {
      "description": "What to keep out of the clip: objects, looks or motion you do not want.",
      "maxLength": 2500,
      "type": "string"
    },
    "prompt": {
      "description": "Describe what happens after the opening frame: the action, the camera and, with sound on, the sounds.",
      "maxLength": 2500,
      "minLength": 1,
      "type": "string"
    },
    "resolution": {
      "default": "720p",
      "description": "Output resolution. Higher tiers cost more per second.",
      "enum": [
        "720p",
        "1080p",
        "4k"
      ],
      "type": "string"
    },
    "shot_type": {
      "default": "single",
      "description": "single keeps one continuous shot; multi lets the model cut the prompt into several shots on its own; customize follows the shot list you give in multi_prompt.",
      "enum": [
        "single",
        "multi",
        "customize"
      ],
      "type": "string"
    }
  },
  "required": [
    "prompt",
    "image_url"
  ],
  "type": "object"
}

Un resultado real de Kling 3.0

PromptLightning flashes and lights the whole forecourt white for an instant. She pushes off the truck, pulls her jacket collar up against the rain and walks out from under the canopy into the downpour toward the camera, rain bouncing off the concrete around her boots. Sound: a sharp crack of thunder, heavy rain drumming on the canopy roof, her footsteps splashing, the buzz of the fluorescent lights.
La misma petición a través de la API
{
  "model": "kling/3.0/image-to-video",
  "input": {
    "prompt": "Lightning flashes and lights the whole forecourt white for an instant. She pushes off the truck, pulls her jacket collar up against the rain and walks out from under the canopy into the downpour toward the camera, rain bouncing off the concrete around her boots. Sound: a sharp crack of thunder, heavy rain drumming on the canopy roof, her footsteps splashing, the buzz of the fluorescent lights.",
    "image_url": "https://media.popnow.ai/influencer/examples/marco.webp",
    "resolution": "720p",
    "duration_seconds": 5,
    "shot_type": "single",
    "generate_audio": true
  }
}

Este resultado partió de un archivo subido: pon tu propio enlace donde está el de ejemplo.

Respuestas, consultas y callbacks

Todos los modelos funcionan igual: crea una tarea y luego consulta su estado o espera el callback.

Consulta el precio primero

cURL
curl -X POST https://api.popnow.ai/api/v1/jobs/quote \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "kling/3.0/image-to-video",
  "input": {
    "prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
    "image_url": "https://media.popnow.ai/influencer/examples/marco.webp",
    "resolution": "720p",
    "duration_seconds": 5,
    "shot_type": "single"
  }
}'

El mismo cuerpo que createTask. Devuelve el cargo esperado y el máximo posible, sin ejecutar nada.

Aceptada

HTTP
HTTP/1.1 202 Accepted

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "state": "queued"
  },
  "request_id": "req_example_create"
}

HTTP 202 significa que la tarea se aceptó y los créditos quedan reservados, todavía sin cobrar. El cargo final nunca supera la reserva.

Consultar estado

cURL
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
  -H "Authorization: Bearer $POPNOW_API_KEY"

Consulta cada pocos segundos espaciando cada vez más y para cuando state sea succeeded, failed, canceled o expired.

Tarea terminada

JSON
{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "model": "kling/3.0/image-to-video",
    "state": "succeeded",
    "output": {
      "assets": [
        {
          "url": "https://cdn.popnow.ai/tasks/task_01k3m8x9q2z4v7n5p6r8s0t1w3/output.mp4?signature=FROM_RESPONSE",
          "expiresAt": "2026-10-17T12:20:00Z",
          "mime": "video/mp4",
          "width": 1280,
          "height": 720,
          "durationSeconds": 5
        }
      ]
    },
    "settled": true
  },
  "request_id": "req_example_record"
}

Descarga desde la url antes de expiresAt. ¿Necesitas un enlace nuevo más tarde? Pídelo con POST /common/download-url.

Verificar un callback

Node.js
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
import express from "express";

const app = express();
// express.raw keeps the exact bytes that were signed; express.json would not match.
app.post("/hooks/popnow", express.raw({ type: "application/json" }), (req, res) => {
  const timestamp = req.header("X-Webhook-Timestamp");
  const signature = req.header("X-Webhook-Signature") ?? "";
  const body = JSON.parse(req.body.toString("utf8"));
  const taskId = body.data?.taskId ?? body.task_id;
  const digest = createHash("sha256").update(req.body).digest("hex");
  const expected = createHmac("sha256", process.env.POPNOW_WEBHOOK_SECRET)
    .update(`${taskId}.${timestamp}.${digest}`)
    .digest("base64");
  const ok = expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
  // Check the signature first, then reject anything older than five minutes.
  if (!ok || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return res.status(401).end();
  res.status(200).end(); // answer fast, then fetch the task and store its files
});

Con callBackUrl te enviamos la tarea terminada. Comprueba la firma sobre el cuerpo sin procesar antes de fiarte de ella.

Enviar un archivo local

cURL
curl -X POST https://api.popnow.ai/api/v1/common/upload-url \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contentType": "image/png", "bytes": 482113}'

# PUT the file bytes to data.uploadUrl with every header in data.headers, then commit it:
curl -X POST https://api.popnow.ai/api/v1/files/$FILE_ID/commit \
  -H "Authorization: Bearer $POPNOW_API_KEY"
# The commit returns a popnow://f/... reference. Put it in any image, video or
# audio field of the task input instead of a public https URL.

Los enlaces https públicos funcionan tal cual. Los archivos locales pasan antes por upload-url y commit.