Получайте ответ потоком
Следите за нативными SSE-событиями и отличайте завершение от обрыва соединения.
Следите за нативными SSE-событиями и отличайте завершение от обрыва соединения.
Задайте BASE_URL как корневой HTTPS-адрес API без завершающего / и без /v1, а API_KEY передайте из хранилища секретов. OpenAI-совместимые SDK используют ${BASE_URL}/v1, Anthropic-совместимые — BASE_URL.
Используйте поток, когда клиент умеет обрабатывать Server-Sent Events (SSE) и должен показывать вывод до завершения генерации. Нужны активный ключ организации, доступная модель из каталога и кредиты. Запрос может списать кредиты. Опция curl -N отключает буферизацию вывода, а -i показывает начальный статус и заголовки.
Сначала один раз создайте случайный ключ логического запроса. Пример для оболочки с OpenSSL; в приложении используйте свой криптографически стойкий генератор и сохраняйте ключ вместе с неизменным телом запроса до терминального исхода:
export UNLIMGPT_REQUEST_KEY="$(openssl rand -hex 16)"
В той же оболочке отправьте запрос. Проверка не позволит начать генерацию, если ключ не был создан:
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-статус не описывает результат потока.
| Протокол | Как увидеть успешное завершение | Что означает частичный или ошибочный результат |
|---|---|---|
| Responses | response.completed, затем data: [DONE] | response.incomplete содержит причину ограничения; response.failed содержит безопасный публичный код ошибки. |
| Chat Completions | Последняя часть choices[0].finish_reason, затем data: [DONE] | length означает частичный текст; после HTTP 200 ошибка может прийти отдельным JSON-объектом в data. |
| Messages | message_delta со stop_reason, затем message_stop | max_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, терминальные ошибки — в ошибках и лимитах.