# AIVeed API — complete reference for LLMs # Generated from the model registry, the live pricing snapshot (version f7f3bc8cb07b66f22ecb94b3db1eb1bd6e3ee612409061e4f608765e6ead9c26), the OpenAPI # builder, and the error registry. Human docs: https://developer.aiveed.io/docs # Machine endpoints (public, no auth): GET https://api.aiveed.io/v1/models · GET https://api.aiveed.io/v1/credits/pricing # OpenAPI 3.1: GET https://api.aiveed.io/v1/openapi.json (error table in x-error-codes) ## What this is Job-based REST API for AI generation: submit a job (video/image/audio), get charged in credits up front (automatically refunded if the provider fails), then poll / stream / receive a webhook; completed jobs carry a hosted result_url. Base URL: https://api.aiveed.io/v1 ## Authentication Create a key on the dashboard: https://developer.aiveed.io/signup?return=/developer/keys (verified email required; max 5 active keys; rotation and revocation on the dashboard or via /v1/auth/keys with a session JWT). Send it as `X-API-Key: aiv_sk_...` or `Authorization: Bearer aiv_sk_...`. Never in the query string. Scopes: generate (job creation, uploads, webhooks) and read (jobs, credits, usage, SSE). Key management is session-JWT-only — an API key cannot mint keys. ## Endpoints GET /v1/health — Health check (public) GET /v1/models — Available models with pricing and capabilities (public) POST /v1/auth/keys — Create API key GET /v1/auth/keys — List API keys POST /v1/auth/keys/{keyId}/rotate — Rotate an API key DELETE /v1/auth/keys/{keyId} — Revoke an API key GET /v1/auth/me — Current user info POST /v1/generate/video — Generate a video POST /v1/generate/image — Generate or edit an image POST /v1/generate/audio — Generate audio (voiceover or music) POST /v1/extend/video — Extend a completed Veo3 video (~7s) POST /v1/batch — Submit multiple jobs (up to 10, submitted sequentially) GET /v1/jobs — List jobs GET /v1/jobs/{id} — Get job status DELETE /v1/jobs/{id} — Cancel a queued job GET /v1/videos — List your generated videos GET /v1/images — List your generated images GET /v1/assets — List your Gemini Omni characters and voices GET /v1/credits — Credit balance GET /v1/credits/pricing — Full pricing table (public) (public) GET /v1/usage/summary — Usage summary (requests, net credit spend, jobs by status/model, daily series) GET /v1/usage/limits — Effective tier, rate limit, concurrency cap, and account caps POST /v1/webhooks — Register webhook URL (max 5 active per account) GET /v1/webhooks — List webhooks DELETE /v1/webhooks/{id} — Delete a webhook POST /v1/sse/tickets — Mint a short-lived SSE ticket GET /v1/sse/jobs/{id} — SSE stream for job progress POST /v1/uploads — Upload media for use as a generation input GET /v1/openapi.json — This spec (public) GET /v1/docs — Interactive API reference (Scalar UI) (public) ## Typical flow 1. POST /v1/generate/video {"model": "seedance-v1-pro", "prompt": "...", "resolution": "480p", "duration": "5"} -> 201 {"id": "job_...", "status": "submitted", "credits_charged": 30, "remaining_credits": ...} 2. GET /v1/jobs/{id} until status == "completed" (statuses: queued|submitted|processing|completed|failed|cancelled) -> {"status": "completed", "result_url": "https://...", ...} Send an Idempotency-Key header (1-200 chars of A-Za-z0-9_.-) on every job-creating request: a retry with the same key replays the ORIGINAL job (HTTP 200, replayed: true) instead of charging again. GET /v1/jobs lists jobs (filters: status, model, type=video|image|extend|audio). ## Media library GET /v1/videos and GET /v1/images list the account's successfully generated media — platform-created and API-created — newest first (filters: model, limit<=100, offset; images also favorite=true). These return durable hosted URLs (video_url is the permanent MP4; image_url is permanent) — a video job's result_url can be a transient provider URL, so use /v1/videos as the durable source. ## Models ### veo3-fast (Veo3 Fast) — video, provider google - options: aspect_ratio: 16:9|9:16; duration: fixed ~8s (do NOT send duration) - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), last_frame_url (requires first_frame_url) - NOT supported (422 UNSUPPORTED_OPTION): resolution - prompt cap: 10000 chars - extendable: POST /v1/extend/video (~7s more) - credits: 120 per ~8s video ### veo3-quality (Veo3 Quality) — video, provider google - options: aspect_ratio: 16:9|9:16; duration: fixed ~8s (do NOT send duration) - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), last_frame_url (requires first_frame_url) - NOT supported (422 UNSUPPORTED_OPTION): resolution - prompt cap: 10000 chars - extendable: POST /v1/extend/video (~7s more) - credits: 320 per ~8s video ### grok-video (Grok Imagine Video) — video, provider xai - options: aspect_ratio: 16:9|9:16|2:3|3:2|1:1; duration: 6|10|15|20|30 (seconds, string); resolution: 480p|720p; mode: fun|normal|spicy - accepts: image_url, first_frame_url (alias of image_url; wins if both sent) - NOT supported (422 UNSUPPORTED_OPTION): last_frame_url - prompt cap: 5000 chars - credits by resolution x duration: 480p: {6s: 60, 10s: 90, 15s: 120, 20s: 140, 30s: 160} | 720p: {6s: 80, 10s: 120, 15s: 150, 20s: 180, 30s: 280} ### kling-3.0 (Kling 3.0) — video, provider kling - options: aspect_ratio: 16:9|9:16|2:3|3:2|1:1; duration: 6|10|15 (seconds, string); mode: std|pro - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), sound (default: inferred from prompt text — send false for silent), multi_prompt/multi_shots, kling_elements - NOT supported (422 UNSUPPORTED_OPTION): last_frame_url, resolution - prompt cap: 2500 chars - credits by mode x duration: std: {6s: 225, 10s: 300, 15s: 450} | pro: {6s: 300, 10s: 450, 15s: 600} ### seedance-2-fast (Seedance 2.0 Fast) — video, provider bytedance - options: aspect_ratio: 16:9|9:16|2:3|3:2|1:1; duration: 6|10|15 (seconds, string); resolution: 480p|720p - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), last_frame_url (requires first_frame_url), generate_audio (default true), reference_image_urls (max 9), reference_video_urls (max 3; surcharge 480p +50 cr, 720p +100 cr), reference_audio_urls (max 1) - first/last frame and reference_* are separate modes: sending both → 422 - prompt cap: 20000 chars - credits by resolution x duration: 480p: {6s: 150, 10s: 200, 15s: 300} | 720p: {6s: 350, 10s: 500, 15s: 650} ### seedance-2 (Seedance 2.0) — video, provider bytedance - options: aspect_ratio: 16:9|9:16|2:3|3:2|1:1; duration: 6|10|15 (seconds, string); resolution: 480p|720p|1080p|4k - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), last_frame_url (requires first_frame_url), generate_audio (default true), reference_image_urls (max 9), reference_video_urls (max 3; surcharge 480p +100 cr, 720p +200 cr, 1080p +600 cr, 4k +1000 cr), reference_audio_urls (max 1) - first/last frame and reference_* are separate modes: sending both → 422 - prompt cap: 20000 chars - credits by resolution x duration: 480p: {6s: 220, 10s: 350, 15s: 500} | 720p: {6s: 450, 10s: 600, 15s: 900} | 1080p: {6s: 900, 10s: 1600, 15s: 2500} | 4k: {6s: 2000, 10s: 3000, 15s: 5000} ### seedance-2-mini (Seedance 2.0 Mini) — video, provider bytedance - options: aspect_ratio: 16:9|4:3|1:1|3:4|9:16|21:9|adaptive; duration: 6|10|15 (seconds, string); resolution: 480p|720p - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), last_frame_url (requires first_frame_url), generate_audio (default true), reference_image_urls (max 9), reference_video_urls (max 3; surcharge 480p +20 cr, 720p +50 cr), reference_audio_urls (max 1) - first/last frame and reference_* are separate modes: sending both → 422 - prompt cap: 20000 chars - credits by resolution x duration: 480p: {6s: 50, 10s: 80, 15s: 120} | 720p: {6s: 100, 10s: 150, 15s: 210} ### seedance-2.5 (Seedance 2.5) — video, provider bytedance - options: aspect_ratio: 16:9|4:3|1:1|3:4|9:16|21:9|adaptive; duration: 6|10|15|20|30 (seconds, string); resolution: 480p|720p - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), last_frame_url (requires first_frame_url), generate_audio (default true), reference_image_urls (max 9), reference_video_urls (max 3; surcharge 480p +150 cr, 720p +350 cr), reference_audio_urls (max 1) - first/last frame and reference_* are separate modes: sending both → 422 - prompt cap: 20000 chars - credits by resolution x duration: 480p: {6s: 300, 10s: 400, 15s: 600, 20s: 750, 30s: 1000} | 720p: {6s: 600, 10s: 800, 15s: 1600, 20s: 1800, 30s: 3000} ### seedance-1.5-pro (Seedance 1.5 Pro) — video, provider bytedance - options: aspect_ratio: 16:9|9:16|2:3|3:2|1:1; duration: 4|8|12 (seconds, string); resolution: 480p|720p - accepts: image_url, first_frame_url (alias of image_url; wins if both sent), generate_audio (default true) - NOT supported (422 UNSUPPORTED_OPTION): last_frame_url - prompt cap: 20000 chars - credits by resolution x duration: 480p: {4s: 30, 8s: 60, 12s: 80} | 720p: {4s: 60, 8s: 100, 12s: 150} ### seedance-v1-pro (Seedance V1 Pro) — video, provider bytedance - options: aspect_ratio: 16:9|9:16|2:3|3:2|1:1; duration: 5|10 (seconds, string); resolution: 480p|720p - accepts: image_url, first_frame_url (alias of image_url; wins if both sent) - NOT supported (422 UNSUPPORTED_OPTION): last_frame_url - prompt cap: 20000 chars - credits by resolution x duration: 480p: {5s: 30, 10s: 50} | 720p: {5s: 60, 10s: 100} ### lipsync (Lip Sync) — video, provider kling - options: resolution: 480p|720p - accepts: image_url, image_url+audio_url+audio_duration (required) - prompt cap: 5000 chars - credits: normal/collate = base + perSecond x (seconds - 5): 480p: base 60 + 5/s | 720p: base 150 + 20/s; trim flat: 480p: 110, 720p: 300; normal caps 15s, collate 120s ### gemini-omni (Gemini Omni) — video, provider google - options: aspect_ratio: 16:9|9:16; duration: 4|6|8|10 (seconds, string); resolution: 1080p|4k - accepts: reference_image_urls (max 7), reference_video_urls (max 1), character_asset_ids (max 3; ids from GET /v1/assets), voice_asset_ids (max 3; REQUIRED; ids from GET /v1/assets) - NOT supported (422 UNSUPPORTED_OPTION): image_url, first_frame_url, last_frame_url, generate_audio - requires voice_asset_ids AND a character (character_asset_ids or reference_image_urls) - prompt cap: 20000 chars - credits by resolution x duration: 1080p: {4s: 120, 6s: 160, 8s: 200, 10s: 240} | 4k: {4s: 250, 6s: 300, 8s: 350, 10s: 400} ### nano-banana (Nano Banana) — image, provider google - accepts: image_urls (max 5, switches to edit mode) - credits: 10 ### nano-banana-pro (Nano Banana Pro) — image, provider google - accepts: image_urls (max 5, switches to edit mode) - credits: 30 ### grok-image (Grok Imagine Image) — image, provider xai - accepts: image_urls (max 5, switches to edit mode) - credits: 20 flat per batch ### gpt-image-2 (GPT Image 2) — image, provider openai - options: resolution: 1K|2K|4K - accepts: image_urls (max 5, switches to edit mode) - credits by resolution: 1K: 10, 2K: 20, 4K: 30 ### voiceover (Voiceover) — audio, provider elevenlabs - accepts: voice_id (required), text (required) - prompt cap: 5000 chars - credits by duration (estimated at 15 chars/s): <=15s: 20, <=30s: 40, <=60s: 80, <=120s: 150, <=300s: 300 ### music (Music) — audio, provider suno - accepts: title, style, lyrics (required unless instrumental: true) - credits: 50 flat ## Extend POST /v1/extend/video {"job_id": "", "prompt": "..."} — Veo3-family only, adds ~7s, flat 120 credits. ## Buying credits USD: Pilot $5 = 600cr, Starter $19 = 3000cr, Popular $49 = 9000cr, Business $99 = 20000cr | INR: Pilot ₹299 = 400cr, Starter ₹1999 = 3000cr, Business ₹9999 = 20000cr — purchased at https://aiveed.io/pricing; the first completed purchase upgrades keys to pro. ## Rate limits & tiers Sliding 60s window per key; X-RateLimit-Limit/Remaining on every response; 429 RATE_LIMIT_EXCEEDED with Retry-After when over. Tiers: free 10rpm/3 concurrent jobs, pro 30rpm/10, enterprise 100rpm/50. Keys auto-upgrade free->pro after the account's first completed purchase. Over the concurrency cap -> 429 concurrency_limit_reached (nothing charged). Free tier: new accounts get up to 200 free credits, and until the first purchase an account can make one video (any model and options that fit within those credits), counted across the web app and the API. /batch is paid-only (403 upgrade_required), since a free account has only one video to make. No image model is free through the API: every generation is charged at its catalogue price against your credit balance, and the web app's own free allowances do not apply here. Live values: GET /v1/usage/limits. ## Uploads POST /v1/uploads (multipart: file + kind=image|audio|video) -> {"url": "..."} for use as first_frame_url/last_frame_url/image_url/image_urls/audio_url/reference_*_urls. Caps: image 10MB, audio 5MB, video 50MB. 0 credits. Image/audio URLs are durable (reusable indefinitely); video URLs are transient (~90 days) — use promptly. ## Batch POST /v1/batch {"jobs": [{"type": "video"|"image", "model": "...", ...same fields as /generate/*}]} — up to 10 items, paid tiers only. Items are charged individually and submitted sequentially; the batch stops at the first insufficient-credits item (later items "skipped", never charged); other per-item errors don't stop it. Response: per-item results + estimated_credits/credits_charged/remaining_credits. ## Webhooks POST /v1/webhooks {"url": "https://...", "events": ["job.completed", "job.failed"], "secret?": "16-64 chars"} (max 5 active; https + publicly routable only; omitted secret is generated and returned once). Every delivery is signed: X-AIVeed-Signature: t=,sha256=HMAC_SHA256(secret, t + "." + raw_body). Verify the HMAC AND reject t older than 300s. At-least-once delivery with retries — dedupe on (job.id, event). Per-job variant: webhook_url + webhook_secret fields on any generate request. ## Real-time (SSE) POST /v1/sse/tickets {"jobId": "..."} -> {"ticket", "expires_in": 300} then GET /v1/sse/jobs/{id}?ticket=... (browsers) or with normal auth headers (servers). Events: status ({id,status,progress,result_url?,error_message?}), heartbeat, done. ?api_key= is never accepted. ## TOON Send Accept: application/toon on any endpoint for a token-optimized response encoding (same data, fraction of the tokens; X-TOON-Dict header names the dictionary). Use it when responses feed an LLM. ## Errors Envelope: {"error": true, "code": "...", "message": "...", "details?": ..., "param?": "..."}. Codes: 400 VALIDATION_ERROR — The request body or query failed schema validation. `details` lists the individual problems. 400 INVALID_PARAM — A path parameter has the wrong type (e.g. a non-integer key or webhook id). 400 INVALID_IDEMPOTENCY_KEY — The Idempotency-Key header is malformed. Allowed: 1-200 characters of A-Z a-z 0-9 _ . - 401 AUTH_REQUIRED — No credentials. Send `X-API-Key: aiv_sk_...` or `Authorization: Bearer `. 401 INVALID_API_KEY — The API key is malformed, unknown, or revoked. 401 KEY_EXPIRED — The API key is past its expiry date. Create or rotate a key on the dashboard. 401 TOKEN_MALFORMED — The Bearer token is not a structurally valid JWT. 401 TOKEN_EXPIRED — The session JWT has expired — log in again. 401 TOKEN_INVALID — The session JWT failed verification. 401 USER_NOT_FOUND — The session JWT is valid but its user no longer exists. 401 PASSWORD_CHANGED — The session JWT was issued before the last password change. Log in again. 401 INVALID_TICKET — The SSE ticket is invalid, expired, or bound to a different job. 402 INSUFFICIENT_CREDITS — Your balance does not cover the job cost. Nothing was charged. 403 insufficient_scope — The API key lacks the required scope (`required_scope` names it), or an API key attempted session-only key management. 403 upgrade_required — A paid-plan feature on a free key (e.g. /batch), or the free trial is exhausted. `pricing_url` links to plans. 403 ACCOUNT_BANNED — The account is suspended. Contact support@aiveed.io. 403 NOT_ELIGIBLE — The account cannot perform this action (e.g. unverified email, locked credits). `reason`/`reasons` explain. 403 CONTENT_POLICY_VIOLATION — The prompt or input media failed content moderation. Repeated violations can suspend the account. 404 JOB_NOT_FOUND — No job with that id belongs to you. 404 KEY_NOT_FOUND — No such API key (or it is already revoked). 404 WEBHOOK_NOT_FOUND — No webhook config with that id belongs to you. 404 NOT_FOUND — The endpoint or referenced resource does not exist. 409 KEY_LIMIT_REACHED — Maximum active API keys reached — revoke one first. 409 KEY_REVOKED — The key is revoked and cannot be rotated. 409 WEBHOOK_LIMIT_REACHED — Maximum active webhooks reached — delete one first. 409 CANNOT_CANCEL — Only queued jobs can be cancelled; this one already left the queue. 413 PAYLOAD_TOO_LARGE — JSON bodies are capped at 1 MB; uploads at their per-kind size cap (image 10 MB, audio 5 MB, video 50 MB). 415 UNSUPPORTED_MEDIA_TYPE — The uploaded file type is not allowed for that `kind`. 422 UNSUPPORTED_OPTION — A request option is not supported by this model (or a webhook URL is not https/publicly routable). `param` names the offending field. 429 RATE_LIMIT_EXCEEDED — Over your per-minute request limit. Honor `Retry-After` and the X-RateLimit-* headers. 429 concurrency_limit_reached — Your key already has `max_concurrent` jobs in flight — wait for one to finish. 429 TOO_MANY_STREAMS — Too many SSE streams open for this account. Close one before opening another, or poll GET /v1/jobs/{id} instead. 500 INTERNAL_ERROR — Unexpected server error. Safe to retry with the same Idempotency-Key. 502 PROVIDER_ERROR — The upstream generation provider is temporarily unavailable. Charged jobs that fail are refunded automatically. 504 GATEWAY_TIMEOUT — The generation service did not respond in time. The job may still be running — poll GET /v1/jobs/{id} rather than resubmitting, or the work could be charged twice. 500 GENERATION_FAILED — Fallback code when a submission fails without a more specific cause. 500 EXTEND_FAILED — Fallback code when a video extension fails without a more specific cause. (item) SKIPPED — Batch per-item only: not submitted because an earlier item failed with INSUFFICIENT_CREDITS. ## Retry rules 429 -> wait Retry-After then retry. 5xx/502 -> retry with the same Idempotency-Key (safe). Other 4xx -> fix the request. Failed/refunded jobs never keep your credits. ## Prompt packs Copy-paste assistant prompts (generate, image, image->video showcase, integration starter): https://developer.aiveed.io/docs/ai-assistants