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

# Unified Model Behavior

> How Lumenfall ensures consistent behavior across all models and providers

Each AI provider has its own API format, parameter names, and supported features. Lumenfall abstracts these differences for you, so you can write code once and have it work consistently across all models and providers.

## Parameter support

When you make a request, Lumenfall handles parameters in four ways, from weakest to strongest support:

| Mode        | What Happens                                                 | Example                                                       |
| ----------- | ------------------------------------------------------------ | ------------------------------------------------------------- |
| Passthrough | Passed as-is to upstream; provider may ignore if unsupported | `style`, `quality`, `guidance_scale`                          |
| Renamed     | Field name mapped to provider's expected name for this model | `prompt`                                                      |
| Converted   | Value transformed to provider's format for this model        | `size`                                                        |
| Emulated    | Behavior emulated even if model doesn't support it           | `n`, `response_format`, `output_format`, `output_compression` |

<Tip>
  **Provider-specific parameters**: Any parameters not recognized by Lumenfall are passed through to the upstream provider. This lets you use provider-specific features without waiting for explicit Lumenfall support. See [Passing additional parameters](/client-libraries/openai-sdk#passing-additional-parameters) for examples.
</Tip>

## Universal features

These features are normalized across all models, giving you consistent behavior regardless of which provider handles your request:

| Feature              | Description                                                |
| -------------------- | ---------------------------------------------------------- |
| `response_format`    | Choose `url` or `b64_json` for any model                   |
| `output_format`      | Choose output format: `png`, `jpeg`, `gif`, `webp`, `avif` |
| `output_compression` | Control compression level for lossy formats                |
| `n`                  | Request multiple images regardless of provider limits      |

<Info>
  When a model natively supports a feature, Lumenfall uses the native capability. Emulation only kicks in when needed.
</Info>

### response\_format

Request images as URLs or base64-encoded data.

When you request `url` but the provider returns base64, we temporarily store the image on our servers and return a URL valid for 60 minutes. The image is deleted after expiry with no copies retained. This applies regardless of your data retention settings.

Supported values: `url`, `b64_json`

```python theme={null}
# Get base64 data even if provider returns URLs
response = client.images.generate(
    model="gemini-3-pro-image",
    prompt="A mountain landscape",
    response_format="b64_json"
)

image_data = response.data[0].b64_json
```

### output\_format and output\_compression

Specify the image format you want. If the provider generates a different format, Lumenfall converts the image for you. Use `output_compression` to control quality for lossy formats.

Supported formats: `png`, `jpeg`, `gif`, `webp`, `avif`

<Note>
  Lumenfall supports more output formats than OpenAI's API. In addition to `png`, `jpeg`, and `webp`, we also support `gif` and `avif`. Note that AVIF conversion is limited to images up to 1,600 pixels; larger images will fall back to the original format.
</Note>

```python theme={null}
response = client.images.generate(
    model="gemini-3-pro-image",
    prompt="A mountain landscape",
    output_format="webp",
    output_compression=85  # 1-100
)
```

## Size, aspect ratio, and resolution

Control the shape and scale of generated images using three parameters. Lumenfall translates these into whatever format each provider expects — pixel dimensions, aspect ratio strings, resolution tiers, or preset sizes.

<Tip>
  **Always use `size`, `aspect_ratio`, and `resolution`** instead of provider-specific parameters like `image_size`, `width`/`height`, or `imageSize`. Since Lumenfall may route your request to different providers, these three universal parameters ensure consistent behavior regardless of which provider handles it.
</Tip>

### Parameters

| Parameter      | Format         | Example           | What it controls                |
| -------------- | -------------- | ----------------- | ------------------------------- |
| `size`         | `"WxH"` pixels | `"1920x1080"`     | Shape and scale (most specific) |
| `aspect_ratio` | `"W:H"` ratio  | `"16:9"`, `"8:1"` | Shape only                      |
| `resolution`   | Scale tier     | `"1K"`, `"4K"`    | Scale only                      |

All three are optional. When omitted, the model uses its defaults.

### How parameters interact

When you provide multiple parameters, more specific inputs take priority:

* **`size` is the most specific** — it determines both shape and scale. If you also pass `aspect_ratio` or `resolution`, they are ignored.
* **`aspect_ratio` + `resolution`** — resolved independently. Shape is matched against the model's supported ratios; scale is matched against supported tiers.
* **`aspect_ratio` alone** — determines shape. Scale is left to the model's default.
* **`resolution` alone** — determines scale without changing shape (useful for upscaling).

```python theme={null}
# Shape from aspect ratio, scale from resolution (independent)
response = client.images.generate(
    model="gemini-3-pro-image",
    prompt="A mountain landscape",
    aspect_ratio="16:9",
    resolution="4K"
)

# Explicit pixel dimensions (overrides both aspect_ratio and resolution)
response = client.images.generate(
    model="flux-2-pro",
    prompt="A mountain landscape",
    size="1920x1080"
)
```

### Shape matching

When the exact aspect ratio you request isn't supported by the model, Lumenfall finds the closest match by comparing the numeric ratio values. For example, requesting `"7:1"` on a model that supports `["4:1", "8:1"]` will match to `"8:1"`.

If you request an exact ratio the model supports, it's used as-is with no transformation.

### Scale matching

Resolution tiers are matched against the model's supported values. If you request a tier the model doesn't support, Lumenfall picks the closest available tier rather than silently dropping your preference. For example, requesting `"8K"` on a model that supports `["1K", "4K"]` will match to `"4K"`.

Two tier formats exist across providers — Lumenfall handles both transparently:

| Format          | Values                           | Used by           |
| --------------- | -------------------------------- | ----------------- |
| K tiers         | `"0.5K"`, `"1K"`, `"2K"`, `"4K"` | Gemini, Vertex    |
| Megapixel tiers | `"0.25"`, `"1"`                  | FLUX on Replicate |

### Dimension clamping

When a model accepts pixel dimensions with constraints (min/max width, height, or megapixels), Lumenfall clamps your dimensions to fit within the model's bounds while preserving the aspect ratio when possible.

```python theme={null}
# If the model's max is 2048x2048, this is clamped to 2048x2048
response = client.images.generate(
    model="flux-2-pro",
    prompt="A mountain landscape",
    size="4096x4096"
)
```

## Error normalization

Each provider returns errors in different formats. Lumenfall transforms all provider errors into the standard [OpenAI error format](https://platform.openai.com/docs/guides/error-codes), so you can handle errors consistently.

| Provider Error           | Normalized To                  |
| ------------------------ | ------------------------------ |
| Content policy violation | `400 content_policy_violation` |
| Rate limit exceeded      | `429 rate_limit_exceeded`      |
| Invalid image format     | `400 invalid_request_error`    |
| Model not found          | `404 model_not_found`          |
| Authentication failed    | `401 invalid_api_key`          |

## Why this matters

* **Write once, switch freely** - Change models without rewriting code
* **No provider lock-in** - Your integration works with any provider
* **Predictable behavior** - Same parameters, same results, regardless of which provider handles the request

## Next steps

<CardGroup cols={2}>
  <Card title="Available Models" icon="cube" href="/models">
    Explore all available image and video generation models.
  </Card>

  <Card title="Routing" icon="route" href="/routing">
    Learn how requests are routed to providers.
  </Card>
</CardGroup>
