Async endpoint. The request returns immediately with a job_id; the actual generation runs in the background and is charged on success only. Billed per second of generated footage.
Request body
One of: kling-2.5-pro, kling-3-pro, kling-3-pro-audio, seedance-2-pro, seedance-2-fast. See Video Generation.
Text prompt describing the desired video. Maximum 4000 characters.
Clip length in seconds. Range 1–10. Each second is billed at the model’s per-second rate.
HTTPS URL of a starting frame. When present, Kyma routes the request to the model’s image-to-video variant — the image becomes the first frame and the prompt drives the motion. Optional; all five models accept it.
Client-supplied key (≤128 chars) to make the request safe to retry. Repeated POSTs with the same (api_key, idempotency_key) pair return the same job — no duplicate charge, no duplicate generation.
Pass-through model-specific parameters (e.g. seed, aspect_ratio). Forwarded to the underlying provider unchanged.
Response
202 Accepted for new jobs, 200 OK if the same idempotency_key is replayed.
{
"id": "v3a9c8b2e1d0a4b6c7d8e9f0",
"object": "video.job",
"status": "pending",
"model": "kling-3-pro",
"created_at": "2026-04-26T10:00:00.000Z",
"completed_at": null,
"output": null,
"error": null,
"estimated_cost": 0.7560,
"charged_amount": null
}
Job ID. Use it to poll GET /v1/jobs/{id}.
One of: pending, processing, succeeded, failed, refunded, expired.
Hold amount placed at submit time (USD) — per_second_usd × duration. Refunded if the job fails.
Final billed amount once the job succeeds. null until then.
Poll for the result
Same response shape. Poll every 2–5 seconds until status is succeeded, failed, refunded, or expired. Most clips complete within 1–3 minutes; the runner times out at 10 minutes.
{
"id": "v3a9c8b2e1d0a4b6c7d8e9f0",
"object": "video.job",
"status": "succeeded",
"model": "kling-3-pro",
"created_at": "2026-04-26T10:00:00.000Z",
"completed_at": "2026-04-26T10:02:18.840Z",
"output": {
"url": "https://blob.vercel-storage.com/.../clip.mp4",
"metadata": {
"videos": [{
"width": 1920,
"height": 1080,
"duration": 5,
"content_type": "video/mp4"
}]
}
},
"error": null,
"estimated_cost": 0.7560,
"charged_amount": 0.7560
}
The output.url points to a Vercel Blob URL hosted by Kyma — the original upstream URL is rehosted so it remains stable after the upstream TTL expires.
Errors
| Status | error.code | When |
|---|
400 | invalid_model | Model is not a supported video model |
400 | invalid_prompt | Missing prompt or > 4000 chars |
400 | invalid_duration | duration is outside 1–10 |
401 | auth_error | Missing or invalid API key |
402 | insufficient_balance | Hold could not be placed |
413 | invalid_request | Request body > 25 MB |
429 | rate_limited | Tier limit exceeded |
500 | db_error / provider_error | Internal failure — hold is fully refunded |
When status becomes failed or refunded, no charge is made and the held funds are returned to your balance via a hold_release ledger entry.
Examples
Cinematic hero clip
curl -X POST https://kymaapi.com/v1/videos/generations \
-H "Authorization: Bearer $KYMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3-pro",
"prompt": "an architectural fly-through of a glass-and-steel tower at sunset, cinematic anamorphic look",
"duration": 5
}'
Talking-head with native audio
curl -X POST https://kymaapi.com/v1/videos/generations \
-H "Authorization: Bearer $KYMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3-pro-audio",
"prompt": "a barista pulling an espresso shot, the machine hisses, ambient cafe murmur",
"duration": 5
}'
Image-to-video
curl -X POST https://kymaapi.com/v1/videos/generations \
-H "Authorization: Bearer $KYMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-pro",
"prompt": "the camera pulls back as the subject begins to walk forward",
"image_url": "https://example.com/frame-1.jpg",
"duration": 5
}'
Idempotent retry
curl -X POST https://kymaapi.com/v1/videos/generations \
-H "Authorization: Bearer $KYMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-fast",
"prompt": "a phone notification slides in from the right, soft chime, clean UI background",
"duration": 5,
"idempotency_key": "campaign-spring-asset-7"
}'
Replaying this exact request returns the same job — no new charge.