Overview

Poll the status of an asynchronous video generation run. Use the runId you received from POST /generate-video along with the modelSlug you used to start the job. When the run completes, the response includes data.output.video.url.

Query parameters

  • runId (string, required): The run identifier returned by the submit call
  • modelSlug (string, required): The model used for the run (e.g., veo2-video)

Usage

import requests
import time

BASE = "https://nano-gpt.com/api"

def get_video_status(run_id: str, model_slug: str, api_key: str) -> dict:
    resp = requests.get(
        f"{BASE}/generate-video/status",
        headers={"x-api-key": api_key},
        params={"runId": run_id, "modelSlug": model_slug},
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()


def wait_for_video(run_id: str, model_slug: str, api_key: str, max_attempts: int = 120, delay_s: int = 5) -> str:
    for i in range(max_attempts):
        data = get_video_status(run_id, model_slug, api_key)
        status = data.get("data", {}).get("status")
        if status == "COMPLETED":
            return data["data"]["output"]["video"]["url"]
        if status == "FAILED":
            raise RuntimeError(data.get("data", {}).get("error", "Video generation failed"))
        time.sleep(delay_s)
    raise TimeoutError("Video generation timed out")

Status values

  • IN_QUEUE: Request queued
  • IN_PROGRESS: Generation in progress
  • COMPLETED: Video ready
  • FAILED: Generation failed
  • CANCELLED: Request cancelled

Response examples

In progress

{
  "data": {
    "status": "IN_PROGRESS",
    "request_id": "fal-request-abc123xyz"
  }
}

Completed

{
  "data": {
    "status": "COMPLETED",
    "request_id": "fal-request-abc123xyz",
    "output": {
      "video": {
        "url": "https://storage.example.com/video.mp4"
      }
    }
  }
}

Failed

{
  "data": {
    "status": "FAILED",
    "request_id": "fal-request-abc123xyz",
    "error": "Content policy violation",
    "isNSFWError": true,
    "userFriendlyError": "Content flagged as inappropriate. Please modify your prompt and try again."
  }
}

Notes

  • Polling this endpoint is free; submission endpoints are rate limited.
  • The final video URL is returned in data.output.video.url when status is COMPLETED.