Input fields
Every model reads the same field names, so a request keeps its shape when you change model. Send only the fields the model lists in its params (GET /v1/models/{id}): any other field is refused with 400, never silently dropped.
| Field | Type | Limits | What it is |
|---|---|---|---|
prompt | string | 20,000 characters | What to make. |
negative_prompt | string | 5,000 characters | What to avoid. |
images | array of files | 16 per call, or the model's max | Reference images. A first frame or main reference goes first. |
end_image | file | The last frame, for models that take one. | |
video | file | A reference or source clip. Its seconds are billed too, see Billing. | |
audio | file | A source sound (lip sync, speech to video). | |
duration | number | The model's min and max, or its values | Seconds of output. For lip sync and similar models, see Length from a file. |
resolution | string | The model's values | For example 720p or 2k. |
aspect_ratio | string | The model's values | For example 9:16, 1:1, 16:9. |
quality | string | The model's values | For example turbo or quality. |
generate_audio | boolean | Ask for sound where the model makes it. Selects the +audio price. | |
seed | integer | Repeatable results where the model supports it. | |
n | integer | 1 to 10, or the model's max | How many images. |
text | string | 20,000 characters | Text to speak, for voice models. |
voice | string | A voice id or name, for voice models. | |
extra | object | 8 KB as JSON | Model-specific options. Only the keys a model allows are used. |
Every model's page has an API reference for each task it does: the endpoint, a request for that model in cURL, Python and JavaScript, and this table filled in with the model's own fields and limits.
Options differ by model. Read a model's params (GET /v1/models/{id}) or open it on the models page: seedance-2.5, for example, lists resolution, duration with its min and max, aspect_ratio, up to 16 images and a reference video.
A file is a public https link, a link from Uploads, or a small base64 data URL. Values are matched without regard to letter case (720P reads as 720p). A field that changes the price and is left out gets the model's first allowed value, so the quote and the run always agree.
What a bad input answers
A request that breaks a model's params is refused before anything is held. The message names the field and says what is allowed.
| You sent | Answer |
|---|---|
| A field the model does not take | 400 invalid_input: "n is not an option of this model. It takes: resolution, prompt, images, ..." |
| A name that is not an input field | 400 invalid_request: "input: Unrecognized key: "colour"" |
A value outside values | 400 invalid_input: "resolution must be one of: 480p, 720p, 1080p." |
A duration outside min and max | 400 invalid_input: "duration must be between 4 and 30." |
| Too many images | 400 invalid_input: "This model takes at most 16 images." |
| A file that is not a link or data URL | 400 invalid_input: "images[0] must be an https URL or a base64 data URL (data:image/png;base64,...)." |
| A missing required field | 400 invalid_input: "prompt is required." |
| A combination with no price | 400 variant_unavailable: "... Priced options: 480p, 720p, 1080p." |
Length from a file
Some models take their length from an input: lip sync, speech to video, video upscales, video edits and motion control. Their catalogue entry lists duration_must_cover (for example ["video", "audio"]). You still send duration, and the generation is priced on it. It must be at least as long as the file, in whole seconds rounded up.
- A file longer than
durationfails the generation withinvalid_input. The message says thedurationto send. Nothing is charged. - A file longer than the model's
maxfails withinvalid_input, and the message says how long the model takes. - A clip that measures 5.02 seconds counts as 5: up to a tenth of a second over is forgiven.
Examples by kind
Each example is a request body for POST /v1/generations. Read the model's params first: options differ from model to model.
Text to video
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-text-to-video-$(uuidgen)" \
-d '{ "model": "seedance-2.5", "input": { "prompt": "A slow push-in on a perfume bottle on wet black stone", "resolution": "720p", "duration": 5, "aspect_ratio": "9:16" } }'Image to video, and first and last frame
images holds the first frame; end_image the last, on models that list it.
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-first-last-frame-$(uuidgen)" \
-d '{ "model": "kling-3.0", "input": { "prompt": "She smiles and lifts the cup", "images": ["https://example.com/start.jpg"], "end_image": "https://example.com/end.jpg", "resolution": "720p", "duration": 5 } }'Video with sound
generate_audio: true selects the +audio price on models that make sound.
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-video-with-sound-$(uuidgen)" \
-d '{ "model": "kling-3.0", "input": { "prompt": "Rain on a window, a soft piano", "resolution": "720p", "duration": 5, "generate_audio": true } }'Reference video
video is a clip to follow. Where the model lists a +video_input price, it applies, and the clip's seconds are billed at that rate.
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-reference-video-$(uuidgen)" \
-d '{ "model": "kling-4.0", "input": { "prompt": "Same camera move, a red sports car", "video": "https://example.com/reference.mp4", "resolution": "720p", "duration": 5 } }'Images: generate, several, edit
n is how many images; an edit sends the picture in images.
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-image-several-$(uuidgen)" \
-d '{ "model": "gpt-image-2", "input": { "prompt": "A red sneaker on white", "resolution": "1k", "aspect_ratio": "1:1", "n": 2 } }'curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-image-edit-$(uuidgen)" \
-d '{ "model": "gpt-image-2", "input": { "prompt": "Make the sneaker blue", "images": ["https://example.com/sneaker.jpg"], "resolution": "1k" } }'Voice-over
text is what to say; quality picks the price tier on models that have one. Priced by each started 1,000 characters.
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-voice-over-$(uuidgen)" \
-d '{ "model": "elevenlabs-tts", "input": { "text": "Fresh coffee, delivered before you wake up.", "quality": "turbo" } }'Music
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-music-$(uuidgen)" \
-d '{ "model": "flowmusic", "input": { "prompt": "A warm lo-fi beat with soft keys", "duration": 30 } }'Lip sync and talking avatars
These take their length from the files, so duration must cover them (see Length from a file).
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-lip-sync-$(uuidgen)" \
-d '{ "model": "bytedance-lipsync", "input": { "video": "https://example.com/face.mp4", "audio": "https://example.com/line.mp3", "duration": 9 } }'curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-avatar-$(uuidgen)" \
-d '{ "model": "kling-avatar-pro", "input": { "images": ["https://example.com/presenter.jpg"], "audio": "https://example.com/voiceover.mp3", "duration": 12 } }'Upscale
curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-upscale-video-$(uuidgen)" \
-d '{ "model": "topaz-video-upscale", "input": { "video": "https://example.com/clip.mp4", "resolution": "1080p", "duration": 8 } }'curl -s -X POST https://vidlab.ai/v1/generations \
-H "Authorization: Bearer $VIDLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: docs-upscale-image-$(uuidgen)" \
-d '{ "model": "topaz-image-upscale", "input": { "images": ["https://example.com/photo.jpg"], "resolution": "2k" } }'