Video Generation

Generate video clips from a text prompt with Qubax. Because video synthesis is asynchronous, the endpoint follows an async pattern: you submit a generation job with a POST request, poll its status, and finally download the finished artifact.

⚠️
Video generation is asynchronous and typically takes minutes per clip. Do not hold the request open — poll the status endpoint with backoff instead.

Async Pattern

The workflow has three steps:

Text
1. POST   /v1/video/generations        →  returns a job ID (status: "pending")
2. GET    /v1/video/generations/{id}    →  poll until status is "completed" or "failed"
3. GET    /v1/media/artifacts/{jobId}/{index}  →  download the finished video bytes

All requests require an API key passed as a Bearer token in the Authorization header:

Text
Authorization: Bearer qbx_live_...

1. Create a Job

Text
POST https://api.qubax.ai/v1/video/generations
ParameterTypeRequiredDescription
modelstringYesID of the video model to use (e.g. runway-gen4-5-text).
promptstringYesText description of the desired video motion and scene.
ℹ️
Some models accept additional parameters such as duration, aspect_ratio, or an image seed. Unsupported parameters are ignored. Model availability can be discovered via GET /v1/models.

Python SDK Example

Using requests to submit the job, poll for status, and finally download the artifact:

Python
import time
import requests

BASE = "https://api.qubax.ai/v1"
HEADERS = {"Authorization": "Bearer qbx_live_..."}

# 1. Create the generation job
resp = requests.post(
    f"{BASE}/video/generations",
    headers=HEADERS,
    json={"model": "runway-gen4-5-text", "prompt": "ocean waves crashing on a reef at sunset"},
)
job = resp.json()
job_id = job["id"]
print("Created job:", job_id)

# 2. Poll for status until terminal
poll_url = f"{BASE}/video/generations/{job_id}"
while True:
    status = requests.get(poll_url, headers=HEADERS).json()
    state = status["status"]
    print("status:", state)
    if state in ("completed", "failed"):
        break
    time.sleep(10)

if state != "completed":
    raise RuntimeError("Video generation failed:", status)

# 3. Download the finished artifact(s)
output_count = status.get("output_count", 1)
for i in range(output_count):
    dl = requests.get(f"{BASE}/media/artifacts/{job_id}/{i}", headers=HEADERS)
    with open(f"video_{job_id}_{i}.mp4", "wb") as f:
        f.write(dl.content)
print("Done.")

cURL Example

Create the job and capture the returned id:

Shell
curl https://api.qubax.ai/v1/video/generations \
  -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  -d '{
    "model": "runway-gen4-5-text",
    "prompt": "ocean waves crashing on a reef at sunset"
  }'

Poll the status endpoint until the job is completed:

Shell
curl https://api.qubax.ai/v1/video/generations/{id} \
  -H "Authorization: Bearer ***

Once complete, download the artifact by index (typically 0):

Shell
curl https://api.qubax.ai/v1/media/artifacts/{jobId}/0 \
  -H "Authorization: Bearer *** \
  -o video.mp4

2. Poll Status

Text
GET https://api.qubax.ai/v1/video/generations/{id}

The status field moves through the values below. Re-poll with backoff until it reaches a terminal state.

StatusMeaning
pendingJob accepted and queued, not yet started.
processingThe model is actively generating frames.
completedArtifacts are ready for download.
failedGeneration failed; see error in the status body.

3. Download Artifact

Text
GET https://api.qubax.ai/v1/media/artifacts/{jobId}/{index}

{jobId} is the job ID returned at creation, and {index} is a zero-based artifact selector. Most jobs produce a single clip at index 0; the completed status body reports the available count.

Status Response Shape

A completed status response looks like:

JSON
{
  "id": "vg_abc123",
  "model": "runway-gen4-5-text",
  "status": "completed",
  "output_count": 1,
  "created_at": 1719792000,
  "completed_at": 1719792120
}

When status is failed, an error object is present describing the cause:

JSON
{
  "id": "vg_abc123",
  "status": "failed",
  "error": {
    "message": "Content policy violation in prompt.",
    "type": "invalid_request_error"
  }
}