API

Ошибки и отладка

Неверный запрос, ключ или баланс приходят HTTP-ошибкой. Если модель уже генерирует — статус 200, а сбой в теле ответа или в SSE.

Форма ответа

TypeScript
type ErrorResponse = {
  error: {
    code: number;
    message: string;
    metadata?: Record<string, unknown>;
  };
};

HTTP-статус совпадает с error.code, если запрос отклонили до генерации: неверные параметры, нет ключа, не хватает баланса.

Если модель уже начала отвечать, HTTP будет 200, а ошибка придёт в теле или событием SSE. Подробнее — стриминг.

const request = await fetch("https://api.aitunnel.ru/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: "Bearer sk-aitunnel-xxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "gpt-5.4",
    messages: [{ role: "user", content: "Привет" }],
  }),
});

console.log(request.status); // код ошибки, если модель ещё не начала генерацию
const response = await request.json();
console.error(response.error?.code);
console.error(response.error?.message);

Коды ошибок

  • 400 — неверный запрос: нет модели, битый JSON, неизвестное имя модели, слишком длинный промпт. Блокировка PII тоже 400.
  • 401 — нет Authorization: Bearer sk-aitunnel-… или ключ недействителен.
  • 402 — не хватает средств на прогноз стоимости. Если не задан max_tokens / max_output_tokens, берётся максимум модели — прогноз огромный, хотя списываются только фактические токены. Укажите лимит или пополните баланс. Подробнее — FAQ про 402. Тот же код, если превышен бюджет ключа.
  • 403 — IP не в белом списке ключа или провайдер отклонил ввод модерацией.
  • 408 — запрос превысил время ожидания.
  • 429 — лимит запросов провайдера, не AITUNNEL. Мы сами повторяем такие запросы. Если 429 всё равно приходит, задайте запасные модели. Подробнее — лимиты.
  • 502 — модель недоступна или провайдер вернул недействительный ответ.
  • 503 — временный сбой (редко — биллинг). Повторите позже.

Ошибки модерации

Если ввод пометили, в error.metadata будет причина:

TypeScript
type ModerationErrorMetadata = {
  reasons: string[]; // почему пометили ввод
  flagged_input: string; // фрагмент до 100 символов; длиннее — обрезан посередине через …
  provider_name: string; // кто запросил модерацию
  model_slug: string;
};

Сообщение error.message уже переписано по-русски: какой провайдер отклонил и почему.

Ошибки провайдера

Если упал апстрим, в error.metadata может быть:

TypeScript
type ProviderErrorMetadata = {
  provider_name: string; // провайдер, у которого случилась ошибка
  raw?: unknown; // исходный текст ошибки, без внутренних ссылок
};

Внутренние ссылки и брендинг из текста ошибки вычищаются. Не полагайтесь на точный вид raw — ориентируйтесь на code и message.

Когда ответа нет

Иногда модель не генерирует текст: холодный старт или масштабирование у провайдера. Обычно это секунды, иногда минуты.

Если пустые ответы повторяются — простой retry или другая модель / запасные модели.

Списание за промпт

В части случаев провайдер всё равно берёт плату за обработку промпта, даже если токенов ответа не было.

Ошибки в стриме

До первого токена — обычный JSON и HTTP 4xx/5xx. После начала генерации статус уже 200: ошибка приходит SSE-событием с error и finish_reason: "error". Примеры кода — стриминг.

Что проверить

  1. error.message — там обычно сказано, что не так.
  2. 402 при большом или отсутствующем max_tokens FAQ.
  3. 429 / 502 запасные модели.
  4. Неизвестная модель — в сообщении часто есть похожее имя из каталога.
  5. В стриме смотрите error в каждом чанке, не только HTTP-статус.