# Images and files

> Send images, PDFs and audio as message content parts.

User messages can mix text with images, PDFs and audio by passing `content` as an array of parts. Each model page lists what it accepts: **Vision** for images, **PDF input** for documents and **Audio input** for audio.

## Images

Send an `image_url` part with a public HTTPS URL or a base64 data URL:

```python
completion = client.chat.completions.create(
    model="google/gemini-3.8-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What’s in this picture?"},
                {"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}},
            ],
        }
    ],
)
```

```python
import base64

with open("receipt.png", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()

image_part = {
    "type": "image_url",
    "image_url": {"url": f"data:image/png;base64,{b64}", "detail": "high"},
}
```

`detail` (`auto`, `low` or `high`) is passed to providers that support it. Some providers, including Gemini, can’t fetch image URLs themselves; for those models Clonvo downloads the image and sends it inline, so URLs work everywhere. Clonvo only fetches public `http` or `https` URLs, up to 20 MB per image and 50 MB per request in total, and gives up after 15 seconds. An image it can’t fetch returns `400`; going over the per-request total returns `400 media_too_large`.

## PDFs and other files

Send a `file` part with the document as a base64 data URL in `file_data`:

```python
with open("contract.pdf", "rb") as f:
    pdf = base64.b64encode(f.read()).decode()

completion = client.chat.completions.create(
    model="google/gemini-3.8-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "List the termination clauses."},
                {
                    "type": "file",
                    "file": {"filename": "contract.pdf", "file_data": f"data:application/pdf;base64,{pdf}"},
                },
            ],
        }
    ],
)
```

Clonvo doesn’t offer a file upload API, so send files inline with `file_data`. `file_id` references aren’t supported on any model and return `400`.

Which providers accept files: OpenAI, Anthropic (PDFs) and Gemini, plus free models whose provider accepts them. Other providers return `400`.

## Audio

Send an `input_audio` part with base64 audio and its format, on models with **Audio input** (OpenAI, Gemini and some free models). Gemini accepts `wav`, `mp3`, `aiff`, `aac`, `ogg` and `flac`.

```json
{
  "type": "input_audio",
  "input_audio": { "data": "<base64>", "format": "wav" }
}
```

## Limits and costs

-   Images, documents and audio are billed as input tokens by the provider; the count is included in `usage.prompt_tokens`.
-   Sending a part a model doesn’t accept returns `400` with the code `unsupported_content`; Clonvo doesn’t drop parts silently. With [fallback models](https://clonvo.com/docs/fallbacks.md), models that can’t accept the content are skipped.
-   Providers limit request and file sizes; check the provider’s documentation before sending large files. For images, a URL keeps the request small.
