Video
Video generation is asynchronous — you submit a job, then poll for the result. Renders take 30 seconds to several minutes depending on the model and length.
Two flavors of model
The catalog has two kinds of video model, each with a slightly different request shape:
- Text-to-video — pass a
prompt. Used for everything in the standard catalog (veo3,kling-2.1-pro,runway-gen4, etc.). - Image-to-video — pass a
promptAND animage_url(a publicly fetchable URL). Used by models with the-i2vsuffix.
The endpoint URL is the same; only the body differs.
Submit a job
/v1/videosauth · sk-echoSubmit a render. Returns 202 with a job id; poll /v1/videos/{id} for the result.
import requests
resp = requests.post(
"https://api.echotokens.me/v1/videos",
headers={"Authorization": "Bearer sk-echo-..."},
json={
"model": "kling-2.5-turbo",
"prompt": "A slow drone shot over an alpine meadow at golden hour.",
"aspect_ratio": "16:9",
"duration": "5",
},
)
job = resp.json()
print(job["id"], job.get("status"))Parameters
- parameter
modeltypestringrequiredrequiredVideo model id — see the catalog below. - parameter
prompttypestringrequiredrequiredDescription of the desired video. - parameter
image_urltypestring (URL)requiredoptionalRequired for image-to-video models (-i2v). Must be a publicly fetchable URL. - parameter
aspect_ratiotypestringrequiredoptional16:9, 9:16, or 1:1.default:16:9 - parameter
durationtypestring (seconds)requiredoptionalModel-dependent. Most models accept "5" or "10". - parameter
qualitytypestringrequiredoptionalModel-dependent. e.g. 720p, 1080p (only some models support a quality switch).
Response
{
"id": "vid_01J...",
"status": "queued"
}Poll for the result
/v1/videos/{id}auth · sk-echoReturns the job's current state. Once status is ready, the result_url is a signed link valid for 24 hours.
import time, requests
while True:
r = requests.get(
f"https://api.echotokens.me/v1/videos/{job_id}",
headers={"Authorization": "Bearer sk-echo-..."},
)
status = r.json()
if status["status"] in ("ready", "failed"):
break
time.sleep(5)
if status["status"] == "ready":
print(status["result"]["url"])
print("Cost:", status.get("cost_usd_cents")){
"id": "vid_01J...",
"status": "ready",
"result": {
"url": "https://api.echotokens.me/v1/assets/eyJ1Ij...",
"duration_seconds": 5
},
"cost_usd_cents": 38
}The portal's Generations history shows clips submitted weeks ago — we re-mint the signed URL with a fresh 24-hour TTL every time you fetch a job from /account/jobs/videos. From your code, just hold the most recent response for that job; the URL inside is good for another 24h from the time you got it.
Image-to-video
The -i2v model family requires an image_url field. The URL must be publicly fetchable — the upstream side-fetches the bytes. If your image isn't already on a public host, use the portal's video studio which uploads attachments to a short-lived signed URL on our host first.
resp = requests.post(
"https://api.echotokens.me/v1/videos",
headers={"Authorization": "Bearer sk-echo-..."},
json={
"model": "kling-2.5-turbo-i2v",
"prompt": "The character turns and smiles, soft window light.",
"image_url": "https://cdn.example.com/hero.png",
"duration": "5",
},
)Model catalog
The live per-model pricing is on the pricing page — it's the source of truth and updates as we ship new models.
catalog auto-syncs from the upstream every 6h · canonical pricing at /pricing
A frontier text-to-video clip can run $0.10 – $2 depending on resolution and length. Check cost_usd_cents on the polled job before scaling out a batch. The usage page shows historical per-request cost.
Submit jobs, attach images for i2v models, and watch them render — including for-you reactions and re-submits — without writing the polling loop yourself.