API
Справочник API
Схемы запросов и ответов очень похожи на OpenAI Chat API. AITUNNEL нормализует их для всех моделей и провайдеров — достаточно выучить одну.
Индекс документации
Полный список статей — /llms.txt. К любой странице добавьте .md, чтобы получить исходный markdown без парсинга HTML.
Этот справочник про POST https://api.aitunnel.ru/v1/chat/completions. Те же поля принимают /responses и /messages. Картинки, видео, речь и эмбеддинги — в введении. Понимание и генерация картинок — картинки. PDF в чате — PDF. Понимание и генерация видео — видео. Аудио во входе и выходе чата — аудио. Озвучка текста — озвучка. Распознавание речи — распознавание речи. Методы кабинета — в AITUNNEL API.
Запросы
Схема запроса
Тело POST на /chat/completions:
// Определения подтипов — ниже
type Request = {
// Нужно одно из двух: messages или prompt
messages?: Message[];
prompt?: string;
// Имя модели, пресета или слаг provider/model.
// "auto" — AITUNNEL выберет модель сам.
model?: string;
// JSON по схеме. Подробнее: /docs/structured-outputs
response_format?: ResponseFormat;
stop?: string | string[];
stream?: boolean;
// Сжатие слишком длинного промпта. Включено по умолчанию.
// Подробнее: /docs/transforms
plugins?: Plugin[];
max_tokens?: number; // [1, context_length)
temperature?: number; // [0, 2]
// Function-tools и серверные инструменты (aitunnel:web_search).
// Подробнее: /docs/tool-calling, /docs/web-search
tools?: Tool[];
tool_choice?: ToolChoice;
parallel_tool_calls?: boolean;
seed?: number;
top_p?: number; // (0, 1]
top_k?: number; // [1, ∞) — у OpenAI игнорируется
frequency_penalty?: number; // [-2, 2]
presence_penalty?: number; // [-2, 2]
repetition_penalty?: number; // (0, 2]
logit_bias?: { [key: number]: number };
top_logprobs?: number;
min_p?: number; // [0, 1]
top_a?: number; // [0, 1]
// Предсказанный хвост ответа — меньше задержка, если угадали.
prediction?: { type: "content"; content: string };
// Голосовой ответ. Подробнее: /docs/audio
modalities?: ("text" | "audio")[];
audio?: { voice: string; format: string };
// Параметры AITUNNEL
models?: string[]; // запасные модели. /docs/fallback
provider?: { sort?: "price" | "throughput" | "latency" }; // /docs/provider
reasoning?: Reasoning; // /docs/reasoning
cache_control?: { type: "ephemeral"; ttl?: "5m" | "1h" }; // /docs/caching
session_id?: string; // липкая маршрутизация кэша
service_tier?: "flex" | "priority"; // /docs/service-tiers
};
type TextContent = {
type: "text";
text: string;
};
type ImageContentPart = {
type: "image_url";
image_url: {
url: string; // URL или data:…;base64. Подробнее: /docs/images
detail?: string; // по умолчанию "auto"
};
};
type FileContentPart = {
type: "file";
file: {
filename: string;
file_data: string; // URL или data:application/pdf;base64,… /docs/pdf
};
};
type VideoContentPart = {
type: "video_url";
video_url: {
url: string; // URL или data:video/mp4;base64. Подробнее: /docs/videos
};
};
type AudioContentPart = {
type: "input_audio";
input_audio: {
data: string; // сырой base64, не URL. Подробнее: /docs/audio
format: string; // например "wav" или "mp3"
};
};
type ContentPart =
| TextContent
| ImageContentPart
| FileContentPart
| VideoContentPart
| AudioContentPart;
type Message =
| {
role: "user" | "assistant" | "system";
content: string | ContentPart[];
name?: string;
}
| {
role: "tool";
content: string;
tool_call_id: string;
name?: string;
};
type FunctionDescription = {
description?: string;
name: string;
parameters: object; // JSON Schema
};
type Tool =
| { type: "function"; function: FunctionDescription }
| { type: "aitunnel:web_search"; parameters?: object };
type ToolChoice =
| "none"
| "auto"
| "required"
| { type: "function"; function: { name: string } };
type ResponseFormat =
| { type: "json_object" }
| {
type: "json_schema";
json_schema: {
name: string;
strict?: boolean;
schema: object;
};
};
type Plugin =
| {
id: "context-compression";
enabled?: boolean;
}
| {
id: "file-parser"; // PDF. /docs/pdf
pdf?: { engine?: "mistral-ocr" | "cloudflare-ai" | "native" };
};
type Reasoning = {
effort?:
| "max"
| "xhigh"
| "high"
| "medium"
| "low"
| "minimal"
| "none";
max_tokens?: number;
exclude?: boolean;
enabled?: boolean;
};Сэмплинг, штрафы, stop, logprobs — параметры. Аудио во входе и выходе — аудио.
Структурированный вывод
response_format заставляет модель ответить JSON:
{ "type": "json_object" }— валидный JSON, без схемы{ "type": "json_schema", "json_schema": { … } }— строго по вашей JSON Schema,strict: true
Подробности и примеры — структурированный вывод. Есть не у всех моделей: смотрите страницу модели.
Плагины
Плагины расширяют запрос на стороне AITUNNEL, не модели. Сжатие середины промпта включено по умолчанию. Чтобы выключить:
{
"plugins": [{ "id": "context-compression", "enabled": false }]
}Подробнее — оптимизация сообщений. PDF — плагин file-parser, см. PDF. Поиск в сети — не плагин, а серверный инструмент aitunnel:web_search.
Стриминг
SSE для всех моделей
Передайте stream: true. Формат — Server-Sent Events. usage приходит один раз в финальном чанке с пустым choices, перед [DONE]. Примеры и разбор ошибок — стриминг.
Нестандартные параметры
Если модель не умеет параметр (например logit_bias не у OpenAI или top_k у OpenAI), он игнорируется. Остальное уходит провайдеру как есть.
Маршрутизация модели
model— id из каталога, имя пресета,autoили слагprovider/modelдля OpenRouter.- Несколько моделей подряд при сбое — массив
models. - Сортировка провайдеров —
provider.sort.
В ответе поле model — фактически использованная модель, не пресет и не auto.
Предзаполнение ответа
Можно попросить модель продолжить начатую реплику: последнее сообщение с role: "assistant" — это префикс, который она допишет.
curl https://api.aitunnel.ru/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-aitunnel-xxx" \
-d '{
"model": "gpt-5.4",
"messages": [
{ "role": "user", "content": "В чём смысл жизни?" },
{ "role": "assistant", "content": "Не уверен, но моё лучшее предположение:" }
]
}'Ответы
Схема нормализована под OpenAI Chat Completions. choices всегда массив. При стриминге у выбора есть delta, иначе — message. Один и тот же код работает со всеми моделями.
type Response = {
id: string;
choices: (NonStreamingChoice | StreamingChoice | NonChatChoice)[];
created: number; // Unix timestamp
model: string; // фактически использованная модель
object: "chat.completion" | "chat.completion.chunk";
system_fingerprint?: string;
usage?: ResponseUsage;
};
type ResponseUsage = {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
cost_rub: number; // сколько списали за этот запрос
balance: number; // остаток кабинета после списания
prompt_tokens_details?: {
cached_tokens?: number;
cache_write_tokens?: number;
};
completion_tokens_details?: {
reasoning_tokens?: number;
};
server_tool_use?: {
web_search_requests?: number;
};
};
type NonChatChoice = {
finish_reason: string | null;
text: string;
error?: ErrorResponse;
};
type NonStreamingChoice = {
finish_reason: string | null;
native_finish_reason: string | null;
message: {
content: string | null;
role: string;
tool_calls?: ToolCall[];
reasoning?: string;
reasoning_details?: unknown[];
audio?: { data: string; transcript?: string };
};
error?: ErrorResponse;
};
type StreamingChoice = {
finish_reason: string | null;
native_finish_reason: string | null;
delta: {
content: string | null;
role?: string;
tool_calls?: ToolCall[];
audio?: { data?: string; transcript?: string };
};
error?: ErrorResponse;
};
type ErrorResponse = {
code: number;
message: string;
metadata?: Record<string, unknown>;
};
type ToolCall = {
id: string;
type: "function";
function: { name: string; arguments: string };
};Пример:
{
"id": "chatcmpl-xxxxxxxxxxxxxx",
"choices": [
{
"finish_reason": "stop",
"native_finish_reason": "stop",
"message": {
"role": "assistant",
"content": "Привет!"
}
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 4,
"total_tokens": 16,
"prompt_tokens_details": { "cached_tokens": 0 },
"completion_tokens_details": { "reasoning_tokens": 0 },
"cost_rub": 0.51,
"balance": 1212.38933
},
"model": "gpt-5.4"
}Причина завершения
finish_reason приводится к одному из: tool_calls, stop, length, content_filter, error.
Исходная строка провайдера — в native_finish_reason.
Стоимость и usage
usage всегда есть в нестриминговом ответе. При стриминге — в последнем чанке.
prompt_tokens/completion_tokens/total_tokens— как вернул провайдерcost_rub— сколько списали за этот запросbalance— остаток кабинета после списанияprompt_tokens_details.cached_tokens— чтение кэша промптаcompletion_tokens_details.reasoning_tokens— токены рассужденийserver_tool_use.web_search_requests— фактические вызовы веб-поиска
История расхода по ключу — статистика, не отдельный generation-эндпоинт.
Дальше
temperature, max_tokensПараметры
Сэмплинг, длина ответа, stop, logprobs, verbosity.
toolsВызов инструментов
Модель предлагает вызов — вы исполняете у себя.
response_formatСтруктурированный вывод
JSON по схеме, без выдуманных полей.
reasoningТокены рассуждений
effort, max_tokens и reasoning_details между шагами.
error.codeОшибки и отладка
JSON-ошибки, 402 из-за max_tokens, стрим и пустой ответ.
aitunnel:web_searchВеб-поиск
Модель сама ищет в сети, когда решит.