Video generation
Introduction
Capability key: video.generate · API origin: https://api.anycap.io
This document defines the external interface contract for Anycap video generation (capability key video.generate). Every endpoint and example uses the production origin https://api.anycap.io.
Unified API (recommended)
New integrations call POST /v1/generations with type=video. The /v1/videos/generations endpoints below remain supported for compatibility.
curl -X POST https://api.anycap.io/v1/generations \ -H "Authorization: Bearer $ANYCAP_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "video", "model": "<model from GET /v1/generations/models?type=video>", "input": { "prompt": "a small orange cat sleeping on a windowsill" }, "parameters": { "resolution": "720P", "ratio": "16:9" } }'input.prompt
input.image_url / input.last_frame_url
input.reference_*_file_ids
parameters
resolution, ratio, duration, audio.1. Setup
- Create a connection key in the console under Agent Access and authorize the required video tiers.
- Every request uses
Authorization: Bearer <ANYCAP_API_KEY>andContent-Type: application/json. Never send Cookie or Origin, and never reuse a browser session. - Monetary fields are decimal integer strings. 1 credit = 1000000 microcredits; display conversion is 1000 credits = $1.
- There are two alternative paths and each has its own discovery endpoint: the tier path — query
GET /v1/videos/tiers, then create withtier; the model path — queryGET /v1/videos/models, then create withmodel. Never invent resource UUIDs, model names or prices; read specifications from the endpoint of the path you chose.
2. Endpoints
| Step | Method | Path | Success |
|---|---|---|---|
| Tier discovery | GET | /v1/videos/tiers | 200 |
| Model discovery | GET | /v1/videos/models | 200 |
| Create a video task | POST | /v1/videos/generations | 202 |
| Read a task | GET | /v1/videos/generations/{id} | 200 |
| Read a task and fetch the result URL | GET | /v1/videos/generations/{id}?result=true | 200 |
| Cancel a task not yet submitted upstream | DELETE | /v1/videos/generations/{id} | 200 |
Key points:
- The create endpoint performs quoting and submission server-side; the caller does not request a quote separately.
- Only three tiers are exposed:
basic/standard/premium. The model and specifications behind each tier are operator configuration. A tier is a ceiling: nothing is downgraded, substituted or silently routed elsewhere. modelandtierare alternatives (either/or). Send exactly one of them:tierfromGET /v1/videos/tiers, ormodelfromGET /v1/videos/models. Sending neither fails with 400field=tier; sending both makesmodelroute the request andtieronly a constraint. The tier listing never reveals which model backs a tier, and no tier-to-model mapping is published.Idempotency-Keyis your own key for the logical call: any opaque string of at most 255 bytes, scoped to your connection. Repeating a key returns the recorded task and never charges twice; the create response returns the taskid(when your key is a UUID the id equals it).- These paths carry no
/apiprefix and accept only a Bearer connection key.
3. Create parameters (POST /v1/videos/generations)
Headers:
| Header | Required | Meaning |
|---|---|---|
Authorization | yes | Bearer <ANYCAP_API_KEY> |
Content-Type | yes | application/json |
Idempotency-Key | no | Your idempotency key: any opaque string of at most 255 bytes (a UUID keeps the task id equal to the key); takes precedence over the body idempotency_key |
Body (additionalProperties: false; unknown fields return 400):
modelstringyes for model-first (alternative to tier)
model instead of tier with prompt (or an image/reference input). It must be a model this key may call (read from GET /v1/videos/models) and is never substituted; with a native_request it pins the model as welltierstringyes for tier-first (alternative to model)
tier instead of model. basic / standard / premium. Sent together with model it only constrains which tier the model must belong to; a model outside that tier fails with 400 field=modelpromptstringunless an image or reference input is set
max_prompt_charactersimage_urlstringno
last_frame_urlstringno
image_url is required alongside itreference_image_urlsstring[]no
image_url, not a reference. For wan3.0-video, frames (image_url/last_frame_url) and reference images are mutually exclusive — send one style per requestreference_image_file_idsstring(uuid)[]no
reference_video_file_idsstring(uuid)[]no
reference_audio_file_idsstring(uuid)[]no
resolutionstringno
ratiostringno
durationintegerno
audiobooleanno
idempotency_keystringno
resource_idstring(uuid)no (advanced)
native_request. Tier-first and model-first requests ignore it: the platform picks among the sources this key may call that are enabled, priced and able to build the requestnative_requestobjectno (advanced)
Rules:
- Two ways to choose — either/or, exactly one per request. Tier path: query
GET /v1/videos/tiers, then sendtierplusprompt(or an image/reference input). Model path: queryGET /v1/videos/models, then sendmodelplusprompt(or an image/reference input). Omitting both fails with 400field=tier. Everything else is optional and resolved inside the chosen tier's or model's own limits. modelsent withtier: the model must belong to that tier, otherwise 400 withfield=model. A model this key may not call fails the same way — never a silent substitution.- Omitted means the source default; a supplied value is executed exactly. A value outside what the source supports and prices returns 400 and is never replaced by another value.
- Reference inputs decide what can serve the request. A source is only offered when it can build every input kind the request carries:
wan3.0-videotakes a first-frameimage_urlonly, while the Seedance models also take reference images, videos and audios. Images may be public HTTPS links; video and audio must be Anycap-owned uploads (their seconds are billed as input seconds). native_requestis the advanced protocol-shaped path (section 14): the chosen model's adapter validates it, it is never rewritten across protocols, and the fields above do not apply to it.
Minimal body (tier path):
{ "tier": "standard", "prompt": "A small orange cat sleeping on a windowsill" }Minimal body (model path — model replaces tier):
{ "model": "doubao-seedance-2-0-mini-260615", "prompt": "A small orange cat sleeping on a windowsill" }4. Create response (202)
{ "id": "8f5b5b9e-1f2a-4c3d-9a1b-7c0f1d2e3a4b", "resource_id": "0f2a9c3e-4b5d-4e6f-8a9b-0c1d2e3f4a5b", "state": "queued", "error_code": "", "billing_status": "held", "reserved_microcredits": "191000000", "charged_microcredits": "0", "created_at": "2026-10-13T08:00:00Z", "selection": { "resource_id": "0f2a9c3e-4b5d-4e6f-8a9b-0c1d2e3f4a5b", "model": "<model>", "resolution": "720P", "ratio": "16:9", "duration": 5, "audio": true }}selection is returned only on the create response and states the model, resolution, ratio, duration and audio actually used. The example amounts are structural; always use the amounts the API returns.
5. Tier discovery: GET /v1/videos/tiers
This read-only endpoint is the tier path discovery surface: it lists only the tiers this key is authorized for, enabled and currently priced, and you create tasks by sending one of these tier values (never invented). It makes no provider call and creates no reservation.
Full response:
{ "items": [ { "tier": "standard", "resolutions": [ { "resolution": "480P", "credits_per_second": "29", "minimum_credits": "116" }, { "resolution": "720P", "credits_per_second": "58", "minimum_credits": "232" } ], "ratios": ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9"], "min_duration": 4, "max_duration": 15, "max_prompt_characters": 1000, "default_resolution": "720P", "default_ratio": "16:9", "default_duration": 5, "audio": true } ]}Amounts in the example are structural only; the live response is authoritative.
tier
basic / standard / premiumresolutions[]
credits_per_second and minimum_credits (the shortest billable job for this tier). Both are integers; prices are published as whole credits, so no fractional or microcredit amount is exposed. A tier carrying a token-metered model with a published video-input discount also shows with_video_credits_per_second (applied automatically to requests that include a video reference)ratios[]
min_duration / max_duration
max_prompt_characters
frame_rate
input_types[]
text / image / video / audioconcurrency / requests_per_minute
default_resolution / default_ratio / default_duration / audio
This endpoint never returns the source or the model behind a tier; use the model discovery endpoint in the next section for model capability. An empty items array means no tier is available to this key; check source enablement, key permissions and published prices.
6. Model discovery: GET /v1/videos/models
A read-only listing of the models this key may call (authorized, enabled and currently priced) together with that model's own parameters and published prices in whole credits. It carries no source id and no tier, so the mapping between tiers and models is never exposed; model capabilities and tier products are two independent surfaces. This is the model path discovery surface: you create tasks by sending one of these model values instead of a tier.
Complete response fields:
{ "items": [ { "model": "doubao-seedance-2-0-mini-260615", "resolutions": [ { "resolution": "480P", "credits_per_second": "36", "with_video_credits_per_second": "22", "minimum_credits": "144" }, { "resolution": "720P", "credits_per_second": "77", "with_video_credits_per_second": "47", "minimum_credits": "308" } ], "ratios": [ "16:9", "4:3", "1:1", "3:4", "9:16", "21:9" ], "min_duration": 4, "max_duration": 15, "max_prompt_characters": 1000, "frame_rate": 24, "input_types": [ "text", "image", "video", "audio" ], "concurrency": 10, "requests_per_minute": 600 } ]}model
model to create with it, or as native_request.model for full controlresolutions[]
credits_per_second and minimum_credits (the shortest billable job for this model, which can be shorter than the tier minimum). Token-metered models with a video-input discount also publish with_video_credits_per_second, applied automatically when the request carries a video referenceratios[]
min_duration / max_duration
max_prompt_characters
frame_rate
input_types[]
concurrency / requests_per_minute
note
- Use this endpoint to build either an advanced
native_request(full control) or a plain model-first request: sendmodelwithprompt/resolution/ratio/duration/audioand Anycap serves that model inside its own limits. - One entry per model: the values are that model's own limits and prices, never a plan-tier union.
GET /v1/videos/tiersstays the plan view (one price per tier).
7. Per-tier limits
A tier is the only external dimension: resolutions, ratios, output duration and prompt length are declared per tier and differ between tiers (one tier may cap at 720P, another may reach 1080P). They should not be assumed or hard-coded; always use the values returned by GET /v1/videos/tiers:
- Which model backs a tier is operator configuration: the caller neither selects nor overrides it, and the platform never substitutes a model because of the prompt or parameters.
- A tier publishes one price: when several models back it, the platform serves the request from the cheapest healthy one and falls back to the next when the upstream throttles or runs out of quota, so the model that answers never changes what you pay.
min_durationis the longer of the platform floor (2 seconds) and that tier's model minimum, so it can differ between tiers.- Tier-first requests always use uppercase resolutions (
480P/720P/1080P); an advancednative_requestfollows the spelling of its own model family (section 14). - A resolution, ratio or duration the tier does not support and price always returns 400; nothing is downgraded, substituted or moved to another tier.
The model path is the alternative: limits there are the model's own resolutions, ratios, min_duration and max_duration from GET /v1/videos/models, not the tier's, and billing uses that model's published per-second prices.
8. Read a task: GET /v1/videos/generations/{id}
idis the task id returned at creation (it equals youridempotency_keywhen that key is a UUID).- Query parameters: none, or a single
result=truethat re-queries the provider and returns the temporary URL.result=falseor any other parameter returns 400. video_urlis returned with raw&separators (no HTML escaping), so it can be pasted into a browser as-is; copy the whole URL including every query parameter.- The link is a temporary signed provider URL (about 24 hours). Anycap never stores the video or the link: retrieve it again with
result=truewhile it lasts, and save the file if you need it longer. The console offers copy, open-in-new-tab and download actions on the result. - Only tasks owned by this key are readable; another key's task returns 404.
Complete response fields (video_url is absent unless result=true and the task completed):
idstring(uuid)
resource_idstring(uuid)
statestring
queued / submitting / submitted / processing / finalizing / completed / failed / pendingerror_codestring
failure_reasonstring
duration_microsecondsstring
video_urlstring
result=true on a completed taskbilling_statusstring
held / pending / settled / releasedreserved_microcreditsstring
charged_microcreditsstring
created_atstring(date-time)
A read without result=true returns only durable local state: it never regenerates, never recharges and never extends a URL lifetime.
selection (section 4) is returned only by create, not by read. To reproduce the specifications used, keep the create response, or read the limits of the path you used: GET /v1/videos/tiers (tier path) or GET /v1/videos/models (model path).
9. States, failure classification and polling
| `state` | Action |
|---|---|
queued / submitting / submitted / processing / finalizing | Wait; poll the local task every 15 seconds |
completed | Request ?result=true for video_url |
failed | Definitive failure; inspect error_code / failure_reason; the reservation is released |
pending | Requires reconciliation; retain the task UUID and stop automatic resubmission |
billing_status: held (reserved) / pending (reconciling) / settled (charged) / released (released).
Closed set of failure_reason values (the field may be absent; treat unfamiliar values as a generic failure and never resubmit automatically):
canceled, authentication_failed, service_access_denied, service_quota_exceeded, content_rejected, invalid_request, reference_preparation_failed, service_connection_failed, upstream_failed.
canceled is produced by the cancellation in section 11. authentication_failed means the generation service rejected authentication (contact platform support); it is not evidence that the caller's Anycap key is invalid.
10. Results and lifetime
- Results are temporary provider HTTPS URLs; Anycap never stores them.
- Result retrieval stops 24 hours after task creation with
result_expired; temporary unavailability may returnresult_unavailable. - A completed task without
video_urldoes not imply zero cost. Never regenerate automatically or assume that reading extends the URL lifetime.
11. Cancel: DELETE /v1/videos/generations/{id}
- Only a task still queued before any upstream submission can be cancelled, releasing its reservation exactly once.
- A task that may already be in flight returns 409 and keeps its reservation for reconciliation.
- The cancelled task object is returned (
stateends asfailed,error_code=canceled).
12. Examples
All examples use the production origin. They reuse one fixed UUID to illustrate replay; in production, generate a fresh UUID per business operation and persist it before submitting.
12.1 curl
export ANYCAP_API_KEY="your-connection-key"export JOB_ID="8f5b5b9e-1f2a-4c3d-9a1b-7c0f1d2e3a4b" # 1) Discover the tiers this key may usecurl -sS https://api.anycap.io/v1/videos/tiers \ -H "Authorization: Bearer $ANYCAP_API_KEY" # 1b) Model path: discover the models this key may callcurl -sS https://api.anycap.io/v1/videos/models \ -H "Authorization: Bearer $ANYCAP_API_KEY" # 2) Create a video task (tier path — `tier` and `model` are alternatives)curl -sS -X POST https://api.anycap.io/v1/videos/generations \ -H "Authorization: Bearer $ANYCAP_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $JOB_ID" \ -d '{ "tier": "standard", "prompt": "A small orange cat sleeping on a windowsill", "resolution": "720P", "ratio": "16:9", "duration": 5, "audio": true }' # 2b) Model path: create with "model" instead of "tier" (use a fresh idempotency key)curl -sS -X POST https://api.anycap.io/v1/videos/generations \ -H "Authorization: Bearer $ANYCAP_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "<model from GET /v1/videos/models>", "prompt": "A small orange cat sleeping on a windowsill", "duration": 4 }' # 3) Read the taskcurl -sS https://api.anycap.io/v1/videos/generations/$JOB_ID \ -H "Authorization: Bearer $ANYCAP_API_KEY" # 4) Fetch the result URL once completedcurl -sS "https://api.anycap.io/v1/videos/generations/$JOB_ID?result=true" \ -H "Authorization: Bearer $ANYCAP_API_KEY" # 5) Cancel a task not yet submitted upstreamcurl -sS -X DELETE https://api.anycap.io/v1/videos/generations/$JOB_ID \ -H "Authorization: Bearer $ANYCAP_API_KEY"12.2 Go
package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" "os" "time") const apiBase = "https://api.anycap.io" func main() { key := os.Getenv("ANYCAP_API_KEY") jobID := "8f5b5b9e-1f2a-4c3d-9a1b-7c0f1d2e3a4b" // use a fresh uuid4 per operation and persist it first create := map[string]any{ "tier": "standard", "prompt": "A small orange cat sleeping on a windowsill", "resolution": "720P", "ratio": "16:9", "duration": 5, "audio": true, } body, _ := json.Marshal(create) req, _ := http.NewRequest(http.MethodPost, apiBase+"/v1/videos/generations", bytes.NewReader(body)) req.Header.Set("Authorization", "Bearer "+key) req.Header.Set("Content-Type", "application/json") req.Header.Set("Idempotency-Key", jobID) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } raw, _ := io.ReadAll(resp.Body) resp.Body.Close() fmt.Println(resp.StatusCode, string(raw)) for i := 0; i < 120; i++ { job := get(key, apiBase+"/v1/videos/generations/"+jobID) fmt.Println("state:", job["state"], "billing:", job["billing_status"]) switch job["state"] { case "completed": fmt.Println(get(key, apiBase+"/v1/videos/generations/"+jobID+"?result=true")) return case "failed", "pending": fmt.Println("stop:", job["error_code"], job["failure_reason"]) return } time.Sleep(15 * time.Second) } fmt.Println("polling deadline; resume GET with the persisted UUID, never a new POST")} func get(key, url string) map[string]any { req, _ := http.NewRequest(http.MethodGet, url, nil) req.Header.Set("Authorization", "Bearer "+key) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out := map[string]any{} json.NewDecoder(resp.Body).Decode(&out) return out}12.3 Java (Java 11+)
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.time.Duration; public class AnycapVideo { static final String API = "https://api.anycap.io"; public static void main(String[] args) throws Exception { HttpClient http = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build(); String key = System.getenv("ANYCAP_API_KEY"); String jobId = "8f5b5b9e-1f2a-4c3d-9a1b-7c0f1d2e3a4b"; // use a fresh uuid4 per operation and persist it first String create = "{" + "\"tier\":\"standard\"," + "\"prompt\":\"A small orange cat sleeping on a windowsill\"," + "\"resolution\":\"720P\"," + "\"ratio\":\"16:9\"," + "\"duration\":5," + "\"audio\":true" + "}"; HttpRequest post = HttpRequest.newBuilder(URI.create(API + "/v1/videos/generations")) .header("Authorization", "Bearer " + key) .header("Content-Type", "application/json") .header("Idempotency-Key", jobId) .POST(HttpRequest.BodyPublishers.ofString(create)) .build(); System.out.println(http.send(post, HttpResponse.BodyHandlers.ofString())); for (int i = 0; i < 120; i++) { String body = http.send(get(key, API + "/v1/videos/generations/" + jobId), HttpResponse.BodyHandlers.ofString()).body(); System.out.println(body); if (body.contains("\"state\":\"completed\"")) { System.out.println(http.send(get(key, API + "/v1/videos/generations/" + jobId + "?result=true"), HttpResponse.BodyHandlers.ofString()).body()); return; } if (body.contains("\"state\":\"failed\"") || body.contains("\"state\":\"pending\"")) { return; } Thread.sleep(15000); } System.out.println("polling deadline; resume GET with the persisted UUID, never a new POST"); } static HttpRequest get(String key, String url) { return HttpRequest.newBuilder(URI.create(url)) .header("Authorization", "Bearer " + key) .GET() .build(); }}13. Reference materials
image_url(tier-first) and images insidenative_request: public HTTPS URLs, at most 8192 characters, without userinfo, explicit ports or fragments. Literal local/private addresses, HTTP and data URLs are rejected. Anycap forwards them verbatim for the provider to fetch.- Private materials use
anycap-file://UUID(same workspace, same actor, unexpired). Owned uploads go throughPOST /v1/video-materials?kind=video|audio|image(see 13.1, connection key) or the browser session API; owned images must be JPG, WebP or BMP (PNG is not accepted). External agents may also use public HTTPS images. - A last frame requires a first frame; frame mode cannot mix with reference mode. At most 10 images, 5 videos and 5 audio files; input video and audio each total at most 15 seconds, and input video plus output at most 30 seconds. The server probes real media; clients cannot declare durations.
13.1 Upload owned materials: POST /v1/video-materials
Upload the file first; the generation request only carries the returned file id. Send multipart/form-data with a single file field and kind=image|video|audio in the query. An optional Idempotency-Key header makes a repeated upload return the same file. The server probes the real media (format, dimensions, frame rate, duration); clients cannot declare them.
| kind | Formats | Size | Notes |
|---|---|---|---|
image | JPG, WebP, BMP | 20 MiB | Short side at least 240 px; PNG is rejected (reference images keep no alpha channel) |
video | MP4, MOV (mov container) | 100 MiB | Real duration is billed as input when used as a reference; reference clips total at most 15 s |
audio | MP3, WAV | 15 MiB | Must accompany at least one image or video; all reference audio totals at most 15 s |
Response (201):
{ "id": "11111111-1111-4111-8111-111111111111", "kind": "media", "filename": "reference.mp4", "bytes": 1234567, "created_at": "2026-10-30T08:00:00Z", "expires_at": "2026-11-02T08:00:00Z", "media": { "duration_microseconds": 5000000 }}curl -X POST "https://api.anycap.io/v1/video-materials?kind=video" \ -H "Authorization: Bearer $ANYCAP_API_KEY" \ -F "file=@./reference.mp4"- Use the returned
idinreference_image_file_ids,reference_video_file_ids,reference_audio_file_idsfor generation, orvideo_file_idfor the edit endpoint. - Files are retained for 72 hours and belong to the same workspace and member; another key or member cannot use the id.
- Ids are stable: retrying a submission reuses the same id and never uploads or charges twice. The provider never receives the id; at submission the platform resolves it to a short-lived signed URL.
- Public HTTPS images may still be sent through
reference_image_urls; video and audio cannot be public URLs because their seconds are billed.
14. Advanced: choose a model
Instead of a tier you may name a model directly (see GET /v1/videos/models). Anycap then builds the request from that model's own defaults and limits and charges that model's published price for the chosen resolution. tier is optional: sent together with model it only constrains which tier the model must belong to, and a model that does not match fails with 400 field=model (never a silent substitution). An unknown or unauthorized model fails the same way.
{ "model": "doubao-seedance-2-0-mini-260615", "prompt": "A small orange cat sleeping on a windowsill", "resolution": "720P", "ratio": "16:9", "duration": 5, "audio": true}Only model plus a prompt (or image_url) are required; every other field is optional and resolved like a tier request. A model's own limits apply, so for example wan3.0-video accepts 2-second jobs even though the premium tier starts at 4 seconds. The response carries the same selection, naming the model that ran.
Full control: native_request
POST /v1/videos/generations also accepts a native native_request in the spelling of the chosen model. native_request.model is required and must be a model your key may call (GET /v1/videos/models); the tier endpoint never reveals it. tier and resource_id may be omitted (the model alone routes); when supplied they must match the same source, otherwise the request fails with capability_unavailable. The platform validates the request with that model's adapter and never rewrites it. Tier-first fields such as prompt and image_url do not apply.
Seedance models (doubao-seedance-*):
{ "tier": "standard", "native_request": { "model": "<model>", "content": [{ "type": "text", "text": "A small orange cat sleeping on a windowsill" }], "resolution": "720p", "ratio": "16:9", "duration": 5, "generate_audio": true }}Fields: model (required; a model from GET /v1/videos/models that your key may call), content[] (required; text or image_url, the latter with an optional first_frame / last_frame / reference_image role), resolution (lowercase), ratio, duration (integer), generate_audio, seed, watermark.
Wan models (wan3.0-*):
{ "resource_id": "0f2a9c3e-4b5d-4e6f-8a9b-0c1d2e3f4a5b", "native_request": { "model": "<model>", "input": { "prompt": "Animate the subject with gentle motion" }, "parameters": { "resolution": "480P", "ratio": "16:9", "duration": 5, "audio": true } }}Fields: model, input.prompt / input.media[] (first_frame / last_frame / reference_image / reference_video / reference_audio), parameters (required resolution / ratio / duration; optional audio / seed / prompt_extend / watermark).
15. Errors and recovery
Errors are {"error":{"code":"...","request_id":"..."}}, correlated by X-Request-ID.
| HTTP | Meaning |
|---|---|
| 400 | Invalid parameters or materials; a value outside the tier's or the model's limits; neither tier nor model sent (field=tier); or model outside the sent tier (field=model) |
| 401 | Invalid key |
| 402 | Insufficient balance |
| 403 | No permission for the source or tier |
| 404 | Source or task not owned by this key |
| 409 | Quote, input or idempotency conflict; or a task that is no longer cancellable |
| 429 | Concurrency or rate limit |
| 503 | No matching available source or configuration |
Recovery:
- Do not retry every error uniformly. Fix 400/401/403/404/409/402 before retrying.
- Timeouts, disconnects, 5xx and missing submission responses are ambiguous. Query the persisted UUID first; even a query 404 does not prove upstream non-delivery, and you must never generate a new UUID and blindly resubmit.
- Reads (GET) may use bounded backoff;
pendingwaits for platform reconciliation. - A local polling deadline neither cancels the task, releases funds nor authorizes another billable request.
16. Appendix: explicit quote endpoints
The older two-step /api/v1 endpoints remain available; new integrations should use the unified endpoints in section 2.
| Step | Method | Path |
|---|---|---|
| Quote | POST | /api/v1/capabilities/video.generate/quotes |
| Submit | POST | /api/v1/capabilities/video.generate/executions |
| Read a task | GET | /api/v1/video-executions/{id} |
A quote returns id, resource_id, price_version_id, usage_limits, amount_microcredits and expires_at; it lasts five minutes and is bound to the native request, so changing input requires a new quote.
gemini-omni-1.2-flash-ext
Send one of the following native_request objects to POST /v1/videos/generations, with the same model in the outer object. Every mode requires a non-empty prompt. Resolution: 360p, 720p (default), 1080p or 4k; 2160p is an alias for 4k. Aspect ratio: 16:9 (default) or 9:16. Duration: 3–15 whole seconds (default 10); first/last frame and extend: 3–10. Edit omits duration. First/last frame forbids system_prompt and negative_prompt. Reference images: up to 10 public HTTPS URLs or owned uploads; do not mix them with frame inputs or video. Upload edit sources first through the video material endpoint; use a single anycap-file:// reference (MP4/MOV/WebM, at most 15 seconds and 64 MB). extend_from_task_id is your completed Anycap job UUID in the current space, for this model and the same available channel; raw channel task IDs are rejected. It may be used for edit as well as extend. Original clips longer than 15 seconds must be trimmed and uploaded. Read GET /v1/videos/generations/{id} until completion; task processing time is not clip duration.
Text to video
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "duration": 15, "aspect_ratio": "9:16"}First frame
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "first_frame_image": "https://example.com/start.jpg", "duration": 6}First and last frame
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "first_frame_image": "https://example.com/start.jpg", "last_frame_image": "https://example.com/end.jpg", "duration": 8}Reference images
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "image_urls": [ "https://example.com/cat.jpg", "https://example.com/ball.jpg" ], "duration": 8}Edit uploaded video
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "video_urls": [ "anycap-file://<uploaded-file-id>" ], "omni_reference_task_type": "edit"}Extend uploaded video
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "video_urls": [ "anycap-file://<uploaded-file-id>" ], "omni_reference_task_type": "extend", "duration": 4}Continue a previous task
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "extend_from_task_id": "<completed-anycap-job-uuid>", "omni_reference_task_type": "extend", "duration": 6}System and negative prompts
{ "model": "gemini-omni-1.2-flash-ext", "prompt": "The camera slowly pans across the scene.", "system_prompt": "Render as a black-and-white silent film.", "negative_prompt": "people, cars, color", "duration": 6}Completed video jobs may include continuation: available indicates whether this video can be edited or extended, duration_microseconds is the full clip length (including the original portion of an extension), and unavailable_reason explains an unavailable action. These fields are read-only. An editing or extension request still uses the completed Anycap job UUID in native_request.extend_from_task_id.