API 金鑰只能放在服務端環境變數或金鑰管理服務中,不得寫進瀏覽器包、Git、日誌或截圖。

官方 SDK 快速上手

The official SDKs wrap the one-step contract (create → poll → download) with automatic idempotency keys and typed errors; the Node SDK has zero dependencies and Python depends only on httpx. Distributed as GitHub repositories for now — npm/PyPI releases will be announced separately.

Node

npm install github:openaiav/sdk-node   # npm 正式发布另行公告

import { OpenAiav } from '@openaiav/sdk'
const client = new OpenAiav({ apiKey: process.env.OPENAIAV_API_KEY })
const task = await client.generations.createAndWait({
  model: 'seedance-2.5-oa', prompt: 'She walks into the sunlight.',
  resolution: '480p', aspectRatio: 'adaptive', durationSeconds: 4,
  generateAudio: false
})
await client.generations.downloadToFile(task.id, './out.mp4')

Python

pip install git+https://github.com/openaiav/sdk-python   # PyPI 正式发布另行公告

from openaiav import OpenAiav
client = OpenAiav(os.environ["OPENAIAV_API_KEY"])
task = client.generations.create_and_wait({
    "model": "seedance-2.5-oa", "prompt": "She walks into the sunlight.",
    "resolution": "480p", "aspectRatio": "adaptive", "durationSeconds": 4,
    "generateAudio": False,
})
client.generations.download_to_file(task["id"], "./out.mp4")

四步接入

  1. 使用服務端環境變數 OPENAIAV_API_KEY 呼叫 https://api.openaiav.com/v1/models,讀取當前模型鍵、計價與 reference_modes。
  2. 向 POST /v1/generations 提交 prompt、referenceMode 與 referenceImages;參考圖是公網 HTTPS URL,不需要預註冊。建立成功為 HTTP 201。
  3. 儲存響應 id,按 poll_after_ms 對同一個 GET /v1/generations/{id} 輪詢。processing、result_pending、submission_unknown 都繼續等待,不要重新建立。
  4. 狀態變為 succeeded 後呼叫 GET /v1/generations/{id}/content 下載;完整響應為 HTTP 200,單區間 Range 為 206。

認證與冪等

export OPENAIAV_API_KEY='oav_...'
export OPENAIAV_IDEMPOTENCY_KEY='openaiav-quickstart-4s-480p-001'

每個請求都帶 Authorization: Bearer oav_...。金鑰只放在服務端。建立任務需要 generation:create,查詢和下載需要 generation:read。網路結果不確定時複用原 Idempotency-Key;同一個鍵不得配不同請求體。

Request headers

引數型別必填說明
Authorizationstring必填所有 /v1 請求均使用 Bearer oav_...;金鑰只儲存在服務端。
Idempotency-Keystring僅建立任務必填網路重試必須複用同一個值;同值同請求體不會重複生成或重複扣費。
Content-Typestring僅 POST 必填建立任務使用 application/json

端點一覽

MethodPathSuccessScope說明
GET/v1/models200valid API key讀取當前可售模型、價格、解析度、時長與 reference_modes。提交前必須按目錄校驗能力。
POST/v1/generations201generation:create建立非同步任務;參考圖與 referenceMode 在同一個 JSON 請求中提交。
GET/v1/generations/{id}200generation:read按響應中的 poll_after_ms 查詢同一任務,直到終態。
GET/v1/generations/{id}/content200 / 206generation:read任務成功後下載輸出;單區間 Range 請求返回 206。

第一步:讀取模型能力

不要寫死模型能力。只有 reference_modes 列出的模式可以提交;介面也應在提交前隱藏或攔截不相容組合。最小示例固定演示 seedance-2.5 的 4 秒、480p、無音訊請求。

curl --fail-with-body 'https://api.openaiav.com/v1/models' \
  --header "Authorization: Bearer $OPENAIAV_API_KEY"

最小公網影片示例

完整鏈路在同一個示例裡:建立 → 輪詢同一任務 → 下載。 first_frame 使用一張參考圖和 adaptivegenerateAudio=false 避免請求音訊。建立、輪詢、下載的成功狀態分別是 201、200、200/206;失敗響應先讀取 HTTP,再讀取 error.code

# Keep both values in environment variables; do not paste secrets into shell history.
# Generate OPENAIAV_IDEMPOTENCY_KEY once for this create intent and keep it unchanged on every retry.
# Set it before the first create, then reuse the exact value after a lost response.
# 1. Create — success: HTTP 201. On failure, the response body contains error.code.
curl --fail-with-body --request POST 'https://api.openaiav.com/v1/generations' \
  --header "Authorization: Bearer $OPENAIAV_API_KEY" \
  --header "Idempotency-Key: $OPENAIAV_IDEMPOTENCY_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "seedance-2.5",
  "prompt": "女孩写完一封信,从乡间石屋走入清晨阳光",
  "resolution": "480p",
  "aspectRatio": "adaptive",
  "durationSeconds": 4,
  "referenceMode": "first_frame",
  "referenceImages": [
    "https://developers.openaiav.com/samples/seedance-letter-reference.webp"
  ],
  "generateAudio": false,
  "outputFormat": "mp4"
}'

# 2. Save the returned id as TASK_ID. Poll the same id — success: HTTP 200.
curl --fail-with-body 'https://api.openaiav.com/v1/generations/TASK_ID' \
  --header "Authorization: Bearer $OPENAIAV_API_KEY"

# Repeat step 2 after poll_after_ms until status is succeeded or failed.
# Never recreate a task whose status is submission_unknown.

# 3. After succeeded, download — success: HTTP 200 (or 206 with Range).
curl --fail-with-body --location 'https://api.openaiav.com/v1/generations/TASK_ID/content' \
  --header "Authorization: Bearer $OPENAIAV_API_KEY" \
  --output 'result.mp4'

請求引數

引數型別必填說明
modelstring必填取自 GET /v1/modelsmodel;最小影片示例使用 seedance-2.5
promptstring必填1–4000 字元。全能參考可按陣列順序用 @Image1@Image2 指代圖片。
resolutionstring可選必須屬於所選模型的 resolutions;最小影片示例使用 480p
aspectRatiostring可選必須屬於所選模型的 aspect_ratios。圖片模型同樣生效;當所選模型的首幀能力要求自適應畫幅時使用 adaptive
durationSecondsinteger可選影片省略時使用模型最小時長;顯式值必須在目錄的 duration_seconds 區間內。最小示例使用 4 秒。
referenceModefirst_frame | omni_reference使用影片參考圖時必填只在目錄 reference_modes 明確列出的 Seedance 影片模型上使用。一次請求只能選擇一個模式。
referenceImagesstring[]與 referenceMode 同時填寫公網 HTTPS 圖片 URL。first_frame 必須且只能 1 張;omni_reference 上限讀取 reference_images_max
inputImagesstring[]可選僅圖片模型的圖生圖輸入,可用 HTTPS 或 data:image/*;上限讀取 input_images_max,不得與影片參考模式混用。
generateAudioboolean可選支援音訊的影片模型省略時預設 true。最經濟示例顯式傳 false;當前目錄沒有單列音訊附加價,計費始終以 GET /v1/models 為準。
outputFormatmp4 | mov可選只能選擇目錄 output_formats 中的值;最小示例使用 mp4

參考素材模式

first_frame

first_frame:參考圖成為起始畫面並決定構圖。必須且只能提交 1 張 referenceImagesaspectRatio 取自所選模型的 aspect_ratios,目錄含 adaptive 時鎖定為 adaptive(輸出跟隨參考圖畫幅)。 first_last_frame:提交恰好 2 張 referenceImages按陣列順序分別是首幀與尾幀,中間畫面由模型補全。兩張圖不要求同尺寸。幀模式與 omni_reference 互斥。

{
  "model": "seedance-2.5",
  "prompt": "女孩写完一封信,从乡间石屋走入清晨阳光",
  "resolution": "480p",
  "aspectRatio": "adaptive",
  "durationSeconds": 4,
  "referenceMode": "first_frame",
  "referenceImages": [
    "https://developers.openaiav.com/samples/seedance-letter-reference.webp"
  ],
  "generateAudio": false,
  "outputFormat": "mp4"
}

omni_reference

omni_reference:參考素材用於鎖定主體、風格與場景的一致性,不要求成為首幀。除 referenceImages 外,支援的模型還可傳 referenceVideosreferenceAudios;各類上限見下表,目錄未宣告的型別提交即 400。提示詞按同類型內的陣列順序引用 @Image1@Video1@Audio1

{
  "model": "seedance-2.5",
  "prompt": "@Image1 保持人物身份与服装一致,女孩从乡间石屋走入清晨阳光",
  "resolution": "480p",
  "aspectRatio": "16:9",
  "durationSeconds": 4,
  "referenceMode": "omni_reference",
  "referenceImages": [
    "https://developers.openaiav.com/samples/seedance-letter-reference.webp"
  ],
  "generateAudio": false,
  "outputFormat": "mp4"
}

Live compatibility

接入方式對所有影片模型是同一套:同一個端點、同一組欄位,換模型只改 model。差異全部由目錄宣告——下表就是目錄本身,逐個模型列出它支援哪些參考模式、各類素材收幾個。目錄沒宣告的能力,提交時會被明確拒絕,不會靜默忽略。

The catalog is not loaded. Call GET /v1/models first; do not submit a reference mode for a model without reference_modes.

First-frame details & last-frame relay

首幀細則:first_frameomni_reference 互斥,同一請求只能選其一;omni 下可用提示詞間接引導某張參考圖作起始畫面,但需要嚴格首幀一致時,請使用 first_frame 模式提交那張圖。Seedance 2.5 的首幀任務畫幅固定 adaptive(輸出跟隨首幀)。尾幀接力:建立時傳 returnLastFrame: true,成功後任務額外返回 last_frame_url(與影片同寬高的無水印 PNG,保留 24 小時)——把這個 URL 直接作為下一單 first_framereferenceImages,即可串聯多鏡頭連續敘事,無需任何預註冊步驟。

輪詢與下載

succeededfailed 才是終態。submission_unknown 是待對賬狀態:保留原任務 ID,繼續輪詢,絕不能重放建立請求。成功後優先使用鑑權下載路徑 /content,不要依賴任何非 Open AIav 地址。產物保留 24 小時(詳情返回 output_expires_at 倒計時;過期後下載返回 410 OUTPUT_EXPIRED,請及時轉存)。

StatusTerminalAction
processingNo已受理;按 poll_after_ms 繼續查詢。
result_pendingNo輸出正在完成結算;繼續查詢同一任務。
submission_unknownNo結果待對賬;不要重放建立請求,繼續保留並查詢原任務 ID。
succeededYes成功;使用 /content 下載輸出。
failedYes確定失敗且預留金額已退回;讀取 error_code

舊端點遷移

/v1/assets/v1/assets/content/v1/assets/{id}/v1/asset-groups/v1/asset-groups/{id} 已退役;使用有效金鑰及相應舊 scope 時返回 HTTP 410 / ENDPOINT_RETIRED。新接入不得呼叫這些路徑;把 referenceModereferenceImages 放進同一次生成請求。

錯誤碼對照

Full reference: HTTP status, code, meaning, suggested handling, and the SDK error class. This table shares its data source with the SDK error map; unknown new codes fall back by HTTP status in the SDK.

HTTPCode含義Suggested handlingSDK
401UNAUTHENTICATEDMissing or unrecognized API key.Send Authorization: Bearer oav_…; keep the key server-side.AuthenticationError
401INVALID_API_KEYThe API key is invalid or revoked.Check the key in the console; rotate to mint a new one if needed.AuthenticationError
403INSUFFICIENT_SCOPEThe key lacks the scope this operation needs.Creation needs generation:create; polling and download need generation:read.PermissionError
429RATE_LIMITEDRequests exceeded the key rate limit.Back off per Retry-After / retryAfterSeconds; the SDK handles this automatically.RateLimitError
400IDEMPOTENCY_KEY_REQUIREDCreation requires an Idempotency-Key header.Generate a unique key per new request and reuse it on retries. The SDK auto-generates one.InvalidRequestError
409IDEMPOTENCY_KEY_CONFLICTThe same idempotency key was used with a different body.Use a fresh key for different parameters; keep key and body identical on retries.InvalidRequestError
400MODEL_NOT_FOUNDUnknown model id.Use ids from GET /v1/models (e.g. seedance-2.5-oa).InvalidRequestError
400INVALID_PROMPTThe prompt is empty or too long.Prompts must be 1–4000 characters.InvalidRequestError
400INVALID_DURATIONdurationSeconds is outside the model range.Use an integer within the catalog range, or -1 when auto duration is supported.InvalidRequestError
400INVALID_RESOLUTIONThe resolution is not supported by the model.Pick a value from the catalog resolutions.InvalidRequestError
400INVALID_ASPECT_RATIOThe aspect ratio is not supported by the model.Pick from catalog aspect_ratios; first_frame often locks adaptive.InvalidRequestError
400INVALID_REFERENCE_IMAGESreferenceImages must be an array of public HTTPS URLs.Provide https:// image URLs readable for the task lifetime.InvalidRequestError
400INVALID_REFERENCE_IMAGEA reference image entry is not a valid URL.The message carries the index (referenceImages[i]); fix that entry.InvalidRequestError
400REFERENCE_IMAGE_URL_NOT_HTTPSA reference image URL is not public HTTPS.http, private-network and data URLs are rejected; host the image publicly over HTTPS.InvalidRequestError
400REFERENCE_MODE_REQUIRES_IMAGESreferenceMode was set without reference images.Provide referenceMode and referenceImages together.InvalidRequestError
400REFERENCE_MODE_NOT_SUPPORTEDThe model does not support the requested reference mode.Choose first_frame / omni_reference per the catalog reference_modes.InvalidRequestError
400FIRST_FRAME_REQUIRES_ONE_IMAGEfirst_frame takes exactly one reference image.Submit exactly one image; use omni_reference for multiple.InvalidRequestError
400TOO_MANY_REFERENCESReference image count exceeds the catalog limit.See reference_images_max in the catalog.InvalidRequestError
400INVALID_INPUT_IMAGESinputImages must be an array.Each item is an HTTPS URL or data:image/* base64.InvalidRequestError
400INVALID_INPUT_IMAGEAn input image entry is malformed.Each entry must be an HTTPS URL or data:image/* base64; the message carries the index.InvalidRequestError
400INPUT_IMAGE_TOO_LARGEAn embedded image exceeds 10 MB.Compress it or switch to a public HTTPS URL.InvalidRequestError
400IMAGE_INPUT_NOT_SUPPORTEDThe model does not accept image input.Only image models with input_images_max>0 accept inputImages.InvalidRequestError
400TOO_MANY_INPUT_IMAGESToo many input images.See input_images_max in the catalog.InvalidRequestError
400INSUFFICIENT_BALANCEBalance is insufficient to reserve this task.Redeem a top-up card on the Billing page, then retry.InvalidRequestError
400LEGACY_ASSET_REFERENCE_RETIREDAsset-id references are retired.Submit referenceMode + referenceImages (public HTTPS) in the same request.InvalidRequestError
404NOT_FOUNDThe task does not exist or belongs to another account.Confirm the task id and the key belong to the same account.InvalidRequestError
409OUTPUT_NOT_READYThe output is not ready yet.Keep polling the task per poll_after_ms until terminal.InvalidRequestError
410OUTPUT_EXPIREDThe download window (24h after success) has closed.Save outputs promptly; regenerate after expiry. Use output_expires_at for countdowns.OutputExpiredError

Console-session-only codes

HTTPCode含義Suggested handling
400REFERENCE_UPLOAD_NOT_FOUNDThe upload reference is missing, expired, or owned by another account.Re-upload in the Playground and run again (uploads are short-lived).
429UPLOAD_QUOTA_EXCEEDEDToo many unused uploads.Run a task to consume uploads, or wait for them to expire.
429WEBHOOK_ENDPOINT_LIMITWebhook endpoint limit reached.Delete or disable an unused endpoint.
400INVALID_WEBHOOK_URLThe callback URL is not publicly reachable HTTPS.Use a public HTTPS address; private/loopback hosts are rejected.