Video Generation
Submit async video generation jobs via /v1/videos/generations and poll for completion. Routed through Together AI to Sora, Veo, Kling, Wan, Seedream, and Vidu.
Endpoints
POST /v1/videos/generations # submit job
GET /v1/videos/generations/{id} # poll status
Video generation is asynchronous. The submit call returns immediately with a job id and a poll_url; the client polls until status is completed (or failed).
Submit Request
| Field | Type | Default | Description |
|---|---|---|---|
model |
string | "auto" |
Video model (see Providers). Use "auto" for health-aware routing. |
prompt |
string | required | Text description. 1–8000 chars. |
duration_seconds |
number | provider default | 1–60 seconds. Most models cap at 4–10s on free tier. |
aspect_ratio |
string | "16:9" |
One of "16:9", "9:16", "1:1". |
image_url |
string | — | Public HTTPS image URL for image-to-video models (Wan 2.6, Wan 2.2 I2V). |
project_id |
string | — | Body-level project tag. Alternative to x-gateway-project-id header. |
Required Header
| Header | Required | Description |
|---|---|---|
Authorization: Bearer <GATEWAY_API_KEY> |
yes | Gateway API key. |
x-gateway-project-id |
yes (or body project_id) |
1–64 chars [a-zA-Z0-9._:-]. |
Providers
All video models currently route through Together AI (TOGETHER_API_KEY required).
| Model ID | Upstream Model | Capabilities |
|---|---|---|
sora-2 |
openai/sora-2 |
Text-to-video |
veo-3-audio |
google/veo-3.0-audio |
Text-to-video with audio |
veo-3-fast-audio |
google/veo-3.0-fast-audio |
Faster Veo 3 variant with audio |
veo-2 |
google/veo-2.0 |
Text-to-video |
kling-2.1-master |
kwaivgI/kling-2.1-master |
High-quality Kling |
kling-2.1-pro |
kwaivgI/kling-2.1-pro |
Kling pro tier |
kling-2.0-master |
kwaivgI/kling-2.0-master |
Previous-gen Kling |
kling-1.6-pro |
kwaivgI/kling-1.6-pro |
Kling 1.6 |
wan-2.6-image |
Wan-AI/Wan2.6-image |
Image-to-video |
wan-2.2-i2v |
Wan-AI/Wan2.2-I2V-A14B |
Image-to-video |
vidu-q1 |
vidu/vidu-q1 |
Text-to-video |
seedream-3 |
ByteDance-Seed/Seedream-3.0 |
ByteDance Seedream |
seedream-4 |
ByteDance-Seed/Seedream-4.0 |
ByteDance Seedream v4 |
Daily free-tier limits are tight (typically 10–30 requests per model per day). See GET /v1/models for the live enabled list.
Submit Response
Status 202 Accepted when the job is queued, or 200 OK if the provider happens to return a finished job synchronously.
{
"id": "job_abc123",
"status": "processing",
"poll_url": "/v1/videos/generations/job_abc123",
"x_gateway": {
"provider": "together",
"model": "openai/sora-2",
"attempts": 1,
"request_id": "req_xyz",
"project_id": "my_project"
}
}
Poll Response
{
"id": "job_abc123",
"status": "completed",
"video_url": "https://cdn.example/video.mp4",
"x_gateway": {
"provider": "together",
"model": "openai/sora-2",
"attempts": 1,
"request_id": "req_poll1",
"project_id": "my_project"
}
}
status is one of "processing", "completed", "failed". When failed, error contains the upstream message.
Examples
Submit
curl https://ai-gateway.sassmaker.com/v1/videos/generations \
-H "Authorization: Bearer <GATEWAY_API_KEY>" \
-H "x-gateway-project-id: my_project" \
-H "Content-Type: application/json" \
-d '{
"model": "sora-2",
"prompt": "A slow aerial drone shot over a misty mountain lake at dawn",
"duration_seconds": 5,
"aspect_ratio": "16:9"
}'const res = await fetch('https://ai-gateway.sassmaker.com/v1/videos/generations', {
method: 'POST',
headers: {
'Authorization': 'Bearer <GATEWAY_API_KEY>',
'x-gateway-project-id': 'my_project',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'sora-2',
prompt: 'A slow aerial drone shot over a misty mountain lake at dawn',
duration_seconds: 5,
aspect_ratio: '16:9',
}),
});
const job = await res.json();
console.log('Job ID:', job.id, 'Status:', job.status);Poll until complete
const BASE = 'https://ai-gateway.sassmaker.com';
async function pollUntilDone(jobId, { interval = 5000, timeout = 300_000 } = {}) {
const deadline = Date.now() + timeout;
while (Date.now() < deadline) {
const res = await fetch(`${BASE}/v1/videos/generations/${jobId}`, {
headers: { 'Authorization': 'Bearer <GATEWAY_API_KEY>' },
});
const body = await res.json();
if (body.status === 'completed') return body.video_url;
if (body.status === 'failed') throw new Error(body.error ?? 'job failed');
await new Promise((r) => setTimeout(r, interval));
}
throw new Error('poll timeout');
}
const videoUrl = await pollUntilDone('job_abc123');
console.log(videoUrl);
Image-to-video (Wan)
curl https://ai-gateway.sassmaker.com/v1/videos/generations \
-H "Authorization: Bearer <GATEWAY_API_KEY>" \
-H "x-gateway-project-id: my_project" \
-H "Content-Type: application/json" \
-d '{
"model": "wan-2.2-i2v",
"prompt": "Camera pans right as clouds roll in",
"image_url": "https://example.com/source-frame.jpg",
"duration_seconds": 4
}'
Error Codes
| Status | code |
Meaning |
|---|---|---|
| 400 | invalid_project_id |
Missing/invalid project_id. |
| 404 | — | Job ID unknown, or upstream poll endpoint returned 404 (see beta caveat above). |
| 502 | provider_error |
Submit or poll failed at upstream. |
| 503 | no_video_provider |
TOGETHER_API_KEY not configured. |