<!-- source: https://modelux.ai/docs/api/anthropic-files -->

> /anthropic/v1/files — upload documents and images, reference by id from messages.

# Files

modelux proxies the Anthropic Files API (`/v1/files/*`) as an
authenticated thin passthrough. Upload PDFs / images / text once, then
reference them by `file_id` from `/anthropic/v1/messages` content
blocks instead of inlining base64 every turn.

```
POST   /anthropic/v1/files                multipart upload
GET    /anthropic/v1/files                list (limit / before_id / after_id)
GET    /anthropic/v1/files/{id}           metadata
GET    /anthropic/v1/files/{id}/content   download bytes (API-generated files only)
DELETE /anthropic/v1/files/{id}
```

## Beta header

The Files API is currently a beta on Anthropic's side. The proxy
forwards your `anthropic-beta` header verbatim — the SDK's beta-tag
declaration reaches the upstream as-is, so the proxy doesn't have to
track which tag is current:

```bash
curl https://api.modelux.ai/anthropic/v1/files \
  -H "Authorization: Bearer mlx_sk_..." \
  -H "anthropic-beta: files-api-2025-04-14" \
  -F "file=@report.pdf"
```

The official Anthropic SDKs set this header automatically when you
opt into the beta on the client.

## Upload

`multipart/form-data` with a single `file` part. The proxy buffers
the body once before forwarding (Anthropic's upload endpoint
requires `Content-Length` and doesn't accept chunked transfer
encoding):

```python
from anthropic import Anthropic

client = Anthropic(
    base_url="https://api.modelux.ai/anthropic",
    api_key="mlx_sk_...",
    default_headers={"anthropic-beta": "files-api-2025-04-14"},
)

with open("report.pdf", "rb") as f:
    file = client.beta.files.upload(file=f)

print(file.id)  # file_011...
```

Response shape:

```json
{
  "id": "file_011...",
  "type": "file",
  "filename": "report.pdf",
  "mime_type": "application/pdf",
  "size_bytes": 102400,
  "created_at": "2026-04-16T..."
}
```

## Reference from messages

Once uploaded, use the file id in a content block. The standard
pattern is a `document` block on a user message:

```json
{
  "model": "claude-sonnet-4-5",
  "max_tokens": 1024,
  "messages": [{
    "role": "user",
    "content": [
      {
        "type": "document",
        "source": {"type": "file", "file_id": "file_011..."}
      },
      {"type": "text", "text": "Summarize the executive summary section."}
    ]
  }]
}
```

Same pattern for image inputs — `{"type":"image","source":{"type":"file","file_id":"..."}}`.

## Retrieve / list / delete

Standard CRUD shapes:

```bash
# Metadata
curl https://api.modelux.ai/anthropic/v1/files/file_011... \
  -H "Authorization: Bearer mlx_sk_..." \
  -H "anthropic-beta: files-api-2025-04-14"

# List with pagination
curl "https://api.modelux.ai/anthropic/v1/files?limit=20&after_id=file_011..." \
  -H "Authorization: Bearer mlx_sk_..." \
  -H "anthropic-beta: files-api-2025-04-14"

# Delete
curl -X DELETE https://api.modelux.ai/anthropic/v1/files/file_011... \
  -H "Authorization: Bearer mlx_sk_..." \
  -H "anthropic-beta: files-api-2025-04-14"
```

## Download

```
GET /anthropic/v1/files/{id}/content
```

The proxy streams the upstream body chunk-by-chunk via `io.Copy`
(Content-Type preserved) — works for arbitrarily large files without
buffering them in proxy memory.

**Anthropic restriction:** the download endpoint is limited to
API-GENERATED files — for example, files produced by computer-use
tool calls. User-uploaded files (the ones you POST'd) come back from
the upstream with `400 invalid_request_error: File is not
downloadable`. The proxy passes that error envelope through
verbatim. Use the file id for in-message references instead.

## BYOK

`X-Modelux-Provider-Key: sk-ant-...` overrides the org's stored
Anthropic credential for this call. Same precedence as messages /
batches.

## Observability

Each endpoint logs to ClickHouse with a distinct `request_type`:

- `file_upload`
- `file_list`
- `file_retrieve`
- `file_download`
- `file_delete`

Same dashboard breakdowns work for both Anthropic and OpenAI files
(the request_type names are shared).

## See also

- [Messages (Anthropic shape)](/docs/api/anthropic-messages) — referencing files from content blocks
- [Message batches (Anthropic)](/docs/api/anthropic-batches) — async batches of message requests
- [Batches & files (OpenAI)](/docs/api/openai-batches) — the OpenAI equivalent
- [Capability matrix](/docs/concepts/capability-matrix) — what's supported where
