API generate video: the full request and response, end to end
The request
curl -X POST https://genace.ai/api/v1/video/generations \
-H "Authorization: Bearer $GENACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0-fast",
"prompt": "a cyclist on a coastal road at golden hour, camera tracking alongside",
"duration_sec": 3
}'
Both snake_case and camelCase are accepted for field names.
The response is a job
{
"job_id": "abc123",
"state": "queued",
"model": "seedance-2.0-fast",
"credits_held": 25
}
202 Accepted. The render takes minutes; credits_held is what was reserved
and comes back in full if the job fails or you cancel it.
Collecting the output
curl "https://genace.ai/api/v1/jobs/abc123?wait=30" \
-H "Authorization: Bearer $GENACE_API_KEY"
On success:
{
"job_id": "abc123",
"state": "succeeded",
"outputs": [{ "url": "https://...", "type": "video" }]
}
The two that surprise people
A failed job is a 200. It describes a failure in the body, so
raise_for_status() and equivalents will not fire. Check state.
Both 429s need opposite handling. Rate limiting clears with time;
concurrency clears only when one of your own jobs finishes. Retrying blindly
helps in one case and spins in the other. Branch on error.code.
Choosing a model
| Model | Credits per clip | Duration | Resolution |
|---|---|---|---|
| Seedance | 25 | 3–15s | 720p, 1080p |
| Kling | 35 | 5 or 10s | 1080p |
| Veo 3 | 100 | 8s fixed | 720p, 1080p |
Duration control usually decides this more than price does — AI video API duration limits.
A working Python implementation with the polling loop is in how to generate video with an API in Python.
Continue with api fundamentals
Models covered on this page
Where these facts come from
- codebase: src/ai/providers/*.ts — every pricing() and paramsSchema
- codebase: src/ai/api/quota.ts — per-tier ceilings
- codebase: src/app/api/v1/video/generations/route.ts — request and response shape