Kling 4.0 (Text to Video)
Kling 4.0 text-to-video, 3-30s at 720p or 1080p. Always generates native audio.
Capabilities
Best for
- •Cinematic text-to-video shots
- •Short social and ad clips
- •Consistent multi-shot sequences
- •Look-dev and style exploration
Not for
- •Frame-exact rotoscoping
- •Feature-length renders
- •Pixel-perfect compositing
- •Precise on-screen text
Authentication
api key header
The Pika API uses API keys to authenticate requests. Send your key in the X-API-Key header. Your API key is a secret. Don't expose it in browsers or other client-side code. Instead, call the API from your server. The signed-in playground uses a portal session and never sends your API key.
X-API-Key: YOUR_API_KEY
Endpoint
asynchronous · poll for the result
REST Setup
plain HTTPS
Video generation runs through the REST endpoint shown above. The API is plain JSON over HTTPS, so any HTTP client works. No provider-specific SDK is required.
Generate
POST /v1/media/kling/kling-4.0/text-to-video
Request
curl -X POST https://api.dev.pika.art/v1/media/kling/kling-4.0/text-to-video \-H "X-API-Key: YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{"prompt": "SCENE: wide 16:9, long-lens compression, camera low on the road. An empty dusty-pink desert road running straight to a distant flat-topped mesa under a soft overcast sky, scrub brush and pale sand either side. A Mexican man in his thirties with a moustache, in a cream cowboy hat, cream cowboy boots and a costumey emerald sequinned western suit with silver yoke trim, pushes a supermarket trolley heaped with whole striped watermelons along the road edge on the left third, walking with purpose. A single tiny white pickup truck far behind on the road. Palette: dusty rose desert against emerald sequins and watermelon green.\nCAMERA: starts low and close at road level beside the trolley, then cranes up and pulls back high above the road in one continuous move, revealing the vast empty desert, the long road and the mesa, the man and his trolley becoming small. The high wide shot is framed to KEEP THE RUNAWAY WATERMELON IN FRAME the whole time.\nACTION / STORY: 0-3s he pushes the trolley forward, one wheel squeaking and wobbling, sequins glittering. 3-6s the trolley jolts over a crack and one watermelon tumbles off the top and rolls away ahead of him down the middle of the road; he stops and watches it go, deadpan. 6-10s he sighs and keeps pushing the trolley onward toward the mesa as the camera rises into the high wide shot. CRITICAL CONTINUITY: in the high wide shot the single runaway watermelon is clearly visible on the road - a distinct dark-green striped ball still rolling along the centre line well ahead of the man, kicking up a tiny puff of dust, a clear gap of road between it and the trolley, with the distant pickup truck further down the road beyond it. The watermelon never disappears from frame.\nAUDIO: a squeaky wobbling trolley wheel, the hollow thump of the watermelon hitting asphalt and rolling, sequins rustling, dry desert wind, a far-off engine. Sparse twangy western guitar. No speech.\nLOOK: a real 35mm film photograph in motion, never a 3D render. Soft, diffused, even, dimensional light; low-to-moderate contrast; colour true, soft but vibrant, never washed out; creamy highlight roll-off, a touch of warmth, light natural film grain, no HDR or sharpening. Skin with real photographic texture - pores, fine hairs, freckles. Anatomy correct: every person has exactly two arms and two hands with five fingers, no extra limbs. No visible text, logos or branding anywhere. SPEED IS CRITICAL: everything moves at normal real-time speed, like 24fps footage played back at 24fps - natural motion, NO slow motion.","duration": 10,"resolution": "720p","aspect_ratio": "16:9"}'
Response
{"id": "media_8f3a2c91-5b7d-4e0a-9c26-31d4f2a8e6b0","status": "queued"}
Request body
Accepted values
- resolution
- aspect_ratio
Returns
Returns a job object with status , not the final output. Store the id from the response and poll the job until it completes.
Poll status
GET /v1/media/jobs/{request_id}
Request
curl https://api.dev.pika.art/v1/media/jobs/{request_id} \-H "X-API-Key: YOUR_API_KEY"
Response
{"id": "media_8f3a2c91-5b7d-4e0a-9c26-31d4f2a8e6b0","status": "running"}
Poll the job by id until it reaches a terminal state: completed or failed. A completed job carries its download URL in output, and GET /v1/media/jobs/{request_id}/content returns that same URL as { "url" } for clients that only kept the id.
DELETE /v1/media/jobs/{request_id} erases the stored media for a job, and the request captured at submit (the prompt and parameters). The job then reports deleted_at and no output, and the content endpoint answers 410.
The job object
Errors
shared across calls
Errors use conventional HTTP status codes with a JSON body of the shape {"message": "..."}. Validation failures return 422 with a message naming the offending field. Submit rejections after the job row exists (balance, rate limit) return the failed job envelope — branch on error.code.
| Status | When | Body |
|---|---|---|
| 401 Unauthorized | The API key is missing or invalid. | {"message":"Invalid API key"} |
| 403 Forbidden | An inactive key is rejected with a {"message"} body. A submit that the org balance or postpaid cycle limit cannot cover is rejected after the job row exists and returns the failed job envelope. GET /billing/balance separates the two: a 200 means the key is active, so the rejection was the balance or the cycle limit. | {"id":"media_8f3a2c91-5b7d-4e0a-9c26-31d4f2a8e6b0","status":"failed","error":{"code":"insufficient_balance","message":"Insufficient org balance"}} |
| 404 Not Found | No job with that id exists in your org, or the media path names an unknown vendor/model/function. | {"message":"media job not found"} |
| 409 Conflict | The result was requested before the job completed, or an Idempotency-Key header was reused with a different body. | {"message":"media job is not ready"} |
| 422 Unprocessable Entity | The request body failed validation: an invalid enum value, a missing required field, a wrong type, or malformed JSON. The JSON message names the offending field. A schema-valid parameter combination that cannot be priced instead fails after job creation and returns the failed job envelope with error code invalid_input. | {"message":"duration: Input should be less than or equal to 15"} |
| 429 Too Many Requests | You've hit your per-minute or per-day request limit, or your org's job queue is full. Returned as the failed job envelope. If there's a Retry-After header, wait that long, then retry with a fresh Idempotency-Key. | {"id":"media_8f3a2c91-5b7d-4e0a-9c26-31d4f2a8e6b0","status":"failed","error":{"code":"rate_limited","message":"rate limit exceeded: rpm"}} |
| 503 Service Unavailable | The model rail or a backend dependency is temporarily unavailable. Returned as the failed job envelope; retry with backoff and a fresh Idempotency-Key. | {"id":"media_8f3a2c91-5b7d-4e0a-9c26-31d4f2a8e6b0","status":"failed","error":{"code":"provider_unavailable","message":"media dispatch unavailable"}} |