Skip to main content
Video generation is async. Submit a job, save queue_id, then poll /video/retrieve until the response is video/mp4.

Endpoints

EndpointPurposeRequired
POST /video/quoteGet price in USD before generatingNo
POST /video/queueSubmit generation requestYes
POST /video/retrievePoll status or download videoYes
POST /video/completeDelete video from storageNo

Step 1: Queue Generation

Request:
POST https://api.venice.ai/api/v1/video/queue
Authorization: Bearer $VENICE_API_KEY
Content-Type: application/json

{
  "model": "wan-2.5-preview-text-to-video",
  "prompt": "A gondola gliding through Venice canals at sunset",
  "duration": "5s",
  "resolution": "720p",
  "aspect_ratio": "16:9"
}
Response (200):
{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000"
}
For Grok Imagine Private models, the queue response includes an extra download_url field:
{
  "model": "grok-imagine-text-to-video-private",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000",
  "download_url": "https://private-share.venice.ai/v1/share/read/..."
}
download_url is a pre-signed URL you use to download the finished video instead of reading it from the retrieve response. It is only returned once, so persist it alongside queue_id. This applies to all four Grok Imagine Private variants:
  • grok-imagine-text-to-video-private
  • grok-imagine-image-to-video-private
  • grok-imagine-reference-to-video-private
  • grok-imagine-video-to-video-private
Unlike the public grok-imagine-*-video variants, Grok Imagine Private models are not billed for content-moderation rejections, so you only pay for successful generations. Save model, queue_id, and download_url (if present) for all subsequent calls.

Step 2: Poll for Completion

Request:
POST https://api.venice.ai/api/v1/video/retrieve
Authorization: Bearer $VENICE_API_KEY
Content-Type: application/json

{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000"
}
Response depends on status:
Content-TypeMeaningAction
application/jsonStill processingWait 5s, poll again
video/mp4CompleteResponse body is the video file
application/json with "COMPLETED"Complete, video not inlineGET the download_url from the queue response
Processing response (200, application/json):
{
  "status": "PROCESSING",
  "average_execution_time": 145000,
  "execution_duration": 53200
}
Times are in milliseconds. Use average_execution_time to estimate remaining wait. Complete response (200, video/mp4): Response body is raw binary video data. Save to file. Complete response (200, application/json with "COMPLETED"): For models that returned a download_url at queue time, retrieve always returns JSON. Fetch the video with GET download_url. The URL is pre-signed (no auth header needed) and valid for 24 hours.

Step 3: Cleanup (Optional)

Either auto-delete on retrieval:
{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000",
  "delete_media_on_completion": true
}
Or call /video/complete after saving:
POST https://api.venice.ai/api/v1/video/complete
Authorization: Bearer $VENICE_API_KEY
Content-Type: application/json

{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000"
}
Response (200):
{
  "success": true
}

Complete Example

import os
import time
import requests

API_KEY = os.environ.get("VENICE_API_KEY")
BASE_URL = "https://api.venice.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

# Queue
resp = requests.post(f"{BASE_URL}/video/queue", headers=HEADERS, json={
    "model": "wan-2.5-preview-text-to-video",
    "prompt": "A gondola gliding through Venice canals at sunset",
    "duration": "5s",
    "resolution": "720p",
    "aspect_ratio": "16:9"
})
data = resp.json()
model, queue_id = data["model"], data["queue_id"]
download_url = data.get("download_url")

# Poll
while True:
    resp = requests.post(f"{BASE_URL}/video/retrieve", headers=HEADERS,
                         json={"model": model, "queue_id": queue_id})
    if "video/mp4" in resp.headers.get("Content-Type", ""):
        with open("output.mp4", "wb") as f:
            f.write(resp.content)
        break
    if resp.json().get("status") == "COMPLETED" and download_url:
        with open("output.mp4", "wb") as f:
            f.write(requests.get(download_url).content)
        break
    time.sleep(5)

# Cleanup
requests.post(f"{BASE_URL}/video/complete", headers=HEADERS,
              json={"model": model, "queue_id": queue_id})

Request Parameters

Queue Request

ParameterTypeRequiredDefaultDescription
modelstringYes-Model ID. Use wan-2.5-preview-text-to-video for text-to-video, wan-2.5-preview-image-to-video for image-to-video
promptstringYes-What to generate. Max 2500 chars
negative_promptstringNo"low resolution, error, worst quality, low quality, defects"What to avoid
durationstringYes-"5s" or "10s"
resolutionstringNo"720p""480p", "720p", or "1080p"
aspect_ratiostringConditional-Model-dependent. Required for models that expose aspect-ratio options; omit for models that do not support aspect-ratio selection
audiobooleanConditionaltrue (when supported)Only valid for models with supportsAudioConfig: true; omit for models without audio config support
image_urlstringOnly for image-to-video-URL or base64 data URL of source image
audio_urlstringConditional-URL or base64 data URL of reference audio for models that support audio input
Queue validation is model-specific. Check /models?type=video for each model’s supported request fields before calling /video/queue.

Quote Request

ParameterTypeRequiredDefaultDescription
modelstringYes-Model ID to price
durationstringYes-"5s" or "10s"
resolutionstringNo"720p""480p", "720p", or "1080p"
aspect_ratiostringConditional-Include when the selected model supports or requires aspect-ratio selection
audiobooleanConditionaltrue (when supported)Only valid for models with supportsAudioConfig: true

Retrieve Request

ParameterTypeRequiredDefaultDescription
modelstringYes-From queue response
queue_idstringYes-From queue response
delete_media_on_completionbooleanNofalseDelete video after successful retrieval

Complete Request

ParameterTypeRequiredDescription
modelstringYesFrom queue response
queue_idstringYesFrom queue response

Image to Video

For image-to-video models, pass source image via image_url. The prompt describes desired motion, not the image content.
{
  "model": "wan-2.5-preview-image-to-video",
  "prompt": "Camera slowly zooms in as leaves rustle in the wind",
  "image_url": "https://example.com/image.jpg",
  "duration": "5s"
}
Or with base64:
{
  "model": "wan-2.5-preview-image-to-video",
  "prompt": "Camera slowly zooms in as leaves rustle in the wind",
  "image_url": "data:image/jpeg;base64,/9j/4AAQ...",
  "duration": "5s"
}

Price Quote

Get exact cost before generating. Send only pricing inputs (model, duration, and optional resolution, aspect_ratio, audio): Request:
{
  "model": "wan-2.5-preview-text-to-video",
  "duration": "10s",
  "resolution": "1080p"
}
Response:
{
  "quote": 0.085
}
Quote is in USD.

Errors

StatusReturned ByMeaningAction
400queue, quote, retrieve, completeInvalid parametersCheck request body against schema
401queue, retrieve, completeAuth failedCheck API key
402queueInsufficient balanceAdd funds
404retrieve, download_urlMedia not found (invalid, expired, or deleted)Verify model/queue_id or re-queue
410download_urlPre-signed URL expired (>24h)Re-queue the generation
413queuePayload too largeReduce image/audio size
422queue, retrieveContent violationModify prompt
500queue, retrieve, completeInference/processing failedRetry with backoff; contact support if persistent
503retrieveModel at capacityRetry with backoff

Polling Strategy

  1. Poll /video/retrieve on an interval (for example, every 5 seconds)
  2. If Content-Type is application/json and status is "PROCESSING", wait and poll again. Use average_execution_time and execution_duration (milliseconds) to estimate remaining time
  3. If Content-Type is video/mp4, save the response body as your output file
  4. If Content-Type is application/json and status is "COMPLETED", GET the download_url from the queue response to fetch the video
  5. Optional cleanup: set delete_media_on_completion: true on retrieve, or call /video/complete after download
  6. Handle 404 as invalid, expired, or deleted media; handle 500/503 with retries/backoff

Available Models

See Video Models for current model list and pricing.