Получайте ответ потоком

Следите за нативными SSE-событиями и отличайте завершение от обрыва соединения.

Задайте BASE_URL как корневой HTTPS-адрес API без завершающего / и без /v1, а API_KEY передайте из хранилища секретов. OpenAI-совместимые SDK используют ${BASE_URL}/v1, Anthropic-совместимые — BASE_URL.

Используйте поток, когда клиент умеет обрабатывать Server-Sent Events (SSE) и должен показывать вывод до завершения генерации. Нужны активный ключ организации, доступная модель из каталога и кредиты. Запрос может списать кредиты. Опция curl -N отключает буферизацию вывода, а -i показывает начальный статус и заголовки.

Отправьте ограниченный запрос

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

bash
export UNLIMGPT_REQUEST_KEY="$(openssl rand -hex 16)"

В той же оболочке отправьте запрос. Проверка не позволит начать генерацию, если ключ не был создан:

bash
test -n "${UNLIMGPT_REQUEST_KEY:-}" \
  && printf 'Authorization: Bearer %s\n' "$API_KEY" \
  | curl -q -H @- -i -N "$BASE_URL/v1/responses" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $UNLIMGPT_REQUEST_KEY" \
    -d '{
  "model": "gpt-5.6-sol",
  "input": "Посчитай до трёх.",
  "max_output_tokens": 64,
  "stream": true
}'

Замените ID модели, если каталог вашей организации показывает другую доступную модель. При повторе запускайте только второй блок с прежним ключом и тем же телом: повторное выполнение команды OpenSSL создаст новый логический запрос. Успешное соединение начинается с HTTP 200. Затем Responses отдаёт именованные события, например response.created, response.output_text.delta и response.completed. Сохраните публичный ID ответа из потока. Текст и число событий с частями ответа будут отличаться; один сетевой блок не обязательно равен одному событию.

Дождитесь завершающего события

Читайте события до терминального события протокола и только затем считайте вызов завершённым. Chat Completions использует блоки data с choices и завершающий маркер; Messages — message_start, content_block_delta и message_stop. Закрытие соединения до терминального события не доказывает завершение. Терминальная ошибка может прийти уже после начального HTTP 200, поэтому один HTTP-статус не описывает результат потока.

ПротоколКак увидеть успешное завершениеЧто означает частичный или ошибочный результат
Responsesresponse.completed, затем data: [DONE]response.incomplete содержит причину ограничения; response.failed содержит безопасный публичный код ошибки.
Chat CompletionsПоследняя часть choices[0].finish_reason, затем data: [DONE]length означает частичный текст; после HTTP 200 ошибка может прийти отдельным JSON-объектом в data.
Messagesmessage_delta со stop_reason, затем message_stopmax_tokens означает ограничение длины; event: error означает ошибку уже открытого потока.

Для Chat Completions stream_options.include_usage: true добавляет перед [DONE] отдельную часть с пустым choices и usage. У Messages usage приходит в message_delta; у Responses — в терминальном объекте ответа. Не прибавляйте токены повторно, если сначала видели предварительную часть, а затем итоговую. Парсер SSE должен собирать полные события по пустой строке между ними и учитывать, что одна сетевая порция может содержать несколько событий или часть одного.

Если соединение оборвалось, сохраните ID ответа и ключ идемпотентности логического запроса, затем проверьте активность API той же организации. Не создавайте сразу новый запрос с новым ключом: он может запустить вторую генерацию. Перед повтором откройте безопасные повторы и диагностику подключения.

Отмена и различия протоколов

Для клиента с API-ключом закрытие потока отменяет запрос. Обрыв браузерного чата не отменяет запуск; пользователь может остановить его явно. Responses также поддерживает POST /v1/responses/{id}/cancel для явной отмены. Используйте ID, возвращённый Responses, а не HTTP-заголовок request-id. Протокол описан в Responses, терминальные ошибки — в ошибках и лимитах.