---
title: "Batch API в AI Gateway"
---

# Batch API в AI Gateway

> Полный индекс документации для ИИ-агентов: [llms.txt](https://timeweb.cloud/llms.txt).

Batch API (пакетная обработка запросов) позволяет отправить несколько запросов к модели одним файлом и получить результаты после завершения обработки. Запросы выполняются в фоновом режиме в течение 24 часов, обычно быстрее.

Пакетная обработка подходит для задач, в которых ответ не нужен сразу, например:

-   перевода большого количества текстов;
-   классификации отзывов и обращений;
-   подготовки описаний товаров;
-   создания векторных представлений текста (embeddings).

При использовании Batch API запросы к моделям становятся вдвое дешевле обычных запросов.

Для использования Batch API:

1.  Подготовьте и загрузите JSONL-файл с запросами.
    
2.  Создайте на его основе пакетную задачу — батч.
    
3.  Проверяйте статус батча до завершения обработки.
    
4.  Скачайте файлы с результатами и ошибками отдельных запросов.
    

Batch API совместим с OpenAI SDK.

## Поддерживаемые модели и ограничения

Batch API доступен только в AI Gateway. Ключи AI-агентов для пакетной обработки не подходят.

Поддерживаются только модели OpenAI, для которых включена пакетная обработка:

-   чат-модели, например `openai/gpt-4.1-mini`, — через эндпоинт `/v1/chat/completions`;
    
-   модели для создания embeddings из семейства `openai/text-embedding-*` — через эндпоинт `/v1/embeddings`.
    

Ограничения JSONL-файла:

| **Параметр** | **Ограничение** |
| --- | --- |
| Формат | JSONL: один JSON-объект на строку |
| Количество запросов | До 50 000 на файл |
| Размер файла | До 50 МБ |
| Модель | Одна на весь файл |
| Эндпоинт | Один на весь файл |
| Срок обработки | До 24 часов |

Внутри запросов не поддерживаются:

-   параметры `stream` и `store`;
    
-   инструменты, кроме `function`, например `web_search` и `file_search`;
    
-   аудио и изображения во входных данных;
    
-   ссылки на файлы через `file_id`;
    

Запросы с неподдерживаемыми параметрами возвращаются с ошибкой.

## Тарификация

Стоимость обработки рассчитывается по входящим и исходящим токенам с учетом множителя Batch API — 0,5 от обычной стоимости запросов к выбранной модели.

### Резервирование средств

При создании батча на балансе аккаунта резервируются средства на обработку всего файла. Сумма складывается из стоимости входящих токенов и предполагаемой стоимости исходящих токенов по цене пакетной обработки.

Количество исходящих токенов определяется отдельно для каждой строки:

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

Поэтому без `max_tokens` сумма резерва может значительно превышать итоговую стоимость обработки. Чтобы ограничить резерв, указывайте значение с учетом ожидаемой длины ответа.

Зарезервированная сумма сразу вычитается из отображаемого баланса и становится недоступна для других платных действий. При этом окончательная стоимость батча определяется только после завершения обработки.

### Средства на работу других сервисов

Для создания батча на аккаунте должно хватать средств не только на резерв, но и на 30 часов работы остальных сервисов. Это необходимо, чтобы резервирование средств для батча не приводило к их блокировке.

Например, если на балансе 5 000 ₽, а остальные сервисы расходуют 500 ₽ в сутки, на 30 часов их работы потребуется:

500 × 30 / 24 = 625 ₽.

Для резервирования под батч останется 4 375 ₽, если на аккаунте нет других зарезервированных сумм.

Если доступных средств недостаточно, API вернет ошибку `402 Insufficient funds`. В этом случае можно пополнить баланс, уменьшить количество запросов в файле или сократить максимальную длину ответа.

### Списание после обработки

После завершения батча рассчитывается стоимость фактически использованных токенов. Оплачиваются только успешные запросы с кодом `200`. Запросы с ошибками не оплачиваются.

Неиспользованная часть резерва сразу возвращается в доступный баланс. Например, если для батча было зарезервировано 1 000 ₽, а фактическая стоимость обработки составила 200 ₽, на балансе снова станут доступны 800 ₽.

Фактический расход отображается в истории расходов как расход по модели.

Если батч завершился со статусом:

-   `expired` или `cancelled` — оплачиваются успешные запросы, которые успели выполниться; остаток резерва возвращается в доступный баланс;
    
-   `failed` — списания нет, весь резерв возвращается в доступный баланс.
    

### Дневные лимиты ключа

Batch API учитывает дневные лимиты API-ключа. При создании батча проверяется, укладывается ли оценка расхода в оставшийся лимит в рублях или токенах. Фактический расход записывается в лимит после завершения обработки.

Например, если оставшийся дневной лимит составляет 5 000 ₽, а батч без `max_tokens` требует резерва в 7 000 ₽, его создание будет отклонено. Батч не запустится и придет уведомление о достижении лимита. Это произойдет, даже если фактическая стоимость обработки была бы сильно ниже лимита (например, 500 ₽): при создании проверяется сумма резерва.

При отказе дневной лимит не расходуется.

## Пример пакетной обработки запросов

Рассмотрим пример пакетного перевода двух текстов с помощью модели `openai/gpt-4.1-mini`.

### Подготовка файла с запросами

Создайте файл `batch.jsonl` со следующим содержимым:

```js
{"custom_id":"1","method":"POST","url":"/v1/chat/completions","body":{"model":"openai/gpt-4.1-mini","messages":[{"role":"user","content":"Переведи на русский: Hello!"}],"max_tokens":500}}
{"custom_id":"2","method":"POST","url":"/v1/chat/completions","body":{"model":"openai/gpt-4.1-mini","messages":[{"role":"user","content":"Переведи на русский: Thank you for your order."}],"max_tokens":500}}
```

Каждый JSON-объект должен занимать одну строку. Объединять запросы в массив и ставить запятые между строками не нужно.

Параметры:

-   `custom_id` — идентификатор запроса, уникальный в пределах файла. По нему вы сможете сопоставить ответ с исходным запросом.
    
-   `method` — HTTP-метод.
    
-   `url` — эндпоинт для обработки запроса: `/v1/chat/completions` для чат-моделей или `/v1/embeddings` для создания эмбеддингов. Значение должно быть одинаковым во всех строках файла.
    
-   `body` — тело запроса к модели. В примере оно содержит имя модели `model`, массив сообщений `messages` и ограничение длины ответа `max_tokens`.
    

Для чат-запросов рекомендуем задавать `max_tokens` с учетом ожидаемой длины ответа. Этот параметр влияет на сумму, которая резервируется при создании батча. Без него резерв будет больше.

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

Отправьте файл через Files API с назначением `purpose=batch`:

```shell
curl --request POST \
  --url https://api.timeweb.ai/v1/files \
  --header "Authorization: Bearer $TIMEWEB_AI_TOKEN" \
  --form "purpose=batch" \
  --form "file=@batch.jsonl"
```

Параметры:

-   `purpose` — назначение файла. Для пакетной обработки укажите `batch`.
    
-   `file` — путь к файлу на локальном компьютере. Перед путем указывается символ `@`.
    

Для файлов с `purpose=batch` модель определяется из содержимого файла. Параметр `target_model_names` передавать не нужно.

Сохраните значение `id` из ответа — оно понадобится для создания батча.

### Создание батча

Отправьте POST-запрос на эндпоинт `/v1/batches`:

```shell
curl --request POST \
  --url https://api.timeweb.ai/v1/batches \
  --header "Authorization: Bearer $TIMEWEB_AI_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "input_file_id": "FILE_ID",
    "endpoint": "/v1/chat/completions",
    "completion_window": "24h"
  }'
```

Параметры:

-   `input_file_id` — идентификатор загруженного файла. Замените `FILE_ID` на значение `id` из предыдущего шага.
    
-   `endpoint` — эндпоинт обработки. Он должен совпадать со значением `url` в строках файла.
    
-   `completion_window` — срок обработки батча. Укажите `24h`.
    

В ответе API вернет объект батча со статусом `validating`. Сохраните его `id` для проверки статуса и отмены задачи.

При создании батча на балансе резервируются средства на обработку всего файла. Если доступных средств недостаточно, API вернет ошибку `402 Insufficient funds`.

### Проверка статуса

Чтобы узнать состояние батча, отправьте GET-запрос, заменив `BATCH_ID` на его идентификатор:

```shell
curl --request GET \
  --url "https://api.timeweb.ai/v1/batches/BATCH_ID" \
  --header "Authorization: Bearer $TIMEWEB_AI_TOKEN"
```

Текущее состояние отображается в поле `status`:

| **Статус** | **Описание** |
| --- | --- |
| `validating` | Выполняется проверка входных данных |
| `in_progress` | Запросы обрабатываются |
| `finalizing` | Подготавливаются результаты |
| `completed` | Обработка завершена. В отдельных запросах могут быть ошибки |
| `failed` | Батч завершился с ошибкой |
| `expired` | Истек срок обработки |
| `cancelled` | Батч отменен |

Повторяйте запрос для проверки состояния, пока обработка не завершится. Успешный батч проходит статусы `validating` → `in_progress` → `finalizing` → `completed`. Статусы `failed`, `expired` и `cancelled` также означают завершение задачи — ждать перехода в `completed` в этих случаях не нужно.

Получить список батчей, доступных текущему ключу, можно отдельным запросом:

```shell
curl --request GET \
  --url https://api.timeweb.ai/v1/batches \
  --header "Authorization: Bearer $TIMEWEB_AI_TOKEN"
```

### Получение результатов

После завершения обработки получите актуальную информацию о батче. Для скачивания файлов используются поля:

-   `output_file_id` — идентификатор файла с результатами;
    
-   `error_file_id` — идентификатор файла с ошибками отдельных запросов.
    

Если в поле `output_file_id` есть идентификатор, подставьте его вместо `OUTPUT_FILE_ID` и скачайте результаты:

```shell
curl --request GET \
  --url "https://api.timeweb.ai/v1/files/OUTPUT_FILE_ID/content" \
  --header "Authorization: Bearer $TIMEWEB_AI_TOKEN" \
  --output results.jsonl
```

Результаты сохранятся в файл `results.jsonl` в текущей директории. Каждая строка содержит JSON-объект с полями:

-   `custom_id` — идентификатор исходного запроса;
    
-   `response.status_code` — HTTP-код ответа;
    
-   `response.body` — тело ответа модели;
    
-   `error` — информация об ошибке, если она есть.
    

Порядок строк в результатах может отличаться от порядка во входном файле. Сопоставляйте запросы и ответы по `custom_id`.

Пример строки из файла результатов для первого запроса:

```js
{"id":"batch_req_b83d7a9e420f4c6198a56e2d03f7c145","custom_id":"req-a7f3","response":{"status_code":200,"request_id":"e7294b18-6c3a-4f85-9d02-a147c8e65b30","body":{"id":"chatcmpl-K7m2R9v4N6p8T1x3B5q0C2d4F6h8J","object":"chat.completion","created":1791804147,"model":"gpt-4.1-mini-2025-04-14","choices":[{"index":0,"message":{"role":"assistant","content":"\u041f\u0440\u0438\u0432\u0435\u0442!","refusal":null,"annotations":[]},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":15,"completion_tokens":3,"total_tokens":18,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"service_tier":"default","system_fingerprint":"fp_a83b72d901"}},"error":null}
```

Значение `content` в этом примере — «Привет!». Кириллица записывается в виде Unicode escape-последовательностей `\uXXXX`: это экранирование символов в JSON.

Если у вас установлен `jq`, вывести идентификатор и текст ответа для каждой строки можно командой:

```shell
jq -r '[.custom_id, .response.body.choices[0].message.content] | @tsv' results.jsonl
```

Для двух запросов из примера вывод может выглядеть так:

```shell
1  Привет!
2  Спасибо за ваш заказ.
```

Если в поле `error_file_id` есть идентификатор, скачайте файл ошибок, заменив `ERROR_FILE_ID` на его значение:

```shell
curl --request GET \
  --url "https://api.timeweb.ai/v1/files/ERROR_FILE_ID/content" \
  --header "Authorization: Bearer $TIMEWEB_AI_TOKEN" \
  --output errors.jsonl
```

Статус `completed` не гарантирует, что все запросы выполнены успешно. Проверьте файл ошибок: он содержит код и описание ошибки для каждого неуспешного запроса. Исправленные запросы можно отправить новым батчем.

При отмене батча или истечении срока обработки запросы, которые успели выполниться, доступны в результатах.

> [!NOTE]
> Файл результатов хранится 30 дней. Скачайте его до окончания этого срока.

## Пример пакетного создания эмбеддингов

Для пакетного создания embeddings подготовьте отдельный JSONL-файл. Используйте модель, для которой включена пакетная обработка, и эндпоинт `/v1/embeddings`.

Например, строка запроса для модели `openai/text-embedding-3-large` выглядит так:

```shell
{"custom_id":"embedding-1","method":"POST","url":"/v1/embeddings","body":{"model":"openai/text-embedding-3-large","input":"Текст для векторизации"}}
```

Загрузите файл с `purpose=batch`, затем создайте батч со значением `endpoint` равным `/v1/embeddings`. Проверка статуса и получение результатов выполняются так же, как для чат-запросов.

## Отмена батча

Чтобы отменить обработку, отправьте POST-запрос, заменив `BATCH_ID` на идентификатор батча:

```shell
curl --request POST \
  --url "https://api.timeweb.ai/v1/batches/BATCH_ID/cancel" \
  --header "Authorization: Bearer $TIMEWEB_AI_TOKEN"
```

Успешные запросы, выполненные до отмены, попадут в результаты и будут оплачены. Остальные запросы не выполняются и не оплачиваются. Неиспользованный резерв возвращается в доступный баланс.
