> ## Documentation Index
> Fetch the complete documentation index at: https://bifrost-dev.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Runware

> Runware API conversion guide - text-to-image, image editing, upscaling, background removal, masking, text/image-to-video, 3D generation, and raw task passthrough

## Overview

Runware exposes a single endpoint (`https://api.runware.ai/v1`) that accepts an **array of tasks**, where a `taskType` field selects the operation. Bifrost wraps each request in this array envelope and maps its unified image and video schemas onto the matching task type. Image tasks return synchronously; video and 3D tasks are submitted asynchronously and polled to completion.

Where an operation has no dedicated Bifrost endpoint, a neutral `type` parameter selects it on the closest one - for example `type: "upscale"` on `/v1/images/edits`.

### Supported Operations

<Info>Upscaling, background removal, masking/segmentation, ControlNet preprocessing, and vectorize are available in **Bifrost v2.0.0 and above**.</Info>

| Operation                                            | Supported | Endpoint                                     | Task Type                  |
| ---------------------------------------------------- | --------- | -------------------------------------------- | -------------------------- |
| Image Generation                                     | ✅         | `/v1/images/generations`                     | `imageInference`           |
| Image Edit (image-to-image, inpainting, outpainting) | ✅         | `/v1/images/edits`                           | `imageInference`           |
| Image Upscale                                        | ✅         | `/v1/images/edits`                           | `upscale`                  |
| Background Removal                                   | ✅         | `/v1/images/edits`                           | `removeBackground`         |
| Masking / Segmentation                               | ✅         | `/v1/images/edits`                           | `imageMasking`             |
| ControlNet Preprocess                                | ✅         | `/v1/images/edits`                           | `controlNetPreprocess`     |
| Vectorize (SVG)                                      | ✅         | `/v1/images/generations`, `/v1/images/edits` | `vectorize`                |
| Video Generation                                     | ✅         | `/v1/videos`                                 | `videoInference` (async)   |
| Video Upscale                                        | ✅         | `/v1/videos`, `/v1/videos/edits`             | `upscale` (async)          |
| Video Background Removal                             | ✅         | `/v1/videos`, `/v1/videos/edits`             | `removeBackground` (async) |
| Video Edit (prompt-driven)                           | ✅         | `/v1/videos/edits`                           | `videoInference` (async)   |
| Video Retrieve / Download                            | ✅         | `/v1/videos/{id}`, `/v1/videos/{id}/content` | `getResponse`              |
| 3D Model Generation                                  | ✅         | `/v1/videos`                                 | `3dInference` (async)      |
| Passthrough (any task type)                          | ✅         | `/runware_passthrough/v1`                    | raw                        |
| Image Variation                                      | ❌         | -                                            | -                          |
| Image / Image Edit (stream)                          | ❌         | -                                            | -                          |
| Video Delete / List / Remix                          | ❌         | -                                            | -                          |
| Captioning, Audio, Model Training                    | ❌         | use [Passthrough](#6-passthrough)            | -                          |

<Note>
  Runware returns an exact per-task **cost** when a request sets `includeCost: true`. Bifrost always sets it and surfaces the value as the provider-reported cost, reported under `usage.cost.total_cost`.
</Note>

***

# 1. Image Generation

## Generate (`POST /v1/images/generations`)

| Parameter             | Type      | Required | Runware field      | Notes                                                                       |
| --------------------- | --------- | -------- | ------------------ | --------------------------------------------------------------------------- |
| `model`               | string    | ✅        | `model`            | Runware model (AIR identifier)                                              |
| `prompt`              | string    | ✅        | `positivePrompt`   | Text description of the image                                               |
| `input_images`        | string\[] | ❌        | input image        | Turns the request into **image-to-image**                                   |
| `negative_prompt`     | string    | ❌        | `negativePrompt`   | What to avoid                                                               |
| `size`                | string    | ❌        | `width` / `height` | `WxH` (default `1024x1024`)                                                 |
| `num_inference_steps` | int       | ❌        | `steps`            | Diffusion steps                                                             |
| `seed`                | int       | ❌        | `seed`             | Seed for reproducibility                                                    |
| `n`                   | int       | ❌        | `numberResults`    | Number of images                                                            |
| `response_format`     | string    | ❌        | `outputType`       | `url` → `URL`, `b64_json` → `base64Data`, `data_uri` → `dataURI`            |
| `output_format`       | string    | ❌        | `outputFormat`     | `png`/`jpeg`/`webp`/`tiff` → `PNG`/`JPG`/`WEBP`/`TIFF`; `svg` for vectorize |
| `output_compression`  | int       | ❌        | `outputQuality`    | Encoder quality                                                             |
| `type`                | string    | ❌        | `taskType`         | `vectorize` for text-to-SVG                                                 |

**Extra Params**: any provider-native field (`CFGScale`, `scheduler`, `lora`, `inputs`, ...) is forwarded as-is on this endpoint - no header required. A `seedImage` passed this way takes precedence over `input_images`.

**Response**: [`BifrostImageGenerationResponse`](https://github.com/maximhq/bifrost/blob/main/core/schemas/images.go) with `data[].url` or `data[].b64_json`, plus `data[].id` (the Runware asset UUID, reusable as an input to a later task).

### Example

<Tabs>
  <Tab title="Gateway">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/images/generations \
      -H "Content-Type: application/json" \
      -d '{
        "model": "runware/runware:100@1",
        "prompt": "A serene mountain landscape at sunset",
        "size": "1024x1024",
        "n": 1
      }'
    ```
  </Tab>

  <Tab title="Go SDK">
    ```go theme={null}
    resp, err := client.ImageGenerationRequest(schemas.NewBifrostContext(ctx, schemas.NoDeadline), &schemas.BifrostImageGenerationRequest{
    	Provider: schemas.Runware,
    	Model:    "runware:100@1",
    	Input: &schemas.ImageGenerationInput{
    		Prompt: "A serene mountain landscape at sunset",
    	},
    	Params: &schemas.ImageGenerationParameters{
    		Size: schemas.Ptr("1024x1024"),
    		N:    schemas.Ptr(1),
    	},
    })
    ```
  </Tab>
</Tabs>

### Text-to-SVG

The `recraft:v4@vector` family generates an SVG from a prompt:

```bash theme={null}
curl -X POST http://localhost:8080/v1/images/generations \
  -H "Content-Type: application/json" \
  -d '{
    "model": "runware/recraft:v4@vector",
    "prompt": "a simple mountain logo",
    "type": "vectorize"
  }'
```

***

# 2. Image Edit

## Edit (`POST /v1/images/edits`)

This endpoint accepts **JSON** and **multipart/form-data**. Use multipart to upload the image as a file; use JSON to reference it by URL, which passes straight to Runware instead of round-tripping the asset through the gateway as base64.

| Parameter                                                                                                               | Runware field                                   | Notes                                                                       |
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------- |
| `images`                                                                                                                | input image                                     | JSON only; a URL string, a Runware asset UUID, or `{ "image": "<base64>" }` |
| `image[]` / `image`                                                                                                     | input image                                     | Multipart only; file upload (bytes → data URI)                              |
| `image_url[]` / `image_url`                                                                                             | input image                                     | Multipart only; Runware asset UUID or public URL                            |
| `mask`                                                                                                                  | mask image                                      | Inpainting mask (bytes → data URI)                                          |
| `prompt`                                                                                                                | `positivePrompt`                                | Edit instruction; not required for the operation types below                |
| `type`                                                                                                                  | `taskType`                                      | Selects the operation - see the table below                                 |
| `negative_prompt`, `size`, `num_inference_steps`, `seed`, `n`, `response_format`, `output_format`, `output_compression` | same as [Image Generation](#1-image-generation) |                                                                             |
| `upscale_factor`, `target_megapixels`                                                                                   | `upscaleFactor`, `targetMegapixels`             | `type: "upscale"` only; mutually exclusive                                  |

**Extra Params**: provider-native fields (`strength`, `maskMargin`, `outpaint`, `settings`, `providerSettings`, ...) are forwarded as-is - no header required. Multipart carries every value as a string, so send JSON when a model's parameters are numbers, booleans or nested objects.

### Operation types

| `type`                  | Task type              | Prompt   | Output                                               |
| ----------------------- | ---------------------- | -------- | ---------------------------------------------------- |
| *(omitted)*             | `imageInference`       | required | Edited image. Supplying a `mask` makes it inpainting |
| `upscale`               | `upscale`              | not used | Enlarged image                                       |
| `background_removal`    | `removeBackground`     | not used | Subject on a transparent background                  |
| `mask` / `segmentation` | `imageMasking`         | not used | Mask image plus `data[].detections[]`                |
| `controlnet_preprocess` | `controlNetPreprocess` | not used | Guide image (canny, depth, openpose, ...)            |
| `vectorize`             | `vectorize`            | not used | SVG                                                  |

Aliases: `remove_background` and `remove_bg` for `background_removal`; `controlnet` and `preprocess` for `controlnet_preprocess`.

<Note>
  Bifrost sends each model the input shape it declares, so the same request works across all of them. Only the reference-image models (Nano Banana, FLUX, Seedream, Qwen-Image, ...) accept **more than one** input image; elsewhere images after the first are dropped, and a `mask` reaches only models that declare one.
</Note>

### Examples

<Tabs>
  <Tab title="Image-to-image">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/images/edits \
      --form 'model="runware/google:4@1"' \
      --form 'image_url="https://example.com/teapot.jpg"' \
      --form 'prompt="make the teapot blue"'
    ```
  </Tab>

  <Tab title="Inpainting">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/images/edits \
      --form 'model="runware/runware:102@1"' \
      --form 'image[]=@"image.png"' \
      --form 'mask=@"mask.png"' \
      --form 'prompt="a bunch of yellow sunflowers"'
    ```
  </Tab>

  <Tab title="Upscale">
    Per-model tuning that has no Bifrost equivalent goes in `settings`, which reaches Runware with its JSON types intact.

    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/images/edits \
      -H "Content-Type: application/json" \
      -d '{
        "model": "runware/topazlabs:wonder@3.5",
        "images": ["https://example.com/teapot.jpg"],
        "type": "upscale",
        "upscale_factor": 4,
        "settings": {
          "enhancementStrength": "high",
          "grain": { "size": 1.5 }
        }
      }'
    ```
  </Tab>

  <Tab title="Background removal">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/images/edits \
      --form 'model="runware/ideogram:remove-background@0"' \
      --form 'image_url="https://example.com/teapot.jpg"' \
      --form 'type="background_removal"'
    ```
  </Tab>

  <Tab title="Segmentation">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/images/edits \
      --form 'model="runware/runware:35@1"' \
      --form 'image_url="https://example.com/teapot.jpg"' \
      --form 'type="segmentation"'
    ```
  </Tab>

  <Tab title="ControlNet">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/images/edits \
      --form 'model="runware/runware:controlnet-preprocess@canny"' \
      --form 'image_url="https://example.com/teapot.jpg"' \
      --form 'type="controlnet_preprocess"'
    ```
  </Tab>
</Tabs>

**Response**: same shape as Image Generation (`data[].url` or `data[].b64_json`). Masking models additionally return `data[].detections[]` with the regions they located.

***

# 3. Video Generation

## Generate (`POST /v1/videos`)

Video tasks are submitted with `deliveryMethod: async` and return a queued job. Poll [Retrieve](#retrieve--download) until `status: completed`, then download.

| Parameter         | Type   | Required | Runware field      | Notes                                                                        |
| ----------------- | ------ | -------- | ------------------ | ---------------------------------------------------------------------------- |
| `model`           | string | ✅        | `model`            | Runware model (AIR identifier)                                               |
| `prompt`          | string | ❌        | `positivePrompt`   | Text description of the video                                                |
| `input_reference` | string | ❌        | first frame image  | Anchors the **first** frame → **image-to-video**                             |
| `video_uri`       | string | ❌        | `inputs.video`     | Source video URL; used by `type: "upscale"` and `type: "background_removal"` |
| `negative_prompt` | string | ❌        | `negativePrompt`   | What to avoid                                                                |
| `seed`            | int    | ❌        | `seed`             | Seed for reproducibility                                                     |
| `size`            | string | ❌        | `width` / `height` | `WxH`; omitted entirely when not given                                       |
| `seconds`         | string | ❌        | `duration`         | Duration in seconds                                                          |
| `type`            | string | ❌        | `taskType`         | `3d`, `upscale`, `background_removal`                                        |
| `output_format`   | string | ❌        | `outputFormat`     | `mp4`, `webm`, `mov`                                                         |

**Extra Params**: provider-native fields are forwarded when the `x-bf-passthrough-extra-params: true` header is set. `settings` and `providerSettings` are promoted to typed fields and reach Runware without it. `taskType` remains available as a raw escape hatch for task types Bifrost does not model.

**Generation Modes** (auto-detected): **text-to-video** (`prompt` only) · **image-to-video** (`prompt` + `input_reference`).

<Note>
  Only a handful of video models mark width and height required; Bifrost sends the 16:9 1080p default for those alone. Every other model picks its own dimensions. Passing `size` always overrides.
</Note>

**Response**: [`BifrostVideoGenerationResponse`](https://github.com/maximhq/bifrost/blob/main/core/schemas/videos.go) with `id`, `status`, `videos[]`.

**Bifrost statuses** (normalized): `queued` → `in_progress` → `completed` / `failed`. Runware's native statuses are `processing`, `success`, `error`.

### Examples

<Tabs>
  <Tab title="Text-to-video">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/videos \
      -H "Content-Type: application/json" \
      -d '{
        "model": "runware/klingai:6@0",
        "prompt": "a red ceramic teapot on a table, slow camera pan"
      }'
    ```
  </Tab>

  <Tab title="Image-to-video">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/videos \
      -H "Content-Type: application/json" \
      -d '{
        "model": "runware/klingai:kling-video@3-pro",
        "prompt": "slow camera pan around the teapot",
        "input_reference": "https://example.com/teapot.jpg"
      }'
    ```
  </Tab>

  <Tab title="Upscale">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/videos \
      -H "Content-Type: application/json" \
      -d '{
        "model": "runware/bytedance:50@1",
        "type": "upscale",
        "video_uri": "https://example.com/clip.mp4"
      }'
    ```
  </Tab>

  <Tab title="Background removal">
    ```bash theme={null}
    curl -X POST http://localhost:8080/v1/videos \
      -H "Content-Type: application/json" \
      -d '{
        "model": "runware/bria:51@1",
        "type": "background_removal",
        "video_uri": "https://example.com/clip.mp4",
        "output_format": "webm"
      }'
    ```
  </Tab>
</Tabs>

## Retrieve / Download

| Operation        | Endpoint                      | Notes                                                          |
| ---------------- | ----------------------------- | -------------------------------------------------------------- |
| Get status       | `GET /v1/videos/{id}`         | Polls via a `getResponse` task; poll until `status: completed` |
| Download content | `GET /v1/videos/{id}/content` | Downloads the raw artifact bytes from the task's output URL    |

<Note>
  Video Delete, List, and Remix are not supported by Runware.
</Note>

***

# 4. Video Edit

## Edit (`POST /v1/videos/edits`)

Operates on an existing video. The source is supplied as a Runware asset UUID, a URL, or an upload, and the `type` parameter picks the operation. Like generation, these are async - poll and download through the same endpoints.

| Parameter                             | Runware field                       | Notes                                                                        |
| ------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------- |
| `video`                               | `inputs.video`                      | URL, file upload, or an asset ID from `videos[].id`                          |
| `prompt`                              | `positivePrompt`                    | Edit instruction; not used by upscale or background removal                  |
| `type`                                | `taskType`                          | *(omitted)* → `videoInference`, `upscale`, `background_removal`              |
| `seed`, `output_format`               | `seed`, `outputFormat`              | `outputFormat` accepts `mp4`, `webm`, `mov`; background removal needs `webm` |
| `upscale_factor`, `target_megapixels` | `upscaleFactor`, `targetMegapixels` | `type: "upscale"` only; not every upscaler accepts them                      |

```bash theme={null}
curl -X POST http://localhost:8080/v1/videos/edits \
  -H "Content-Type: application/json" \
  -d '{
    "model": "runware/bria:51@1",
    "video": { "url": "https://example.com/clip.mp4" },
    "type": "background_removal",
    "output_format": "webm"
  }'
```

***

# 5. 3D Model Generation

Runware's 3D models (TRELLIS, Tripo, Hunyuan 3D, Rodin, Meshy) run as the `3dInference` task type on the same async submit-then-poll lifecycle as video. Drive them through `POST /v1/videos` with `type: "3d"`. The finished mesh is returned under `videos[]` with `content_type: model/gltf-binary`.

**Text-to-3D** uses `prompt` alone. **Image-to-3D** uses `input_reference`.

<Note>
  Runware rejects a 3D task that carries both an input image and a prompt. When you supply `input_reference`, Bifrost drops the prompt so the request succeeds - the image is the subject.
</Note>

Models differ in whether they take the image singly or as an array; Bifrost sends the form each model declares.

```bash theme={null}
# 1. Submit (returns a queued job with an id)
curl -X POST http://localhost:8080/v1/videos \
  -H "Content-Type: application/json" \
  -d '{
    "model": "runware/tencent:hunyuan-3d@3.1-pro",
    "type": "3d",
    "input_reference": "https://example.com/teapot.jpg"
  }'

# 2. Poll until status is completed
curl http://localhost:8080/v1/videos/<id-from-step-1>

# 3. Download the mesh
curl -o model.glb http://localhost:8080/v1/videos/<id-from-step-1>/content
```

A completed response looks like:

```json theme={null}
{
  "status": "completed",
  "videos": [
    { "type": "url", "url": "https://im.runware.ai/.../model.glb", "content_type": "model/gltf-binary" }
  ],
  "usage": { "cost": { "total_cost": 0.375 } }
}
```

***

# 6. Passthrough

The passthrough route forwards a **raw Runware task array** to `https://api.runware.ai/v1` and returns the untouched response, unlocking the task types Bifrost does not model natively - captioning, audio inference, model training and prompt enhancement. Bifrost still injects the provider key, strips client auth, and logs the call.

* **Endpoint:** `POST /runware_passthrough/v1`
* **Body:** a raw Runware task array (exactly what you would send to Runware directly)
* **Auth:** use your Bifrost key; Bifrost injects the real Runware key from its pool

<Note>
  For anything slower than quick image inference, submit with `deliveryMethod: "async"` and poll with a `getResponse` task. A synchronous task that outruns the connection window returns an upstream `504 failedTaskTimeout`. This is Runware's sync limit, not a passthrough error.
</Note>

```bash theme={null}
# Submit an async captioning task
curl -X POST http://localhost:8080/runware_passthrough/v1 \
  -H "Authorization: Bearer <your-bifrost-key>" \
  -H "Content-Type: application/json" \
  -d '[{
    "taskType": "caption",
    "taskUUID": "11111111-1111-1111-1111-111111111111",
    "deliveryMethod": "async",
    "model": "runware:150@2",
    "inputs": { "image": "https://im.runware.ai/.../input.jpg" },
    "includeCost": true
  }]'

# Poll with a getResponse task
curl -X POST http://localhost:8080/runware_passthrough/v1 \
  -H "Authorization: Bearer <your-bifrost-key>" \
  -H "Content-Type: application/json" \
  -d '[{ "taskType": "getResponse", "taskUUID": "11111111-1111-1111-1111-111111111111" }]'
```

***

## Setup & Configuration

Configure Runware as a provider.

<Tabs>
  <Tab title="Web UI">
    1. Navigate to **Models** > **Model Providers**. Look for **Runware** under **Configured Providers**. If it is missing, click on **Add New Provider** and select **Runware**.
    2. Click **Add Key** or edit an existing key.
    3. Set a name for your key.
    4. Paste your API key directly or use an environment variable (for example, `env.RUNWARE_API_KEY`).
    5. Set **Allowed Models** to **All Models** (default) or the specific model allowlist you want this key to serve.
    6. Save the provider configuration.
  </Tab>

  <Tab title="config.json">
    ```json theme={null}
    {
      "providers": {
        "runware": {
          "keys": [
            {
              "name": "runware-key-1",
              "value": "env.RUNWARE_API_KEY",
              "models": [
                "*"
              ],
              "weight": 1.0
            }
          ]
        }
      }
    }
    ```
  </Tab>

  <Tab title="API">
    Refer to the API documentation for [Provider Keys Management](https://docs.getbifrost.ai/api-reference/providers/create-a-key-for-a-provider).
  </Tab>

  <Tab title="Go SDK">
    ```go theme={null}
    case schemas.Runware:
    	return []schemas.Key{{
    		Name:   "runware-key-1",
    		Value:  *schemas.NewSecretVar("env.RUNWARE_API_KEY"),
    		Models: []string{"*"},
    		Weight: 1.0,
    	}}, nil
    ```
  </Tab>
</Tabs>

***

## Reference Links

* [Runware API Documentation](https://docs.runware.ai/)
* [Runware Model Explorer](https://my.runware.ai/models)
* [Runware Model Schemas](https://schemas.runware.ai/registry.json)
* [Bifrost Runware Provider Source](https://github.com/maximhq/bifrost/tree/main/core/providers/runware)
