Batch запросы

Много запросов одним пакетом, результаты забираете позже. Удобно, когда ответ не нужен сразу: прогон датасета, ночная генерация, массовые эмбеддинги.

Окно выполнения — 24 часа. После завершения результаты приходят в том же GET, отдельный файл скачивать не нужно.

Какие модели

Обычное имя из каталога: claude-opus-4.8, gpt-5.4. Batch есть, если у модели в каталоге поле batch:

JSON
{
  "batch": { "discount": 0.5, "window": "24h" }
}

Прямые маршруты отдельных провайдеров в Batch не ходят — только модели с полем batch.

Эндпоинты

МетодПутьЧто делает
POST/v1/batchesСоздать пакет, 202 Accepted
GET/v1/batchesСписок ваших пакетов
GET/v1/batches/{id}Статус и результаты

Отмены нет: провайдер начинает работу сразу и выставляет нам счёт независимо от того, ждёте вы результат. «Отмена» означала бы вернуть вам деньги за уже оплаченную нами работу.

Base URL
Авторизация
Тот же Bearer, что для чата

Форма запроса

endpoint
Форма API для всего пакета
model
Id модели из каталога
requests
Непустой массив. У каждого элемента — custom_id и body

custom_id уникален внутри пакета. body — то же, что вы бы отправили на выбранный endpoint. Модель в body можно не ставить: берётся верхний model. Если поставить — должно совпасть.

Один пакет — одна модель и один endpoint, не больше 10 000 запросов.

endpointAPI
/v1/chat/completionsChat Completions
/v1/responsesResponses
/v1/messagesMessages
/v1/embeddingsEmbeddings

Отправка

curl https://api.daaj.ru/v1/batches \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-VTOP Ai-xxx" \
  -d '{
    "endpoint": "/v1/chat/completions",
    "model": "claude-opus-4.8",
    "requests": [
      {
        "custom_id": "req-0001",
        "body": {
          "messages": [
            { "role": "user", "content": "Суммируй VTOP Ai одним предложением." }
          ]
        }
      }
    ]
  }'

Успешный POST возвращает 202 и объект со статусом validating — пакет принят и встал в очередь, это ещё не готовые ответы.

JSON
{
  "id": "batch_123",
  "object": "batch",
  "endpoint": "/v1/chat/completions",
  "model": "claude-opus-4.8",
  "completion_window": "24h",
  "status": "validating",
  "created_at": 1782097200,
  "finalized_at": null,
  "request_counts": {
    "total": 1,
    "completed": 0,
    "failed": 0
  },
  "usage": null,
  "results": null,
  "error": null
}

Единственное окно — 24h.

Опрос

cURL
curl https://api.daaj.ru/v1/batches/batch_123 \
  -H "Authorization: Bearer sk-VTOP Ai-xxx"

Цепочка статусов:

Статусы
validating → in_progress → finalizing → completed

Ещё бывают failed, expired, cancelling, cancelled. Терминальные: completed, failed, expired, cancelled. Опрашивайте, пока не дойдёте до одного из них.

Опрос нужен только чтобы узнать результат. Пакет мы досчитываем сами: раз в минуту планировщик проверяет незавершённые задачи, поэтому резерв освобождается без вашего участия — даже если процесс, отправивший пакет, давно завершился. Можно спокойно закрыть скрипт и вернуться за results позже.

Сразу после POST пакет может пару десятков секунд не находиться у провайдера — в это время GET вернёт статус из нашей записи (validating). Это нормально, повторите опрос.

request_counts — прогресс: total, completed, failed.

Пока пакет не completed, results равен null. После — массив в том же ответе. Каждый элемент склеивается со входом по custom_id. Заполнено ровно одно: response или error.

JSON
{
  "id": "batch_req_123",
  "custom_id": "req-0001",
  "response": {
    "status_code": 200,
    "request_id": "request_123",
    "body": {
      "id": "gen-…",
      "object": "chat.completion",
      "model": "claude-opus-4.8",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "VTOP Ai — единый API к сотням моделей с оплатой в рублях."
          },
          "finish_reason": "stop"
        }
      ]
    }
  },
  "error": null
}

Списание

При POST на балансе резервируется оценка (худший случай по составу пакета, уже со скидкой Batch). Резерв — это не списание: деньги удержаны, но ещё не потрачены, и в истории расходов их нет.

Когда пакет доходит до терминального статуса, списывается факт, а лишнее возвращается. При failed / expired / cancelled резерв возвращается целиком и списания не появляется вообще. Больше зарезервированного с вас не спишут: если провайдер выставил нам больше, разницу оплачиваем мы.

У пакета есть жёсткий срок (expires_at, чуть больше суток — окно выполнения плюс запас). Если к этому времени результата нет, пакет переводится в expired и резерв возвращается полностью. Зависнуть навсегда, удерживая деньги, пакет не может.

Итог в рублях — usage.cost_rub после completed.

Список пакетов и кабинет

cURL
# Ваши пакеты, новые сверху
curl "https://api.daaj.ru/v1/batches?limit=20" \
  -H "Authorization: Bearer sk-VTOP Ai-xxx"

# Все асинхронные задачи (пакеты и видео), которые ещё держат резерв
curl "https://api.daaj.ru/v1/jobs?active=true" \
  -H "Authorization: Bearer sk-VTOP Ai-xxx"

Параметры списка: status, active=true, limit (до 100), after. GET /v1/jobs дополнительно возвращает active_count и active_reserved_rub — сколько задач выполняется и сколько рублей они держат; у каждой записи есть kind, reserved_rub, а после расчёта cost_rub и refunded_rub. Чужой id вернёт 404.

То же самое без кода — Статистика → Задачи в кабинете: сумма резерва, статусы, фактическое списание и возврат, фильтры по типу и статусу. Результаты завершённого пакета оттуда можно выгрузить в JSON. Во вкладке «Расходы» рядом — только фактически потраченное, резервы туда не попадают.

Другие формы API

Все элементы одного пакета — один endpoint. Смешать формы — несколько пакетов.

Пример Messages:

JSON
{
  "endpoint": "/v1/messages",
  "model": "claude-opus-4.8",
  "requests": [
    {
      "custom_id": "req-1",
      "body": {
        "max_tokens": 32,
        "messages": [
          { "role": "user", "content": "Скажи привет." }
        ]
      }
    }
  ]
}

/v1/embeddings работает так же, если у модели в каталоге есть batch. В body обязательно input (строка или массив строк). Картинки и прочий мультимодальный вход в Batch не принимаются — для них синхронный /embeddings.

Ограничения

  • Только текст. Картинки, аудио, видео, файлы в элементах пакета отклоняются. Для них — обычные синхронные эндпоинты.
  • На части моделей все body в пакете должны иметь одинаковый response_format (или все без него). Иначе пакет не пройдёт проверку.
  • Имена пресетов в model не подходят — только каталожные id.