tunnel_ docs

Chat Completions

POST /v1/chat/completions — OpenAI-совместимый эндпоинт. Формат тела и ответа идентичны openai.chat.completions.create(...).

Тело запроса

ПолеТипОбязательноеКомментарий
modelstringдаslug из каталога, например gemini-3.5-flash
messagesarrayда, ≥1 элементrole: system | user | assistant | tool | developer; content: строка, null или массив content-parts
streambooleanнет, по умолчанию falseсм. «Стриминг» ниже
остальные поля (temperature, max_tokens, top_p, stop, …)нетпробрасываются апстриму как есть

Неизвестный model404 model_not_found. Пустое тело/некорректная структура messages400 invalid_request. Подробности — на странице «Коды ошибок».

Передача параметров на Gemini-маршрутах

Для моделей, маршрутизируемых на Google Gemini, в нативный запрос переносятся только temperature и max_tokens — остальные OpenAI-поля (top_p, stop, presence_penalty и т.п.) Gemini не понимает и шлюз их не транслирует. Для моделей на OpenAI-совместимом или Anthropic апстриме пробрасываются все переданные поля.

Пример ответа (без стрима)

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "model": "gemini-3.5-flash",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Привет! Чем могу помочь?" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 8, "completion_tokens": 7, "total_tokens": 15 }
}

Стриминг

С stream: true ответ приходит как Server-Sent Events — чанки в формате chat.completion.chunk, поток завершается строкой data: [DONE]. Родной stream=True у OpenAI SDK читает это без дополнительной настройки.

Python

from openai import OpenAI

client = OpenAI(
    base_url="https://api.aigateway.andrewdev.ru/v1",
    api_key="sk-tn-ВАШ_КЛЮЧ",
)
stream = client.chat.completions.create(
    model="gemini-3.5-flash",
    messages=[{"role": "user", "content": "Напиши хайку про рассвет"}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

JavaScript

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://api.aigateway.andrewdev.ru/v1',
  apiKey: 'sk-tn-ВАШ_КЛЮЧ',
});
const stream = await client.chat.completions.create({
  model: 'gemini-3.5-flash',
  messages: [{ role: 'user', content: 'Напиши хайку про рассвет' }],
  stream: true,
});
for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) process.stdout.write(delta);
}

Если соединение обрывает клиент — апстрим-запрос тоже прерывается (токены после обрыва не тарифицируются). Если обрывается сам апстрим посреди потока — в поток пишется финальное SSE-событие с ошибкой, а списание считается по фактически переданным клиенту чанкам с флагом usage_estimated.

Изображения в content parts

Как и в OpenAI Vision, вместо строки в content передаётся массив частей: текст + image_url с data-URI:

response = client.chat.completions.create(
    model="gemini-3.5-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Что на картинке?"},
                {
                    "type": "image_url",
                    "image_url": {"url": "data:image/png;base64,iVBORw0KGgo..."},
                },
            ],
        }
    ],
)

Для моделей на Gemini- и Anthropic-маршрутах image_url транслируется в нативный inline-формат провайдера; для OpenAI-совместимого апстрима content parts пробрасываются как есть (апстрим должен сам поддерживать vision).

Таймауты и размер тела

ПараметрЗначение
Установление соединения с апстримом10 с
Полный ответ (включая стрим)10 мин
Максимальный размер тела запроса20 МиБ

Превышение таймаута или размера тела возвращает 502/400 в стандартном формате ошибок — см. «Лимиты».