# Файлы

Files API — хранилище файлов вашего аккаунта. Файл загружается один раз, получает идентификатор вида `rai_file_…` и дальше указывается в запросах вместо содержимого: не нужно каждый раз кодировать его в base64 и пересылать в теле запроса.

Отдельной платы за хранение нет.

## Загрузка файла

Файл отправляется на `/api/v1/files` запросом `multipart/form-data`, поле `file`:


```bash
curl https://routerai.ru/api/v1/files \
  -H "Authorization: Bearer $ROUTERAI_API_KEY" \
  -F "file=@photo.png"
```

```python
import os
import requests

with open("photo.png", "rb") as f:
    response = requests.post(
        "https://routerai.ru/api/v1/files",
        headers={"Authorization": f"Bearer {os.environ['ROUTERAI_API_KEY']}"},
        files={"file": f},
    )

file_id = response.json()["id"]
```


Ответ — метаданные файла:

```json
{
  "id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW",
  "type": "file",
  "filename": "photo.png",
  "mime_type": "image/png",
  "size_bytes": 184320,
  "created_at": "2026-10-13T10:30:25.818Z",
  "downloadable": false
}
```

### Правила и лимиты

| Параметр | Значение |
|---|---|
| Размер файла | до 100 МБ через API, до 50 МБ через личный кабинет |
| Хранилище аккаунта | 1 ГБ |
| Срок хранения | не ограничен, пока вы не удалите файл |
| Частота загрузок | до 60 файлов в минуту на аккаунт |
| Форматы | PDF, PNG, JPEG, GIF, WebP, DOCX, XLSX, PPTX, MP3, WAV, FLAC, OGG, текст в UTF-8 (JSON, NDJSON, CSV, Markdown, обычный текст) |
| Имя файла | от 1 до 255 символов; `/` задаёт путь (`data/report.csv`), сегменты `.` и `..` запрещены |

Тип файла определяется по содержимому, а не по расширению и не по заголовку `Content-Type`: PNG с именем `report.txt` сохранится как `image/png`.

Файл принадлежит аккаунту ключа. В команде квота общая, а видимость файлов зависит от роли:

- участник видит, использует в запросах и удаляет только файлы, загруженные им самим — своими ключами или в личном кабинете;
- администратор команды видит и может использовать или удалить файлы всех участников;
- ключ уровня команды, не привязанный к участнику, работает как ключ администратора.


## Использование в запросах

Укажите идентификатор файла в блоке содержимого сообщения. Форма блока зависит от API.

### Какие файлы можно передавать

| Тип файла | Как попадает к модели |
|---|---|
| PNG, JPEG, GIF, WebP | Изображением — модель должна поддерживать изображения на входе |
| PDF | Целиком, если модель принимает файлы; иначе RouterAI извлекает текст и передаёт его |
| DOCX, XLSX, PPTX | RouterAI извлекает текст и передаёт его модели |
| Текст (JSON, NDJSON, CSV, Markdown, обычный текст) | Текстом, как есть |
| MP3, WAV, FLAC, OGG | Аудио — в Chat Completions и Responses, а также в расшифровке речи; модель должна поддерживать аудио на входе |

Документы обрабатываются так же, как при отправке в base64 — подробности и выбор способа разбора PDF описаны в гайде [«Работа с PDF»](/docs/guides/overview/multimodal/pdfs).

### Chat Completions


```bash
curl https://routerai.ru/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ROUTERAI_API_KEY" \
  -d '{
    "model": "google/gemini-4-argon",
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "Что изображено на этой картинке?"
          },
          {
            "type": "file",
            "file": {
              "file_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"
            }
          }
        ]
      }
    ]
  }'
```

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://routerai.ru/api/v1",
    api_key=os.environ["ROUTERAI_API_KEY"],
)

completion = client.chat.completions.create(
    model="google/gemini-4-argon",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Что изображено на этой картинке?"},
                {"type": "file", "file": {"file_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"}},
            ],
        }
    ],
)

print(completion.choices[0].message.content)
```


### Responses

Для изображений подходят оба типа блока — `input_image` и `input_file`, для документов и текста — только `input_file`:

```bash
curl https://routerai.ru/api/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ROUTERAI_API_KEY" \
  -d '{
    "model": "google/gemini-4-argon",
    "input": [
      {
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "Что изображено на этой картинке?"
          },
          {
            "type": "input_image",
            "file_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"
          }
        ]
      }
    ]
  }'
```

### Messages

Блок `image` или `document` с источником типа `file`. Изображение можно передать в любом из них, документ и текст — только в `document`:

```bash
curl https://routerai.ru/api/v1/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ROUTERAI_API_KEY" \
  -d '{
    "model": "anthropic/claude-sonnet-5.5",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "Что изображено на этой картинке?"
          },
          {
            "type": "image",
            "source": {
              "type": "file",
              "file_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"
            }
          }
        ]
      }
    ]
  }'
```

### Аудио

Аудиофайл передаётся тем же блоком `file` (в Responses — `input_file`) либо блоком `input_audio` с идентификатором вместо содержимого. Формат указывать не нужно — он берётся из файла:

```json
{
  "type": "input_audio",
  "input_audio": {
    "file_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"
  }
}
```

В Messages аудио на входе не поддерживается — такой запрос вернёт ошибку `400`. Набор форматов зависит от модели: например, аудиомодели OpenAI принимают только WAV и MP3. Подробнее — в гайде [«Аудио»](/docs/guides/overview/multimodal/audio).

Для расшифровки речи идентификатор указывается в `input_audio` вместо `data` и `format`:

```bash
curl https://routerai.ru/api/v1/audio/transcriptions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ROUTERAI_API_KEY" \
  -d '{
    "model": "google/gemini-3.5-transcribe",
    "input_audio": {
      "file_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"
    }
  }'
```

В запросе `multipart/form-data` вместо поля `file` передаётся поле `file_id`.

### Генерация изображений

В запросе к `/api/v1/images` загруженную картинку можно указать как исходную в `input_references` и как маску в `mask`:

```json
{
  "model": "openai/gpt-image-2.5-sunburst",
  "prompt": "Замени фон на закат",
  "input_references": [
    {"type": "file", "file": {"file_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"}}
  ]
}
```

Здесь подходят только изображения. Требования к формату и размеру картинки зависят от модели — см. гайд [«Генерация изображений»](/docs/guides/overview/multimodal/image-generation).

### Что важно знать

- **Экономии токенов нет.** RouterAI подставляет содержимое файла в запрос к провайдеру, модель каждый раз получает и оплачивает файл целиком — столько же токенов, сколько при отправке того же файла в base64. Идентификатор избавляет только от пересылки содержимого в теле запроса.
- **Файл не привязан к провайдеру.** Один и тот же идентификатор работает с любой подходящей моделью во всех трёх API. Выбор провайдера и переключение на резервного работают как обычно.
- **Лимиты запроса:** до 20 файлов, изображение до 20 МБ, документ, текстовый или аудиофайл до 25 МБ, все вместе до 32 МБ.
- **Документы и аудио — только в сообщении пользователя.** Внутри результата инструмента (`tool_result`, `function_call_output`) по идентификатору можно передать только изображение.
- **Идентификаторы других сервисов не подходят.** Значения вида `file-…` и `file_…`, полученные в Files API OpenAI или Anthropic, вернут ошибку `400`: загрузите файл в RouterAI и используйте его идентификатор.
- В `image_url` идентификатор файла указывать нельзя — только в блоках, перечисленных выше. Это относится и к `input_references`.

## Список файлов

```bash
curl "https://routerai.ru/api/v1/files?limit=20" \
  -H "Authorization: Bearer $ROUTERAI_API_KEY"
```

Файлы возвращаются от новых к старым:

```json
{
  "data": [
    {
      "id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW",
      "type": "file",
      "filename": "photo.png",
      "mime_type": "image/png",
      "size_bytes": 184320,
      "created_at": "2026-10-13T10:30:25.818Z",
      "downloadable": false
    }
  ],
  "has_more": true,
  "first_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW",
  "last_id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW"
}
```

| Параметр | Описание |
|---|---|
| `limit` | Размер страницы, от 1 до 100. По умолчанию 20 |
| `after` | Идентификатор последнего файла предыдущей страницы (`last_id`) — вернутся файлы после него |

Пока `has_more` равно `true`, запрашивайте следующую страницу с `after`, равным `last_id` предыдущего ответа.

## Метаданные и удаление

```bash
# Метаданные одного файла
curl https://routerai.ru/api/v1/files/rai_file_jHl6fK2WxH3qkGu2uwnPYtyW \
  -H "Authorization: Bearer $ROUTERAI_API_KEY"

# Удаление
curl -X DELETE https://routerai.ru/api/v1/files/rai_file_jHl6fK2WxH3qkGu2uwnPYtyW \
  -H "Authorization: Bearer $ROUTERAI_API_KEY"
```

Ответ на удаление:

```json
{
  "id": "rai_file_jHl6fK2WxH3qkGu2uwnPYtyW",
  "type": "file",
  "deleted": true
}
```

Удаление необратимо и сразу освобождает место в хранилище. Запросы с идентификатором удалённого файла получают ошибку `404`.

## Ошибки

Ошибки приходят в формате `{"error": {"message": "…", "code": 400}}`. Отклонённый запрос к модели не тарифицируется.

| Код | Когда возникает |
|---|---|
| `400` | Пустой файл, неподдерживаемый формат или недопустимое имя при загрузке |
| `400` | Файл указан в блоке не своего типа (документ или аудио в блоке для изображений, не-аудио в `input_audio`, не изображение в `input_references` или `mask`) либо аудио передано в Messages |
| `400` | В запросе к модели указан идентификатор другого сервиса (`file-…`, `file_…`) |
| `403` | Файл не помещается в хранилище аккаунта |
| `404` | Файл не найден: удалён, принадлежит другому аккаунту или, для рядового участника команды, загружен другим участником |
| `413` | Файл больше 100 МБ либо превышены лимиты файлов в одном запросе к модели |
| `429` | Слишком много загрузок за минуту — повторите позже, см. заголовок `Retry-After` |


