Castaly · Blog · Guides

Generate AI Video from Code: One Modelflare Key for Every Castaly Model

Create, poll and download a video task with curl or Python, call the image models, and see how API billing shares your Castaly balance and prices.

A figure in an oversized violet coat rides down a long, empty subway escalator in a white-tiled tunnel, a frame from a Kling O1 clip.

Every model in the Castaly Studio can also be called from your own code. Castaly runs on your Modelflare account, so one Modelflare API key reaches every image and video model at the same public price, paid from the same balance.

This guide walks through a video request from start to download, then covers images, billing and the docs you will need.

What you need

  1. An API key. Sign in to Modelflare with the same account you use for Castaly and create a key. Keep it in an environment variable; the examples below read MODELFLARE_API_KEY.
  2. A paid balance. API calls draw on the paid balance you share with Castaly. Top up on either site.
  3. The model's docs page. Each model has a page at docs.modelflare.dev with its fields, limits and the exact request that produced its sample.

All requests go to https://modelflare.dev/v1 with the key as a bearer token:

Authorization: Bearer YOUR_MODELFLARE_API_KEY

Video: create, poll, download

Video generation is asynchronous. You create a task, poll it until it finishes, then download the file.

1. Create a task

This is the exact request that produced the Seedance 2.5 sample on its docs page:

curl https://modelflare.dev/v1/videos \
  -H "Authorization: Bearer $MODELFLARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.5",
    "prompt": "A small research submersible descends through the deep ocean, its headlights sweeping over a drifting field of bioluminescent jellyfish and a sunken stone archway. Camera follows from behind, particles float in the beams, blue-black water, calm and mysterious, photoreal, no text.",
    "seconds": "5",
    "duration": 5,
    "resolution": "1080p",
    "ratio": "16:9",
    "aspect_ratio": "16:9"
  }'

The response comes back at once with a task ID and a queued status:

{
  "id": "task_…",
  "task_id": "task_…",
  "object": "video",
  "model": "seedance-2.5",
  "status": "queued",
  "progress": 0
}

2. Poll until it finishes

curl https://modelflare.dev/v1/videos/TASK_ID \
  -H "Authorization: Bearer $MODELFLARE_API_KEY"

Keep polling while status is queued or in_progress, and stop at completed or failed. A failed task carries error_code and error_message. Our recorded tasks took from about one minute to just over ten, about three minutes typically, and the longest were 10-second 1080p Seedance 2.5 clips. Poll every 10 to 15 seconds rather than continuously.

3. Download the result

curl -L https://modelflare.dev/v1/videos/TASK_ID/content \
  -H "Authorization: Bearer $MODELFLARE_API_KEY" \
  -o clip.mp4

Result URLs can expire, so save the file as soon as the task completes.

The result of the request above: seedance-2.5 · 5 s · 1080p · 16:9 — 245,025 tokens, about $3.54.

The same loop in Python

import os, time, requests

BASE = "https://modelflare.dev/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["MODELFLARE_API_KEY"]}

task = requests.post(BASE + "/videos", headers=HEADERS, json={
    "model": "kling-3.0",
    "prompt": "Stop-motion claymation style: a small orange clay fox sneaks "
              "through a miniature felt forest, no text.",
    "seconds": "5",
    "duration": 5,
    "resolution": "720p",
    "ratio": "16:9",
    "aspect_ratio": "16:9",
}).json()

while True:
    status = requests.get(BASE + "/videos/" + task["task_id"], headers=HEADERS).json()
    if status["status"] in ("completed", "failed"):
        break
    time.sleep(15)

if status["status"] == "completed":
    video = requests.get(BASE + "/videos/" + task["task_id"] + "/content", headers=HEADERS)
    open("clip.mp4", "wb").write(video.content)
else:
    print(status.get("error_code"), status.get("error_message"))

Each family has its own options

The simple fields above are enough for text-to-video, and most video model pages show a working request in this shape. Beyond that, each family uses its provider's own structure, and Modelflare forwards it as written:

Family Frames, references and extras
Seedance content[] with role on each image, video or audio item; generate_audio; on Seedance 2.5, omni_reference_task_type for edit and extend
Kling model_name, mode, image, image_tail, video_url, image_list, sound
Wan and HappyHorse input with prompt and media[], plus parameters; HappyHorse accepts parameters.watermark: false
MiniMax H3 content[] with roles, plus resolution, duration and ratio

Do not mix shapes inside one request, and read the model's page before adding fields: invalid parameters return a 4xx error with a request ID.

Images

GPT Image, Seedream and Wan image models use the OpenAI-style images endpoint and return in one call:

curl https://modelflare.dev/v1/images/generations \
  -H "Authorization: Bearer $MODELFLARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2.5-flare",
    "prompt": "Picture-book illustration of a small fox carrying a paper lantern through a snowy birch forest at dusk, no text.",
    "size": "1536x1024",
    "quality": "medium",
    "n": 1
  }'

GPT Image returns Base64 image data in data[].b64_json. Gemini image models use Google's native generateContent request instead; their docs pages give the endpoint and body.

Billing through the API

  • Same prices as the Studio. An API call to a model ID is billed at the public price shown on the pricing page.
  • Same estimate, hold and settlement. The gateway holds an estimate when the task starts, settles on the usage the provider reports, and returns the difference. Failed tasks are refunded in full.
  • Different gift balance. API calls spend your Modelflare gift balance first, then your paid balance. Castaly gift balance only pays for generations in Castaly.

The billing guide covers holds and refunds in detail.

Using an AI agent instead

If you work with Claude Code, Codex or another agent that reads SKILL.md files, the Modelflare Media Skill teaches it to pick a model, quote the price, submit the request, wait for videos and save the result. It is generated from the live catalog, so its model list and prices stay current. Castaly's Connect any agent page walks through installing it.

Set up an agent from Castaly →

FAQ

Is the API more expensive than the Studio?

No. Both use the same public price for each model ID.

Do I need a separate account or balance for the API?

No. Castaly runs on your Modelflare account. Create a key there and calls use the paid balance you already share with Castaly.

How do I know a video task has failed?

The poll response has status: "failed" with error_code and error_message. The hold for a failed task is refunded in full.

Where do I find the exact fields for a model?

On its page at docs.modelflare.dev, which lists every field, its limits and a request that produced a real sample.