Complete Video API Standard
Unified cnAPI video generation standard covering references, keyframes, callbacks, polling, downloads, and errors.
This is the customer-facing standard for asynchronous video generation through cnAPI. Always use the public cnAPI model name and the public task id returned by the API.
All current public video models share the create, polling/webhook, and download lifecycle. Reference-media fields are model-family specific, however; do not apply one family's media example to every model.
Endpoints
| Purpose | Method and path |
|---|---|
| Create a video | POST https://cnapi.vip/v1/videos |
| Retrieve task status | GET https://cnapi.vip/v1/videos/{id} |
| Download the result | GET https://cnapi.vip/v1/videos/{id}/content |
| Receive a terminal callback | Set callback_url in the create request |
Authorization: Bearer sk-your-api-key
Content-Type: application/json
Accept: application/jsonKeep API keys on your server. Never embed them in browser, mobile, or desktop client code.
Basic text-to-video request
curl --request POST 'https://cnapi.vip/v1/videos' \
--header 'Authorization: Bearer sk-xxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"model": "SD2.5 720P",
"prompt": "A silver sports car driving through a neon city at night, cinematic tracking shot",
"duration": 8,
"size": "16:9"
}'You may use an integer duration or a string seconds, for example "8".
Common request fields
| Field | Type | Required | Description |
|---|---|---|---|
model | string | yes | Exact public model name shown by cnAPI |
prompt | string | conditional | Prompt; only selected reference-capable models allow it to be empty |
negative_prompt | string | no | Negative prompt for multi-reference models; Veo uses metadata.negativePrompt |
duration | integer | no | Duration in seconds; mutually exclusive with seconds |
seconds | string | no | Duration as a string |
size | string | no | Aspect ratio or size, such as 16:9 or 1280x720 |
image | string | no | One reference image URL |
images | string[] | no | Reference image URLs; recommended image form |
video / videos | string / string[] | no | Gemini Omni requires these top-level fields; multi-reference families use metadata.referenceVideos |
seed | integer | no | Random seed |
generate_audio | boolean | no | Generate audio on models that explicitly support it |
camera_control | object | no | Model-specific camera control |
callback_url | string | no | Terminal webhook URL |
metadata | object | no | Video/audio references, keyframes, and other extensions |
Output resolution is fixed by the public model name. Do not attempt to change a model tier by overriding resolution.
Reference media
Reference images
Use the top-level images array for consistent behavior across current models:
{
"model": "SD2.5 720P",
"prompt": "Keep the same character identity and clothes, walking by the sea",
"duration": 10,
"size": "16:9",
"images": [
"https://cdn.example.com/character-front.jpg",
"https://cdn.example.com/character-side.jpg"
]
}Reference videos and audio for multi-reference models
For the SD, Seedance, H3, Wan, and Kling families that support multiple references, put video and audio references in metadata:
{
"model": "SD2.5 720P",
"prompt": "Use the product appearance, camera motion, and sound rhythm from the references",
"duration": 12,
"size": "16:9",
"images": ["https://cdn.example.com/product.jpg"],
"metadata": {
"referenceVideos": [
"https://cdn.example.com/camera-motion.mp4"
],
"referenceAudios": [
"https://cdn.example.com/sound-reference.mp3"
]
}
}Do not submit multiple aliases for the same media type. For example, do not send both top-level images and metadata.referenceImages; compatibility aliases are selected, not guaranteed to be merged.
For minimax-h3-768p, an audio reference requires at least one image, video, or first frame.
First and last frames
{
"model": "Seedance-2.5-720p官方版",
"prompt": "Smoothly transition from the morning frame to the night frame",
"duration": 10,
"size": "16:9",
"metadata": {
"firstFrame": "https://cdn.example.com/start.jpg",
"lastFrame": "https://cdn.example.com/end.jpg"
}
}lastFrame requires firstFrame. For models marked as exclusive below, keyframes cannot be mixed with ordinary image, video, or audio references.
Media URL requirements
- Prefer directly downloadable public HTTPS URLs.
- URLs must not require cookies, login state, Referer, or custom headers.
- Do not use localhost, private IPs, container hostnames, or intranet-only URLs.
- Keep URLs valid for at least 60 minutes after task creation.
- Recommended formats: JPG/PNG/WebP, MP4/MOV, and MP3/WAV.
- Keep each reference video below 50 MB and each reference audio file below 15 MB when possible.
- Only submit material you are authorized to use.
Current public model capabilities
Veo
The two public Veo models support 4/6/8 seconds and 720P/1080P. They accept text or one input image, but not reference video or reference audio. Use metadata.negativePrompt, metadata.seed, and metadata.generateAudio for Veo-specific controls.
{
"model": "veo-3.1-fast",
"prompt": "Keep the subject from the reference image and slowly push the camera forward",
"duration": 8,
"size": "1920x1080",
"images": ["https://cdn.example.com/reference.jpg"],
"metadata": {
"negativePrompt": "blur, distortion",
"generateAudio": true
}
}Grok video
Grok video accepts text or one input image. It does not accept multiple images, reference video, or reference audio. Set 480P/720P with metadata.resolution; the -1080p model is fixed at 1080P.
{
"model": "grok-imagine-video-1.5",
"prompt": "Keep the subject and slowly pull the camera back",
"duration": 8,
"size": "16:9",
"images": ["https://cdn.example.com/start.jpg"],
"metadata": { "resolution": "720p" }
}Gemini Omni video
gemini-omni-flash outputs 720P and accepts up to ten images or one reference video. Its reference video must use top-level video/videos, not metadata.referenceVideos. The video must be MP4/MOV, no longer than ten seconds, and no larger than 64 MiB.
{
"model": "gemini-omni-flash",
"prompt": "Use the motion from the video and the product from the image",
"duration": 6,
"size": "16:9",
"images": ["https://cdn.example.com/product.jpg"],
"video": "https://cdn.example.com/reference.mp4"
}| Public model | Duration | Ratios | Output | Image/video/audio limits | Keyframes | Audio control |
|---|---|---|---|---|---|---|
veo-3.1-fast | 4/6/8s | 16:9, 9:16 | 720P/1080P | 1 / 0 / 0 | no | native audio; metadata.generateAudio |
veo-3.1 | 4/6/8s | 16:9, 9:16 | 720P/1080P | 1 / 0 / 0 | no | native audio; metadata.generateAudio |
grok-imagine-video | 1–15s | 16:9, 9:16, 1:1, 4:3, 3:4, 3:2, 2:3 | 480P/720P | 1 / 0 / 0 | no | no |
grok-imagine-video-1.5 | 1–15s | same as above | 480P/720P | 1 / 0 / 0 | no | no |
grok-imagine-video-1.5-1080p | 1–15s | same as above | 1080P | 1 / 0 / 0 | no | no |
gemini-omni-flash | 3–10s | 16:9, 9:16 | 720P | 10 / 1 / 0 | no | no |
SD2.5 720P | 4–30s | auto, 1:1, 21:9, 16:9, 9:16, 3:4, 4:3 | 720P | 30 / 10 / 10 | yes, exclusive | generate_audio |
SD2.5 480P | 4–30s | auto, 1:1, 21:9, 16:9, 9:16, 3:4, 4:3 | 480P | 30 / 10 / 10 | yes, exclusive | generate_audio |
SD2.0 720P | 4–15s | 1:1, 21:9, 16:9, 9:16, 3:4, 4:3 | 720P | 9 / 3 / 3; 12 total | yes, exclusive | not configurable |
minimax-h3-768p | 4–15s | 1:1, 16:9, 9:16 | 768P | 10 / 5 / 5 | yes | not configurable |
Seedance-2.5-720p官方版 | 4–30s | 16:9, 9:16, 1:1, 4:3, 3:4, 21:9 | 720P | 30 / 10 / 10 | yes, exclusive | not configurable |
Seedance-2.0-720p官方版 | 4–15s | same as above | 720P | 9 / 3 / 3 | yes, exclusive | not configurable |
Seedance-2.0-fast-720p官方版 | 4–15s | same as above | 720P | 9 / 3 / 3 | yes, exclusive | not configurable |
seedance-2.0-mini-480p | 4–15s | same as above | 480P | 9 / 3 / 3 | not published; omit | not configurable |
seedance-2.0-mini-720p | 4–15s | same as above | 720P | 9 / 3 / 3 | not published; omit | not configurable |
wan3.0-video-720p | 4–30s | 16:9, 9:16, 1:1, 4:3, 3:4 | 720P | 10 / 5 / 5 | yes, exclusive | not configurable |
wan3.0-video-1080p | 4–30s | same as above | 1080P | 10 / 5 / 5 | yes, exclusive | not configurable |
kling-3.0-turbo-720p | 4–15s | 16:9, 9:16, 1:1 | 720P | 30 / 10 / 0 | yes | generate_audio |
kling-3.0-turbo-1080p | 4–15s | same as above | 1080P | 30 / 10 / 0 | yes | generate_audio |
kling-3.0-turbo-2k | 4–15s | same as above | 2K | 30 / 10 / 0 | yes | generate_audio |
kling-3.0-turbo-4k | 4–15s | same as above | 4K | 30 / 10 / 0 | yes | generate_audio |
Available models and account access may change. Use the live model list for discovery.
Model-specific rules: Veo, Grok, and Gemini Omni must use their family examples above rather than the multi-reference fields; SD2.0 720P allows at most 12 ordinary references in total; minimax-h3-768p requires a visual reference when reference audio is present; wan3.0-video-* can omit the prompt when media is supplied, although a prompt is still recommended; and kling-3.0-turbo-* does not accept reference audio but does support generate_audio. Resolution suffixes are part of the exact model name and must not be removed.
Create response
{
"id": "task_xxxxxxxxxxxxxxxxxxxxxxxx",
"task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxx",
"object": "video",
"model": "SD2.5 720P",
"status": "queued",
"progress": 0,
"created_at": 1788249600
}Save id. task_id is retained for legacy compatibility. HTTP 200 means the task was accepted, not that generation has finished.
Polling
curl 'https://cnapi.vip/v1/videos/task_xxx' \
--header 'Authorization: Bearer sk-xxxx'| Status | Meaning | Action |
|---|---|---|
queued | waiting | keep waiting |
in_progress | generating | keep waiting |
completed | finished | call the /content endpoint |
failed | failed | inspect error.code and error.message |
unknown | unknown | retry briefly, then contact support if persistent |
Wait 3–5 seconds before the first query, poll every 10–15 seconds, and use a total timeout of at least 30 minutes. Do not submit a duplicate while the original task is still active.
Webhooks
Set a public callback_url in the create request. It must be no longer than 2048 characters, must not target localhost or private networks, and should return a 2xx response within 15 seconds.
Terminal events are video.completed and video.failed:
{
"id": "evt_task_xxx_completed",
"type": "video.completed",
"created_at": 1788250200,
"data": {
"task_id": "task_xxx",
"model": "SD2.5 720P",
"status": "completed",
"progress": "100%",
"output_url": "https://cnapi.vip/v1/videos/task_xxx/content",
"created_at": 1788249600,
"completed_at": 1788250200
}
}Relevant headers:
X-NewAPI-Event: video.completed
X-NewAPI-Delivery: evt_task_xxx_completed
X-NewAPI-Timestamp: 1788250200
X-NewAPI-Signature: sha256=<hex-hmac>Verify HMAC-SHA256 over:
X-NewAPI-Timestamp + "." + raw request body bytesUse the full API key, including the sk- prefix, as the HMAC secret. Compare signatures in constant time and deduplicate deliveries using X-NewAPI-Delivery or the event id.
Reject callbacks whose timestamp differs from your server time by more than five minutes to reduce replay risk.
Failed deliveries use exponential backoff. Each attempt has a 15-second timeout; delivery is attempted up to eight times, with a maximum backoff of 15 minutes. Polling may be used as a fallback alongside webhooks.
Downloading the result
After status=completed:
curl --location \
'https://cnapi.vip/v1/videos/task_xxx/content' \
--header 'Authorization: Bearer sk-xxxx' \
--output result.mp4Clients must follow HTTP redirects. Copy completed assets to your own object storage if you need permanent retention.
Treat webhook output_url as opaque and potentially temporary. Do not parse or depend on its hostname or path layout.
Retry and error rules
- 400: invalid model, duration, ratio, field placement, or reference count.
- 401: missing or invalid API key.
- 403: the key cannot access the model or group.
- 404: task not found, not owned by the account, or content not ready.
- 429: apply
Retry-Afteror exponential backoff. - 5xx: status queries may be retried with backoff.
status=failed: the HTTP query succeeded but generation failed; inspecterror.message.
POST /v1/videos does not currently guarantee customer-provided idempotency keys. If a fully transmitted create request ends with an ambiguous network timeout, do not blindly resubmit it because duplicate tasks may be generated and billed.
How is this guide?