Api.Airforce
API REFERENCE

동영상

비동기 작업 모델을 사용하여 비디오 클립을 생성합니다. 프롬프트를 제출하고, 상태를 폴링하고, 결과를 가져옵니다.

비디오 생성은 백그라운드에서 실행되며 스트리밍 렌더링이 없습니다. 흐름은 항상 다음과 같습니다. 작업 생성 → 상태 폴링 → MP4 다운로드. 작업은 24시간 후에 만료됩니다.

1. 작업 만들기

작업을 제출하고 태스크 ID를 반환합니다. 비용은 선택한 모델의 기간 × 초당 가격을 기준으로 선불로 차감됩니다.

POSThttps://api.airforce/v1/video/generations

비디오 모델

· live
ParameterTypeRequiredDescription
modelstringRequiredVideo model ID. Use /v1/models and filter by output_modalities.includes("video").
promptstringRequiredScene description.
modestringOptional"text" (default), "image" (animate a first-frame image), "reference" (style transfer from one or more frames).
duration_secondsintegerOptionalClip length. Range depends on the model — typically 5, 8 or 10 s. Defaults to the model's minimum.
aspect_ratiostringOptional"16:9", "9:16", "1:1", "4:3" — must be in the model's supported list.
qualitystringOptional"480p", "720p", "1080p" — must be in the model's supported list.
input_imagesarrayOptional[{ url? } | { b64_json? }] — required for "image" and "reference" modes.
seedintegerOptionalReproducibility seed where supported.
soundbooleanOptionalEnable native audio track on models that produce sound (e.g. wan).

텍스트-비디오

curl https://api.airforce/v1/video/generations \
  -H "Authorization: Bearer sk-air-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "wan-2.6",
    "prompt": "A red fox darting across snowy hills at dawn",
    "duration_seconds": 8,
    "aspect_ratio": "16:9",
    "quality": "720p",
    "sound": true
  }'

이미지-비디오(첫 번째 프레임)

curl https://api.airforce/v1/video/generations \
  -H "Authorization: Bearer sk-air-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-1",
    "mode": "image",
    "prompt": "Camera pulls back as the dragon takes off",
    "duration_seconds": 5,
    "aspect_ratio": "16:9",
    "input_images": [{"url": "https://example.com/dragon.jpg"}]
  }'

응답

ParameterTypeRequiredDescription
task_idstringOptionalPersistent task identifier. Use it on every follow-up endpoint.
statusstringOptional"queued" right after creation.
modelstringOptionalEcho of requested model.
createdintegerOptionalUnix timestamp.
expires_atintegerOptionalUnix timestamp after which the result is purged (typically created + 86400).
cost_centsnumberOptionalUp-front cost debited from your balance. Refunded if the task ultimately fails.
{
  "task_id": "vid_01HXY1234ABCD",
  "status": "queued",
  "model": "wan-2.6",
  "created": 1715000000,
  "expires_at": 1715086400,
  "cost_cents": 320
}

2. 상태 폴링

5~15초마다 폴링합니다. 작업은 일반적으로 기간과 모델에 따라 30초~4분 내에 완료됩니다. 상태가 "완료"로 전환되면 동일한 엔드포인트가 결과 URL을 반환합니다.

GEThttps://api.airforce/v1/video/tasks/:task_id
ParameterTypeRequiredDescription
statusstringOptional"queued" | "running" | "completed" | "failed" | "expired".
progressintegerOptional0–100 while running. Absent for queued tasks.
result_urlstringOptionalMP4 download URL once status is "completed". Pre-signed; valid until expires_at.
thumbnail_urlstringOptionalOptional poster frame.
errorobjectOptionalSet when status is "failed". { type, message }.
cost_centsnumberOptionalFinal cost. Equals the create-time cost on success.
{
  "task_id": "vid_01HXY1234ABCD",
  "status": "completed",
  "progress": 100,
  "result_url": "https://cdn.api.airforce/video/vid_01HXY1234ABCD.mp4",
  "thumbnail_url": "https://cdn.api.airforce/video/vid_01HXY1234ABCD.jpg",
  "model": "wan-2.6",
  "duration_seconds": 8,
  "expires_at": 1715086400,
  "cost_cents": 320
}

2b. 스트림 진행(선택사항)

서버에서 보낸 이벤트 스트림을 사용하여 폴링 루프를 건너뜁니다. 진행률 변경당 하나의 이벤트를 내보내고 작업이 종료 상태가 되면 닫힙니다. GET 엔드포인트와 동일한 페이로드 형태.

GEThttps://api.airforce/v1/video/tasks/:task_id/stream
event: progress
data: {"task_id":"vid_01HXY...","status":"running","progress":12}

event: progress
data: {"task_id":"vid_01HXY...","status":"running","progress":58}

event: completed
data: {"task_id":"vid_01HXY...","status":"completed","progress":100,"result_url":"https://cdn.api.airforce/video/vid_01HXY....mp4"}

3. 나열 및 삭제

GEThttps://api.airforce/v1/video/tasks

최근 작업을 반환합니다(최신 작업부터). 대시보드에서 기록 보기를 렌더링하는 데 유용합니다.

ParameterTypeRequiredDescription
limitintegerOptionalMax items returned. Default 50, max 200. Pass as a query string.
statusstringOptionalFilter to one status, e.g. ?status=running.
curl "https://api.airforce/v1/video/tasks?limit=20&status=completed" \
  -H "Authorization: Bearer sk-air-YOUR_API_KEY"
DELETEhttps://api.airforce/v1/video/tasks/:task_id

기록에서 작업을 제거합니다. MP4는 CDN 저장소에서도 삭제됩니다. 환불 불가 — 비용이 이미 인출되었습니다.


비용 및 제약

각 비디오 모델은 읽을 수 있는 기능 메타데이터를 노출합니다. /v1/models:

ParameterTypeRequiredDescription
video_caps.aspect_ratiosarrayOptionalAllowed aspect_ratio values.
video_caps.qualitiesarrayOptionalAllowed quality values.
video_caps.min_duration_s / max_duration_sintegerOptionalAllowed range for duration_seconds.
video_caps.modesarrayOptionalSubset of ["text", "image", "reference"] supported.
video_caps.price_per_second_centsintegerOptionalCost = duration_seconds × this value.
  • Cost is debited at task creation. Failed tasks (status "failed" or "expired") refund the cost.
  • Max 4 concurrent video tasks per API key.
  • Result URLs are pre-signed and stop working at expires_at. Download or copy the MP4 to your own storage if you need it longer.

엔드투엔드 스크립트

async function generateVideo(prompt) {
  const create = await fetch('https://api.airforce/v1/video/generations', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'wan-2.6',
      prompt,
      duration_seconds: 8,
      aspect_ratio: '16:9',
      quality: '720p',
    }),
  }).then(r => r.json());

  const { task_id } = create;

  // Poll until done.
  while (true) {
    await new Promise(r => setTimeout(r, 8_000));
    const task = await fetch(
      `https://api.airforce/v1/video/tasks/${task_id}`,
      { headers: { Authorization: `Bearer ${API_KEY}` } },
    ).then(r => r.json());

    if (task.status === 'completed') return task.result_url;
    if (task.status === 'failed' || task.status === 'expired') {
      throw new Error(task.error?.message ?? task.status);
    }
  }
}