# 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.