# Vivideo API (v1) — machine-readable summary for AI agents Base URL: https://api.vivideo.ai Human docs: https://developers.vivideo.ai OpenAPI spec: https://developers.vivideo.ai/openapi.yaml Get an API key (human step): https://app.vivideo.ai/account/api-keys (Settings → More → API Keys) ## Authentication Every endpoint except GET /v1 requires: Authorization: Bearer vv_live_... (or header X-API-Key) Keys are account-scoped secrets shown once at creation. 401 codes: missing_api_key, invalid_api_key, api_key_revoked. ## Core workflow (async video generation) 1. GET /v1/me → {plan, premium, credits, free_video_available, links} 2. POST /v1/videos (send Idempotency-Key header to make retries safe) Auto mode (AI avatar video, script+scenes+voiceover generated for you): {"mode":"auto","prompt":"...","duration_seconds":30, "avatar_id":"(optional, GET /v1/avatars)","voice_id":"(optional, GET /v1/voices)", "brand_kit_id":"(optional, GET /v1/brand-kits)","style_id":"(optional HeyGen template)", "file_asset_ids":["(optional HeyGen asset_ids from POST /v1/assets)"], "orientation":"landscape|portrait"} Cost: 3 credits per 5 seconds. Duration 5–300s. Manual mode (direct model access): {"mode":"manual","model":"veo31_fast","prompt":"...","duration_seconds":8, "resolution":"1080p","aspect_ratio":"16:9"} Operation inferred from inputs: image_url (→ image_to_video), first_frame_url+last_frame_url (→ first_last_frame), image_urls[] (→ multiple_images). Optional: negative_prompt, seed, generate_audio, style, movement_amplitude (vidu), cfg_scale (kling), camera_fixed, auto_fix, folder_id, name. GET /v1/models returns the FULL V2 catalog (32 models, e.g. veo31_fast, veo31, sora2, sora2_pro, kling_v3, kling25_turbo, wan26, seedance2, pixverse_v5, ltx2, luma_ray2, grok, hailuo23_pro, cogvideox, …) each with operations, resolutions, durations, aspect_ratios, credits_per_second, styles. resolution/duration_seconds/aspect_ratio/style are validated per-model (400 lists allowed values). credits_charged is authoritative. → 201 {"id","object":"video","status":"processing","credits_charged",...} 3. Poll GET /v1/videos/{id} every poll_interval_seconds (5s). status: queued | processing | completed | failed | preview completed → video_url (mp4), optional caption_url, video_url_no_captions, duration_seconds failed → error{message, credits_refunded:true}; manual renders include progress{queue_position,percent} 4. Or register a webhook instead of polling (see Webhooks). ## Free accounts (important for agent UX) Free accounts have ONE free video project. POST /v1/videos returns 201 with status:"preview": the project is prepared but NOT rendered; response includes preview.image_url (low-res — display blurred), preview.message and preview.upgrade_url = https://app.vivideo.ai/upgrade. Tell the user their preview is ready and give them the upgrade link. After they upgrade (existing Stripe flow in the app), call POST /v1/videos/{id}/render — the same project renders and the FIRST video is free (comped). Further free-account creations → 403 free_limit_reached (with links.upgrade). The allowance is per ACCOUNT and atomic: more keys / concurrent / repeated requests cannot bypass it. ## Other endpoints GET /v1/models — model list with operations, durations, resolutions, credit rates GET /v1/videos?folder_id&status&limit — list videos (newest first) POST /v1/videos/{id}/render — render a preview after upgrade (idempotent) GET /v1/avatars?view=characters|catalogue&search&gender&limit — stock catalogue + owned POST /v1/avatars — {"kind":"prompt"|"photo","name","prompt"|"file_url","consent":true(photo)}; async; poll GET /v1/avatars/{id} until ready GET /v1/voices?language&gender&search&limit — 100+ voices POST /v1/voices/speech — {"text"(≤300),"voice_id"} → {audio_url}; NO voice cloning via API GET /v1/brand-kits — list; POST /v1/brand-kits — create {name, colors, fonts, motion_style, brand_identity, logo_*} POST /v1/brand-kits/from-url — {"url":"https://..."} → unsaved draft kit extracted from the site GET /v1/folders — folders (projects containers) POST /v1/uploads — {"filename","content_type"} → {upload_url (presigned PUT), public_url}; PUT bytes, then use public_url as image_url/first_frame_url/file_url/logo_url POST /v1/assets — {"filename","content_type","size_bytes"} → {id (as_...), asset_id, upload_url, upload_headers}; PUT bytes then POST /v1/assets/{id}/complete; use asset_id as file_asset_ids / avatar asset_id / brand logo_asset_id GET/DELETE /v1/assets, POST /v1/assets/{id}/complete — manage HeyGen assets DELETE /v1/brand-kits/{id} — delete a brand kit GET/POST /v1/webhooks, DELETE /v1/webhooks/{id} — manage webhook endpoints (max 5, https-only public URLs) ## Webhooks Events: video.completed, video.failed. Delivery body: {"id":"evt_...","object":"event","type":"video.completed","created":,"data":{"video":{...}}} Signature header: Vivideo-Signature: t=,v1=hex(hmac_sha256(secret,".")) secret (whsec_...) is returned once at registration. Retries with backoff (1m,5m,30m,2h,6h); dedupe on event id. Respond 2xx fast. Dispatch latency up to ~60s after completion. ## Credits & premium Same balance as the app (no separate API credits). Rendering requires premium (pro/max plan). 402 insufficient_credits → links.buy_credits = https://app.vivideo.ai/subscription?context=insufficient_credits 403 upgrade_required / free_limit_reached → links.upgrade = https://app.vivideo.ai/upgrade Failed renders auto-refund. Charges are atomic (no double-spend from concurrent requests). ## Rate limits (per account unless noted) 120/min per key; 240/min per account; generation 6/min·60/h·200/day (premium) or 2/min·10/day (free); avatar-create/brand-from-url/speech 5/min·100/day; webhook writes 10/min. 429 rate_limited → honor Retry-After header / retry_after_seconds. ## Errors — single envelope {"error":{"code","message","retryable","request_id","details?","retry_after_seconds?","links":{...}}} Codes: invalid_request, unknown_model, invalid_url, missing_api_key, invalid_api_key, api_key_revoked, account_not_found, not_found, insufficient_credits, upgrade_required, free_limit_reached, rate_limited, duplicate_request, idempotency_in_flight, payload_too_large, webhook_limit_reached, upstream_error, internal_error. retryable:true → safe to retry (use backoff). Always keep request_id for support. ## Agent guidance - Always send Idempotency-Key on POST /v1/videos; on 409 duplicate_request reuse details.existing_video_id. - Check GET /v1/me before expensive calls; surface upgrade/buy-credit links to the human. - Poll at poll_interval_seconds; do not tight-loop. - Video generation takes minutes (manual: ~1–10 min; auto: ~2–10 min). Set user expectations.