Video Generation

Generate videos from a text prompt using the OpenAI Videos API format. Generation is asynchronous: create a job, poll it until it completes, then download the MP4. All three endpoints use the same API key as the chat endpoints.

Base URL: https://api.techopenclaw.com — authentication uses the same Authorization: Bearer toc-..... header as the chat endpoints (details in API Reference).

POST/v1/videosOpenAI

Create a video generation job — one request produces one video (there is no n/count parameter; send parallel requests for several clips). Returns immediately with the initial job status (usually queued).

FieldTypeRequiredDescription
modelstringYesVideo model name from the LLM Catalog. Replace seedance_2.5 in the examples with a video model available to your account.
promptstringYesText description of the video to generate.
secondsstringNoClip duration. Each model accepts its own set of values (see the model table below); an unsupported value returns 400 with the accepted list. Omitted = the model default.
sizestringNoOutput frame size, 720x1280 by default. Every model takes the four OpenAI sizes; the Seedance models also take four extra ratios — see the frame size table. Unsupported values return 400 with the accepted list.
aspect_ratiostringNoAlternative to size: a ratio like 16:9 is translated to its size. Unknown or blank values are ignored (the default size applies).
input_referencearray / fileNoReference images for the model (first frame, style frames, …). Multiple images are accepted — in JSON pass an array of { "image_url": "https://…" } objects (https or data URL), in multipart repeat the input_reference part once per image. Order is kept. Each model caps how many it takes (10 for Seedance, 3 for Veo and Omni) — more returns 400. An empty or missing field means text-to-video.
last_frameobjectNoEnd frame, as one { "image_url": … } object. Veo-3.1 only, and only together with exactly one input_reference image (the first frame).
input_videostringNoSource video URL (video-to-video), https only. Omni-Flash only; it also accepts up to 3 input_reference images alongside.
resolutionstringNo720p (default) or 1080p on Veo-3.1 (upscaled render). On models that do not offer it the value is ignored.
Request — JSON (two reference images)
curl https://api.techopenclaw.com/v1/videos \
  -H "Authorization: Bearer toc-....." \
  -H "Content-Type: application/json" \
  -d '{
  "model": "seedance_2.5",
  "prompt": "A slow dolly shot across a neon-lit city street at night",
  "seconds": "5",
  "size": "1280x720",
  "input_reference": [
    { "image_url": "https://example.com/first-frame.jpg" },
    { "image_url": "https://example.com/style-frame.jpg" }
  ]
}'
Request — multipart (upload reference images, repeat the part per image)
curl https://api.techopenclaw.com/v1/videos \
  -H "Authorization: Bearer toc-....." \
  -F model="Veo-3.1" \
  -F "prompt=A slow dolly shot across a neon-lit city street at night" \
  -F seconds="8" \
  -F size="1280x720" \
  -F [email protected] \
  -F [email protected]
Response — Video object
{
  "id": "video_abc123",
  "object": "video",
  "model": "seedance_2.5",
  "status": "queued",
  "progress": 0,
  "created_at": 1790567494,
  "completed_at": null,
  "expires_at": null,
  "prompt": "A slow dolly shot across a neon-lit city street at night",
  "size": "1280x720",
  "seconds": "5",
  "remixed_from_video_id": null,
  "error": null
}

Works with the OpenAI SDK by pointing base_url at Techopenclaw:

Request — Python (openai SDK)
from openai import OpenAI

client = OpenAI(api_key="toc-.....", base_url="https://api.techopenclaw.com/v1")

video = client.videos.create_and_poll(
    model="seedance_2.5",
    prompt="A slow dolly shot across a neon-lit city street at night",
    seconds="5",
    size="1280x720",
)

content = client.videos.download_content(video.id)
content.write_to_file("video.mp4")
GET/v1/videos/{video_id}OpenAI

Get the current state of a job. Poll this endpoint until status is completed or failed; sleep between rounds following the openai-poll-after-ms response header (milliseconds, default 10000). Typical completion time is 1–10 minutes.

Request — curl
curl https://api.techopenclaw.com/v1/videos/video_abc123 \
  -H "Authorization: Bearer toc-....."
Response — completed
{
  "id": "video_abc123",
  "object": "video",
  "model": "seedance_2.5",
  "status": "completed",
  "progress": 100,
  "created_at": 1790567494,
  "completed_at": 1790567670,
  "expires_at": null,
  "prompt": "A slow dolly shot across a neon-lit city street at night",
  "size": "1280x720",
  "seconds": "5",
  "remixed_from_video_id": null,
  "error": null
}
StatusMeaning
queuedJob accepted, waiting to start
in_progressRendering
completedDone — download via the content endpoint
failedJob failed — see the error field
GET/v1/videos/{video_id}/content?variant=videoOpenAI

Download the finished MP4. Only available while status is completed — earlier calls return 404 with a not-ready message. The response body is the raw video file (Content-Type: video/mp4), not JSON.

Request — curl
curl "https://api.techopenclaw.com/v1/videos/video_abc123/content?variant=video" \
  -H "Authorization: Bearer toc-....." \
  -o video.mp4

Models & limits

What each video model accepts — durations, frame ratios, how many reference images, and its extras:

ModelsecondsFrame ratiosMax input imagesExtras
seedance_2.0_fast5, 10, 15 (default 5)all six ratios10—
seedance_2.55–30 (default 5)all six ratios10—
Veo-3.14, 6, 8 (default 8)9:16, 16:93last_frame, resolution 1080p
Omni-Flash109:16, 16:93input_video (video-to-video)

Frame sizes and their ratios (the Seedance models take all eight; Veo and Omni take the first four):

sizeRatioModels
720x12809:16 (default)all
1280x72016:9all
1024x17929:16all
1792x102416:9all
1024x10241:1Seedance only
768x10243:4Seedance only
1024x7684:3Seedance only
1680x72021:9Seedance only

Billing

Video is priced per second: price = the model's credits-per-second rate × the requested seconds. Rates per model are shown in the Pricing Policy. Before a job starts, your available balance must cover its price plus the price of all your unfinished jobs.

OutcomeBilling
completedCharged in full: credits-per-second of the model × seconds
failed — prompt blocked by content moderationCharged in full (the video was already rendered when the prompt was rejected)
failed — system error, never started, or timed outNot charged

Error Codes

CodeMeaningAction
400Malformed request, seconds/size not supported by the model, or more input_reference images than the model takesRead error.message — it lists the accepted values
401Invalid or missing API keyCheck your toc- key
402Not enough credits for the requested durationTop up or shorten the clip. Unfinished jobs count toward your available balance
404Unknown video id, or the video belongs to a different API keyVerify the id and the key used to create the job
429Service is busy right nowRetry after the seconds given in Retry-After
502Submission outcome unknown (possible duplicate job)If x-should-retry: false is present, do NOT retry automatically — check by video id first
503Model temporarily unavailable or no capacityRetry shortly
Support · Telegram