Responses API
/v1/responsesOpenAI Responses API — на этот путь настраивается Codex CLI.
Запрос
modelstringbodyобязательноinputstring|arraybodyобязательноstreambooleanbodymax_output_tokensintegerbodyОтветы
Response
{
"id": "resp_…",
"object": "response",
"status": "completed",
"model": "gpt-5.6-sol",
"output": [
{ "type": "message", "role": "assistant",
"content": [{ "type": "output_text", "text": "Hello!" }] }
],
"usage": { "input_tokens": 9, "output_tokens": 12, "cost_usd": "0.0000465" }
}Подробности
Нужен ключ в заголовке Authorization: Bearer или x-api-key.
Проксируется в OpenAI-совместимый апстрим ровно так же, как чат: перечислены только поля, которые читает сам шлюз, всё остальное тело (tools, reasoning, instructions, text и прочее) уходит как есть. Ручка нужна отдельным пунктом потому, что именно на неё настраивается Codex CLI: wire_api = "responses" в ~/.codex/config.toml.
Стоимость этого запроса приходит в самом ответе: заголовок x-teamtoken-cost-usd и поле usage.cost_usd в теле. Значение — строка с десятичной записью («0.0000465»), а не число: число после парсинга показывалось бы по правилам языка клиента (Python выдал бы 4.65e-05), строка доходит до кода ровно такой, как записана. Стоимость может и не прийти — тогда её нет ни в заголовке, ни в поле: в нестриминговом ответе так бывает, когда апстрим её не сообщил, в стриме — когда у модели нет тарифа в каталоге. Стрим здесь идёт именованными SSE-событиями. Шлюз пытается дописать стоимость в кадр с usage (у Responses API он вложен в response.completed), но переписывает только кадр, начинающийся с data: — кадр с отдельной строкой event: уходит нетронутым, и тогда стоимость в стриме не приходит. В нестриминговом ответе стоимость приходит и заголовком, и полем.
Байт-в-байт такой же запрос с тем же ключом в пределах короткого TTL (по умолчанию 60 с) не уезжает в модель повторно — шлюз отдаёт тело первого ответа и второй раз денег не берёт. Кэшируется только успешный ответ не больше 256 КБ; всё остальное уедет апстриму заново. У повтора из кэша нет заголовка x-teamtoken-cost-usd (списания не было), а cost_usd в теле — от первого, оплаченного ответа. Отсюда же следствие: уже оплаченный ответ отдаётся и при пустом кошельке — проверка баланса стоит ПОСЛЕ идемпотентности. Любая ошибка приходит одним конвертом (поле code — не у каждого статуса): { "error": { "message": "...", "type": "...", "code": "PROVIDER_CODE" } }.
Модерация, когда она включена, читает текст запроса и блокирует его только по реальному вердикту: недоступный или отвечающий ошибкой модератор запрос пропускает. Ответ всегда несёт то логическое имя модели, которое ты запросил. Если ответ не уложился в таймаут ожидания шлюза (по умолчанию чтение 300 с, в стриме 60 с без байтов), приходит 504; нестриминговую попытку шлюз при этом помечает, и если апстрим всё же досчитал и списал, реконсайлер возвращает сумму на баланс компенсирующим грантом. Из тел ошибок вычищены имена хостов апстрима, поэтому текст ошибки может отличаться от того, что прислал апстрим.
Своего маршрута у этого пути нет: все POST /v1/* принимает один обработчик шлюза, и список принимаемых путей у него закрытый — на любой другой /v1/* приходит 404.