> ## Documentation Index
> Fetch the complete documentation index at: https://docs.comfy.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Use FLUX 3 Video with Comfy Router

> Python, TypeScript and cURL snippets for generating video with synchronized audio from FLUX 3 over HTTP through Comfy Router, plus the request fields and the result shape

API Reference for FLUX 3 Video. FLUX 3 Video is Black Forest Labs' video generation model, turning a text prompt into a short clip with synchronized audio.

<Note>
  **Comfy Router is not generally available yet.** `POST /v2/models/{provider}/{model}` and its catalog and schema siblings are not serving requests yet: an authenticated call answers `404` today. The snippets on this page document the contract those routes will serve, published ahead of the rollout so your integration is ready to write against.
</Note>

## Quick start

Create a key at [platform.comfy.org/profile/api-keys](https://platform.comfy.org/profile/api-keys) and export it as `COMFY_API_KEY`. The Python and TypeScript snippets use the Comfy SDKs (`pip install comfy-sdk`, `npm install @comfyorg/sdk`); the cURL snippet is the same call over raw HTTP.

**Model ID:** `bfl/flux-3-video`

**Endpoint:** `POST https://api.comfy.org/v2/models/bfl/flux-3-video`

<CodeGroup>
  ```python Python theme={null}
  from comfy_sdk import Comfy

  # Reads COMFY_API_KEY from the environment. Each call sends a fresh
  # Idempotency-Key and waits up to 10 minutes for the finished result.
  with Comfy() as client:
      result = client.models.run(
          "bfl/flux-3-video",
          {
              "mode": "t2v",
              "prompt": "a single red maple leaf falling onto still water, slow motion",
              "duration": 5,
              "aspect_ratio": "16:9",
              "generate_audio": True,
          },
      )

  print("video:", result["result"]["sample"])
  ```

  ```typescript TypeScript theme={null}
  import { comfy } from "@comfyorg/sdk";

  // Reads COMFY_API_KEY from the environment. Each call sends a fresh
  // Idempotency-Key and waits up to 10 minutes for the finished result.
  type Result = { result: { sample: string } };
  const { data } = await comfy.models.run<Result>("bfl/flux-3-video", {
    mode: "t2v",
    prompt: "a single red maple leaf falling onto still water, slow motion",
    duration: 5,
    aspect_ratio: "16:9",
    generate_audio: true,
  });

  console.log("video:", data.result.sample);
  ```

  ```bash cURL theme={null}
  curl https://api.comfy.org/v2/models/bfl/flux-3-video \
    -H "X-API-Key: $COMFY_API_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d "{\"mode\": \"t2v\", \"prompt\": \"a single red maple leaf falling onto still water, slow motion\", \"duration\": 5, \"aspect_ratio\": \"16:9\", \"generate_audio\": true}"
  ```
</CodeGroup>

## Schema

### Input

<ParamField body="aspect_ratio" type="string" default="&#x22;auto&#x22;">
  Output aspect ratio: auto, 21:9, 2:1, 16:9, 4:3, 1:1, 3:4, or 9:16. auto lets BFL choose from the prompt and any references.
</ParamField>

<ParamField body="draft" type="boolean" default="false">
  Draft mode: generate a fast preview whose result includes a draft\_cache download URL. Send that bundle back with mode draft\_enhance to render the full-quality version of the same generation.
</ParamField>

<ParamField body="draft_cache" type="string">
  draft\_enhance only. Encrypted draft-cache bundle from a prior draft generation, as the base64-encoded downloaded bundle or its still-valid http(s) URL. The original inputs are embedded in the bundle.
</ParamField>

<ParamField body="duration" type="integer | string" default="&#x22;auto&#x22;">
  Video duration in seconds (any whole second from 5 to 20), or auto to fit the content.

  Range: `5` to `20`
</ParamField>

<ParamField body="generate_audio" type="boolean" default="true">
  Generate synchronized audio alongside the video.
</ParamField>

<ParamField body="keyframes" type="object">
  i2v only. Images that become frames of the video, each an http(s) URL or base64, one to ten total. Accepts a single image, a list of images (one starts the video, two start and end it, more spread evenly and need a set duration), or timestamped \[seconds, image] pairs in time order, e.g. \[\[0, "..."], \[3.5, "..."]].
</ParamField>

<ParamField body="mode" type="string" required>
  Generation mode: t2v (text-to-video), i2v (image-continuation), v2v (video-continuation), or draft\_enhance (full-quality render of a prior draft). Spelled-out aliases such as text-to-video are accepted.
</ParamField>

<ParamField body="prompt" type="string">
  Free-form prompt describing the video. Required for every mode except draft\_enhance.
</ParamField>

<ParamField body="resolution" type="string" default="&#x22;hd&#x22;">
  Video resolution class: hd, or fhd for a higher-resolution result finished by the video upsampler. Exact dimensions vary with the aspect ratio.
</ParamField>

<ParamField body="safety_tolerance" type="integer" default="2">
  Tolerance level for input and output harm moderation, 0 strictest. Sexual content is limited to level 3 and hate content to level 2 regardless of the requested tolerance; requests with conditioning media are limited to level 2.

  Range: `0` to `4`
</ParamField>

<ParamField body="start_video" type="string">
  v2v only. The video to continue, an http(s) URL or base64 MP4; the generated clip carries on from its final frames.
</ParamField>

<ParamField body="version" type="string" default="&#x22;latest&#x22;">
  Endpoint version. latest serves the current release; dated pinnable release tags are added as they are published.
</ParamField>

Generated from the schema Router serves at `GET /v2/models/bfl/flux-3-video/openapi.json`, the same document it validates a call against before the request reaches the provider.

### Output

<ResponseField name="cost" type="number">
  Provider-reported cost in credits, populated once the task is Ready.

  Format: `float`
</ResponseField>

<ResponseField name="id" type="string" required>
  BFL task identifier.
</ResponseField>

<ResponseField name="progress" type="number">
  Optional generation progress reported by BFL.

  Range: `0` to `1`

  Format: `float`
</ResponseField>

<ResponseField name="result" type="object | object" required>
  The finished generation. Exactly one of the two URL leaves is populated: `sample` in the default mode, `draft_cache` in `draft: true` mode.
</ResponseField>

<ResponseField name="result.cost" type="number">
  Provider-reported task cost. This is BFL's number, not the Comfy charge.

  Format: `double`
</ResponseField>

<ResponseField name="result.draft_cache" type="string (uri)">
  Signed URL returned INSTEAD of `sample` by the `draft: true` mode, re-hosted onto Comfy storage the same way `sample` is: normally a Comfy-hosted URL valid for up to 24 hours, and BFL's own roughly two-hour delivery URL when the re-host could not be performed.

  Format: `uri`
</ResponseField>

<ResponseField name="result.sample" type="string (uri)">
  Signed URL for the generated MP4. Router re-hosts the asset onto Comfy storage and rewrites this field, so it is normally a Comfy-hosted URL valid for up to 24 hours - signed for 24 hours when minted and replayed from a 23-hour memo, so a later poll can hand back one with as little as an hour left; a leaf whose re-host could not be performed keeps BFL's own roughly two-hour delivery URL instead. Absent in `draft: true` mode.

  Format: `uri`
</ResponseField>

<ResponseField name="status" type="string" required>
  Task status: Pending, Reasoning, Generating, Ready, Request Moderated, Content Moderated, Error, or Task not found. Compare case-insensitively; Router forwards BFL's spelling unchanged.
</ResponseField>

## Examples

### Input

```json theme={null}
{
  "mode": "t2v",
  "prompt": "A slow dolly shot through a rain-soaked neon street at night"
}
```

### Output

```json theme={null}
{
  "cost": null,
  "id": "3f7a1b28-5c0d-4e91-8a6f-1b2c3d4e5f60",
  "progress": null,
  "result": {
    "cost": null,
    "draft_cache": "https://example.invalid/bfl/flux-3-video/draft.mp4"
  },
  "status": "Ready"
}
```

`result.sample` is a signed URL that expires roughly two hours after the result is ready. Download the MP4 promptly.

## Before you ship

The snippets above are the shortest working call. Three things are the same for every model and are documented once on the [Comfy Router headers](/development/comfy-router/headers) page: send an `Idempotency-Key` on every paid call and reuse it when you retry, expect the connection to be held up to Router's 10 minute deadline, and keep `X-Comfy-Request-Id` from every response. The SDKs do all three for you; the cURL tab does none of them. On failure, `X-Comfy-Error-Type` names the bucket, and a `422` means the body failed the model's schema and was never billed.

<CardGroup cols={3}>
  <Card title="Headers" icon="list" href="/development/comfy-router/headers">
    Authentication, idempotency, request IDs, error buckets, retry pacing, spend limits.
  </Card>

  <Card title="Quick Start" icon="rocket" href="/development/comfy-router/quickstart">
    Typed error handling in Python and TypeScript, reading the 422, walking the catalog.
  </Card>

  <Card title="Limitations" icon="triangle-exclamation" href="/development/comfy-router/limitations">
    What Router does not do today, and what to use instead.
  </Card>
</CardGroup>
