How to Generate AI Videos with Python (Full Tutorial)
Published July 3, 2026 · 10 min read · By the VideoGenAPI team
In this tutorial you'll build a complete Python script that turns a text prompt into an AI-generated video using Sora 2, Kling 3 or any of the 15 models on VideoGenAPI. No ML infrastructure, no GPUs - just requests and an API key.
Prerequisites
- Python 3.8+
- The
requestslibrary:pip install requests - A VideoGenAPI API key - create a free account and generate one from your dashboard
Step 1 - Set up authentication
All requests use Bearer token authentication. Store your key in an environment variable, never in code:
import os
import time
import requests
API_KEY = os.environ["VIDEOGENAPI_KEY"]
BASE_URL = "https://videogenapi.com/api/v1"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
Step 2 - Send a generation request
Video generation is asynchronous: you submit a job and get back a generation_id immediately.
def generate_video(prompt: str, model: str = "sora-2", duration: int = 10) -> str:
"""Submit a generation job and return its generation_id."""
response = requests.post(
f"{BASE_URL}/generate",
headers=HEADERS,
json={
"model": model,
"prompt": prompt,
"duration": duration,
"resolution": "1080p",
"aspect_ratio": "16:9",
},
timeout=30,
)
response.raise_for_status()
data = response.json()
return data["generation_id"]
Want a different model? Just change the model parameter: "kling-3", "veo3", "grok-imagine-1-5", "seedance-2"... The model catalog lists every key with its capabilities and pricing.
Step 3 - Poll until the video is ready
Fast models finish in ~30 seconds; cinematic models like Sora 2 take 1-4 minutes. Poll with a reasonable interval and a timeout:
def wait_for_video(generation_id: str, timeout_s: int = 600) -> dict:
"""Poll the status endpoint until completion (or failure)."""
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
response = requests.get(
f"{BASE_URL}/status/{generation_id}",
headers=HEADERS,
timeout=30,
)
response.raise_for_status()
data = response.json()
status = data["status"]
if status == "completed":
return data
if status == "failed":
raise RuntimeError(f"Generation failed: {data.get('error', 'unknown error')}")
time.sleep(10) # be nice to the API
raise TimeoutError(f"Generation {generation_id} did not finish in {timeout_s}s")
Step 4 - Download the result
def download_video(video_url: str, filename: str = "output.mp4") -> None:
with requests.get(video_url, stream=True, timeout=120) as r:
r.raise_for_status()
with open(filename, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 20):
f.write(chunk)
if __name__ == "__main__":
gen_id = generate_video(
"A cinematic drone shot gliding over misty mountains at golden hour"
)
print(f"Job submitted: {gen_id}")
result = wait_for_video(gen_id)
print(f"Done in {result.get('processing_time', '?')}s")
download_video(result["video_url"])
print("Saved to output.mp4")
Ship AI video in your app today
One API key for Sora 2, Veo 3, Kling 3 and 12 more models. Flat plans from $29/mo.
Get your free API key →Production tips
- Use webhooks instead of polling for high volume - you'll receive a callback when the job completes. See the documentation.
- Handle rate limits: catch HTTP 429 and back off exponentially.
- Log the
generation_idwith every job so you can recover results after a crash viaGET /api/v1/generations. - Route by use case: fast models (Seedance 2, Grok Imagine) for previews, premium models (Sora 2, Veo 3) for final renders.
Complete script
The full example is ~60 lines and works with every model on the platform. Swap prompts, batch it with concurrent.futures, or wrap it in a FastAPI endpoint - the pattern stays the same: generate → poll → download.
Ready to try it? Create your free API key and generate your first video in the next five minutes.