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.

BASH
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" }  }'
FieldMeaning
input.prompt
Video instruction.
input.image_url / input.last_frame_url
Optional first or last frame.
input.reference_*_file_ids
Optional owned reference images, videos or audio.
parameters
resolution, ratio, duration, audio.
Video jobs return 202 with job; poll GET /v1/generations/{id}?result=true. DELETE cancels only a job still queued before the billable upstream call.

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> and Content-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 with tier; the model path — query GET /v1/videos/models, then create with model. Never invent resource UUIDs, model names or prices; read specifications from the endpoint of the path you chose.

2. Endpoints

StepMethodPathSuccess
Tier discoveryGET/v1/videos/tiers200
Model discoveryGET/v1/videos/models200
Create a video taskPOST/v1/videos/generations202
Read a taskGET/v1/videos/generations/{id}200
Read a task and fetch the result URLGET/v1/videos/generations/{id}?result=true200
Cancel a task not yet submitted upstreamDELETE/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.
  • model and tier are alternatives (either/or). Send exactly one of them: tier from GET /v1/videos/tiers, or model from GET /v1/videos/models. Sending neither fails with 400 field=tier; sending both makes model route the request and tier only a constraint. The tier listing never reveals which model backs a tier, and no tier-to-model mapping is published.
  • Idempotency-Key is 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 task id (when your key is a UUID the id equals it).
  • These paths carry no /api prefix and accept only a Bearer connection key.

3. Create parameters (POST /v1/videos/generations)

Headers:

HeaderRequiredMeaning
AuthorizationyesBearer <ANYCAP_API_KEY>
Content-Typeyesapplication/json
Idempotency-KeynoYour 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):

FieldTypeRequiredMeaning
modelstringyes for model-first (alternative to tier)
MeaningModel path: send 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 well
tierstringyes for tier-first (alternative to model)
MeaningTier path: send 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=model
promptstringunless an image or reference input is set
MeaningPrompt; limited by the selected source's max_prompt_characters
image_urlstringno
MeaningPublic HTTPS first-frame image, at most 8192 characters
last_frame_urlstringno
MeaningPublic HTTPS last-frame image; a first-frame image_url is required alongside it
reference_image_urlsstring[]no
MeaningUp to 8 public HTTPS reference images; the first frame is 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 request
reference_image_file_idsstring(uuid)[]no
MeaningUp to 9 reference images uploaded to Anycap, by file id
reference_video_file_idsstring(uuid)[]no
MeaningUp to 3 reference videos uploaded to Anycap, by file id. Their seconds are billed on top of the output seconds, so only owned uploads are accepted; all reference videos stay within 15 seconds and video plus output within 30
reference_audio_file_idsstring(uuid)[]no
MeaningUp to 3 reference audios uploaded to Anycap, by file id. An audio needs at least one image or video in the same request, and all reference audios together stay within 15 seconds
resolutionstringno
MeaningOmit for the selected source's default; must be supported and currently priced by it, otherwise 400
ratiostringno
MeaningOmit for the selected source's default; must be supported by it
durationintegerno
MeaningOmit for the selected source's default; never below its minimum (2 seconds) or above its maximum
audiobooleanno
MeaningGenerate audio
idempotency_keystringno
MeaningYour idempotency key: any opaque string of at most 255 bytes. The server generates one when omitted, but then a retry is a new task
resource_idstring(uuid)no (advanced)
MeaningPin the source of a 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 request
native_requestobjectno (advanced)
MeaningNative request in the model's own spelling, see section 14. It replaces the fields above; tier-first fields are not applied to it

Rules:

  • Two ways to choose — either/or, exactly one per request. Tier path: query GET /v1/videos/tiers, then send tier plus prompt (or an image/reference input). Model path: query GET /v1/videos/models, then send model plus prompt (or an image/reference input). Omitting both fails with 400 field=tier. Everything else is optional and resolved inside the chosen tier's or model's own limits.
  • model sent with tier: the model must belong to that tier, otherwise 400 with field=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-video takes a first-frame image_url only, 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_request is 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.
A tier is a ceiling: omitting a field uses that tier's default and a supplied value is executed exactly; a resolution, ratio or duration the tier does not support and price always returns 400 and is never downgraded or substituted. On the model path, that model's own published limits are the ceiling instead.

Minimal body (tier path):

JSON
{ "tier": "standard", "prompt": "A small orange cat sleeping on a windowsill" }

Minimal body (model path — model replaces tier):

JSON
{ "model": "doubao-seedance-2-0-mini-260615", "prompt": "A small orange cat sleeping on a windowsill" }

4. Create response (202)

JSON
{  "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:

JSON
{  "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.

FieldMeaning
tier
Tier name: basic / standard / premium
resolutions[]
Priced resolutions as whole credits: 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[]
Ratios the tier supports
min_duration / max_duration
Allowed output duration range
max_prompt_characters
Prompt character limit
frame_rate
Provider billing frame rate (fixed by the provider, 24 for Ark Seedance)
input_types[]
Reference kinds the model accepts: text / image / video / audio
concurrency / requests_per_minute
Upstream quotas, reported for information; the platform keeps its own limits
default_resolution / default_ratio / default_duration / audio
Defaults Anycap applies when a field is omitted

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:

JSON
{  "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    }  ]}
FieldMeaning
model
Model name. Send it as the top-level model to create with it, or as native_request.model for full control
resolutions[]
Priced resolutions as whole credits: 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 reference
ratios[]
Ratios the model supports
min_duration / max_duration
Allowed output duration range
max_prompt_characters
Prompt character limit
frame_rate
Billing frame rate; absent for per-second models
input_types[]
Input kinds the model accepts
concurrency / requests_per_minute
Concurrency and rate limits
note
Optional note
  • Use this endpoint to build either an advanced native_request (full control) or a plain model-first request: send model with prompt/resolution/ratio/duration/audio and 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/tiers stays 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_duration is 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 advanced native_request follows 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}

  • id is the task id returned at creation (it equals your idempotency_key when that key is a UUID).
  • Query parameters: none, or a single result=true that re-queries the provider and returns the temporary URL. result=false or any other parameter returns 400.
  • video_url is 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=true while 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):

FieldTypeMeaning
idstring(uuid)
MeaningTask id
resource_idstring(uuid)
MeaningSource actually used
statestring
Meaningqueued / submitting / submitted / processing / finalizing / completed / failed / pending
error_codestring
MeaningTask error code; empty on success
failure_reasonstring
MeaningFailed tasks only; closed set in section 9
duration_microsecondsstring
MeaningVerified output duration in microseconds; omitted when unknown. Output duration only, excludes input video
video_urlstring
MeaningTemporary provider HTTPS URL, only with result=true on a completed task
billing_statusstring
Meaningheld / pending / settled / released
reserved_microcreditsstring
MeaningReserved microcredits
charged_microcreditsstring
MeaningCharged microcredits
created_atstring(date-time)
MeaningCreation time (RFC 3339, UTC)

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 / finalizingWait; poll the local task every 15 seconds
completedRequest ?result=true for video_url
failedDefinitive failure; inspect error_code / failure_reason; the reservation is released
pendingRequires 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 return result_unavailable.
  • A completed task without video_url does 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 (state ends as failed, 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

BASH
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

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+)

JAVA
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 inside native_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 through POST /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.

kindFormatsSizeNotes
imageJPG, WebP, BMP20 MiBShort side at least 240 px; PNG is rejected (reference images keep no alpha channel)
videoMP4, MOV (mov container)100 MiBReal duration is billed as input when used as a reference; reference clips total at most 15 s
audioMP3, WAV15 MiBMust accompany at least one image or video; all reference audio totals at most 15 s

Response (201):

JSON
{  "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 }}
BASH
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 id in reference_image_file_ids, reference_video_file_ids, reference_audio_file_ids for generation, or video_file_id for 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.

JSON
{  "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-*):

JSON
{  "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-*):

JSON
{  "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.

HTTPMeaning
400Invalid 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)
401Invalid key
402Insufficient balance
403No permission for the source or tier
404Source or task not owned by this key
409Quote, input or idempotency conflict; or a task that is no longer cancellable
429Concurrency or rate limit
503No 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; pending waits 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.

StepMethodPath
QuotePOST/api/v1/capabilities/video.generate/quotes
SubmitPOST/api/v1/capabilities/video.generate/executions
Read a taskGET/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.

Markdown version of this page →

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

JSON
{  "model": "gemini-omni-1.2-flash-ext",  "prompt": "The camera slowly pans across the scene.",  "duration": 15,  "aspect_ratio": "9:16"}

First frame

JSON
{  "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

JSON
{  "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

JSON
{  "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

JSON
{  "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

JSON
{  "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

JSON
{  "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

JSON
{  "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.