> ## 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 Crystal Video Upscaler with Comfy Router

> Call fal/crystal-video-upscaler through Comfy Router: endpoint, request shape and the response Router returns.

API Reference for `fal/crystal-video-upscaler`, served by Comfy Router from fal.

**Input:** Video · **Output:** Video

## Quick start

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

**Model ID:** `fal/crystal-video-upscaler`

**Endpoint:** `POST https://api.comfy.org/v2/models/fal/crystal-video-upscaler`

<Tabs defaultTabIndex={1}>
  <Tab title="Wait for the result">
    <CodeGroup>
      ```python Python theme={null}
      from comfy_sdk import Comfy

      # Reads COMFY_API_KEY from the environment.
      # The SDK automatically creates an idempotency key and reuses it for automatic retries.
      with Comfy() as client:
          result = client.models.run(
              "fal/crystal-video-upscaler",
              {
                  "scale_factor": 2,
                  "video_url": "https://storage.googleapis.com/falserverless/example_inputs/crystal_upscaler/video_upscaling/video_in.mp4",
              },
          )

      print(result)
      ```

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

      // Reads COMFY_API_KEY from the environment.
      // The SDK automatically creates an idempotency key and reuses it for automatic retries.
      const { data } = await comfy.models.run("fal/crystal-video-upscaler", {
        scale_factor: 2,
        video_url: "https://storage.googleapis.com/falserverless/example_inputs/crystal_upscaler/video_upscaling/video_in.mp4",
      });

      console.log(data);
      ```

      ```bash cURL theme={null}
      curl https://api.comfy.org/v2/models/fal/crystal-video-upscaler \
        -H "X-API-Key: $COMFY_API_KEY" \
        -H "Idempotency-Key: $(uuidgen)" \
        -H "Content-Type: application/json" \
        -d "{\"scale_factor\": 2, \"video_url\": \"https://storage.googleapis.com/falserverless/example_inputs/crystal_upscaler/video_upscaling/video_in.mp4\"}"
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Queue and collect later">
    The same body, sent to `POST https://api.comfy.org/v2/models/fal/crystal-video-upscaler/requests`. Router answers `201` with a `request_id` as soon as the run is admitted, and the result is collected once it is ready, from this process or another one. [Queued delivery](/development/comfy-router/queue) walks through status, cancellation and collection.

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

      # Reads COMFY_API_KEY from the environment.
      # Each submit() call mints its own Idempotency-Key and reuses it for automatic retries.
      async def main():
          async with AsyncComfy() as client:
              handle = await client.models.submit(
                  "fal/crystal-video-upscaler",
                  {
                      "scale_factor": 2,
                      "video_url": "https://storage.googleapis.com/falserverless/example_inputs/crystal_upscaler/video_upscaling/video_in.mp4",
                  },
              )
              print("request_id:", handle.request_id)  # with the model ID, all another process needs

              # Poll until the request completes, waiting the Retry-After the server names.
              async for update in handle.iter_events():
                  print(update.status, update.queue_position)

              # The provider's own payload, the same value models.run() returns.
              # A request that failed or was cancelled raises the typed Router error here.
              result = await handle.get()

          print(result)

      asyncio.run(main())
      ```

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

      // Reads COMFY_API_KEY from the environment.
      // Each submit() call mints its own Idempotency-Key and reuses it for automatic retries.
      const handle = await comfy.models.submit("fal/crystal-video-upscaler", {
        scale_factor: 2,
        video_url: "https://storage.googleapis.com/falserverless/example_inputs/crystal_upscaler/video_upscaling/video_in.mp4",
      });
      console.log("requestId:", handle.requestId); // with the model ID, all another process needs

      // Poll until the request completes, waiting the Retry-After the server names.
      for await (const update of handle.events()) {
        console.log(update.status, update.queuePosition);
      }

      // The same result models.run() returns. A request that failed or was cancelled rejects here.
      const result = await handle.get();

      console.log(result.data);
      ```

      ```bash cURL theme={null}
      # 1. Submit. Router answers 201 with request_id, status_url, response_url and cancel_url.
      curl https://api.comfy.org/v2/models/fal/crystal-video-upscaler/requests \
        -H "X-API-Key: $COMFY_API_KEY" \
        -H "Idempotency-Key: $(uuidgen)" \
        -H "Content-Type: application/json" \
        -d "{\"scale_factor\": 2, \"video_url\": \"https://storage.googleapis.com/falserverless/example_inputs/crystal_upscaler/video_upscaling/video_in.mp4\"}"

      # 2. Poll until status is COMPLETED, waiting the Retry-After seconds each response names.
      REQUEST_ID="<request_id from the 201 body>"
      curl -i https://api.comfy.org/v2/models/fal/crystal-video-upscaler/requests/$REQUEST_ID/status \
        -H "X-API-Key: $COMFY_API_KEY"

      # 3. Collect. 200 with the model's native output, 202 with the status body while it is still running.
      curl https://api.comfy.org/v2/models/fal/crystal-video-upscaler/requests/$REQUEST_ID \
        -H "X-API-Key: $COMFY_API_KEY"
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Schema

### Input

<ParamField body="scale_factor" type="number" default="2">
  Factor applied to each side of the input video. The upscaled video must not exceed 5K. fal bills per output megapixel per second, so the price grows with the square of this value.

  Range: `1` to `200`
</ParamField>

<ParamField body="video_url" type="string" required>
  URL of the input video (MP4, MOV, WebM, M4V or GIF).
</ParamField>

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

### Output

<ResponseField name="video" type="object" required>
  The upscaled video file.
</ResponseField>

<ResponseField name="video.content_type" type="string">
  MIME type of the video file.
</ResponseField>

<ResponseField name="video.duration" type="number">
  Duration of the video in seconds.
</ResponseField>

<ResponseField name="video.file_name" type="string">
  Name of the video file.
</ResponseField>

<ResponseField name="video.file_size" type="integer">
  Size of the video file in bytes.
</ResponseField>

<ResponseField name="video.fps" type="number">
  Frame rate of the video.
</ResponseField>

<ResponseField name="video.height" type="integer">
  Height of the video in pixels.
</ResponseField>

<ResponseField name="video.num_frames" type="integer">
  Number of frames in the video.
</ResponseField>

<ResponseField name="video.url" type="string" required>
  URL of the upscaled video.
</ResponseField>

<ResponseField name="video.width" type="integer">
  Width of the video in pixels.
</ResponseField>

## Examples

### Input

```json theme={null}
{
  "scale_factor": 2,
  "video_url": "https://storage.googleapis.com/falserverless/example_inputs/crystal_upscaler/video_upscaling/video_in.mp4"
}
```

### Output

```json theme={null}
{
  "video": {
    "content_type": "video/mp4",
    "duration": 10,
    "file_name": "upscaled.mp4",
    "file_size": 3950551,
    "fps": 30,
    "height": 720,
    "num_frames": 300,
    "url": "https://example.invalid/fal/crystal-video-upscaler/upscaled.mp4",
    "width": 1280
  }
}
```

## Before you ship

The SDKs create an `Idempotency-Key` and reuse it for automatic retries. For manual retries, reuse the original key. Router can hold the connection for up to 10 minutes.

When a request fails, Router sends an `X-Comfy-Error-Type` response header explaining why. A `422` means Router rejected the input before calling the provider, and a `413` means the request body was larger than Router accepts. Download generated assets promptly because [result URLs can expire](/development/comfy-router/reference#result-assets).

Any size limit named in a field description above is the provider's own bound on that field, quoted from the provider's specification. Router applies a separate cap to the whole request body, which base64-encoded media counts against: see [request body size](/development/comfy-router/limitations#request-bodies-are-capped).

This page documents one partner model called through Comfy Router. The same `comfy-sdk` / `@comfyorg/sdk` package also ships a second client, for running a whole ComfyUI workflow graph on Comfy Cloud: `Comfy(api_key=...)` / `new Comfy({ apiKey })`, with `client.workflows`, `client.assets` and `client.jobs`. See [Comfy SDKs](/development/api-development/sdks).

<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="Using the Router API" icon="code" href="/development/comfy-router/api">
    Model discovery, validation errors, retries, and billing.
  </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>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.