Как устроен API

Открыть в Markdown
На этой странице

AI Creator API — прокси между твоим инструментом и провайдером модели. Он проверяет ключ и лимиты, резервирует деньги на балансе, передаёт запрос провайдеру и возвращает его ответ. Тело запроса уходит как есть; меняется только имя модели, если это алиас.

Три протокола#

Мы отвечаем по трём протоколам. Какой нужен, решает инструмент, а не ты:

ПротоколЗапросКто пользуется
Anthropic MessagesPOST /v1/messagesClaude Code, Anthropic SDK
OpenAI ResponsesPOST /v1/responsesCodex CLI, OpenAI SDK
OpenAI Chat CompletionsPOST /v1/chat/completionsCline, OpenCode, Aider, OpenAI SDK

Один протокол в другой мы не переводим. Запрос к модели по протоколу, на котором её нет, вернёт 400 model_not_available. Форматы запросов и ответов — как у официальных API Anthropic и OpenAI; все пути и заголовки — в справочнике API.

Адрес для клиентов Anthropic — https://api.aicreator.app, для клиентов OpenAI — https://api.aicreator.app/v1. Для России есть второй адрес того же API — https://api-ru.aicreator.app: ключи, пути и баланс общие.

Имена моделей и алиасы#

В поле model мы принимаем только имена из своего списка — они перечислены в разделе «Модели и цены», а для своего ключа их отдаёт GET /v1/models. Имя пишется буква в букву: другое написание той же модели получит 400 model_not_available.

Четыре коротких имени, которые присылает Claude Code, мы заменяем сами:

АлиасМодель
opusclaude-opus-5-5
sonnetclaude-sonnet-5-5
haikuclaude-haiku-5-5
fableclaude-fable-5-1

Запрос с алиасом считается и оплачивается как запрос к модели, в которую он превратился.

Что происходит с запросом#

До отправки провайдеру мы проверяем:

  • ключ — иначе 401;
  • лимиты ключа и сервиса — иначе 429;
  • что модель есть на этом протоколе и разрешена ключу — иначе 400 или 403;
  • что баланс вмещает резерв под запрос — иначе 402.

Отказ на этом шаге ничего не стоит и в журнал запросов кабинета не попадает. Дальше запрос уходит провайдеру, ответ возвращается тебе в том виде, в каком пришёл, а с баланса списывается сумма по фактическим токенам. Ответ на запрос, который дошёл до провайдера, несёт заголовок X-Billing-Id — по нему запрос находится в выгрузке статистики. Коды отказов — в разделе «Ошибки и лимиты».

Стриминг#

С "stream": true ответ приходит как SSE. Поток провайдера мы передаём байт в байт: те же события в том же порядке.

  • Если модель молчит дольше 15 секунд, мы шлём keepalive: event: ping в протоколе Anthropic и SSE-комментарий : ping в протоколах OpenAI.
  • В стриме Chat Completions мы всегда включаем stream_options.include_usage: последним приходит чанк с пустым choices: [] и статистикой токенов. Свой клиент должен проверять, что choices не пуст.
  • Один запрос длится не дольше 30 минут.

Почему длинные ответы нужно стримить#

Запрос без стрима ждёт весь ответ молча: пока модель работает, по соединению ничего не идёт. Перед нашим API стоит Cloudflare, и если ответа нет дольше примерно двух минут, он закрывает соединение с кодом 524, хотя модель ещё работает. Адрес для России идёт через тот же Cloudflare, так что и там правило то же.

На стрим это ограничение не действует: данные или keepalive идут постоянно.Для длинных ответов и долгого thinking включай "stream": true. Claude Code и Codex стримят сами.

Резерв и списание#

  1. Перед запросом мы резервируем на балансе сумму по оценке. Не хватает баланса — ответ 402 insufficient_balance, и провайдеру запрос не уходит.
  2. После ответа списываем сумму по фактическим токенам из ответа провайдера. Остаток резерва сразу возвращается на баланс; списание не бывает больше резерва.

Резерв заведомо больше цены запроса. Вход оценивается по размеру тела: байты, делённые на 3, плюс 8 192 токенов запаса. Выход — по max_tokens, а без него — по максимуму модели. К сумме добавляется 20%. Поэтому на небольшом балансе задавай max_tokens явно.

Запрос, который отклонён или упал до начала генерации, ничего не стоит: резерв возвращается целиком. Если генерация оборвалась на середине, оплачивается то, что модель успела сгенерировать. В редком случае сбоя на нашей стороне резерв возвращается примерно через 45 минут. Подробности — в разделе «Биллинг и статистика».

Чьи ошибки#

Ошибки бывают двух видов. Наши — когда запрос остановили мы; у них общий JSON-формат с полем error.code. Ошибки провайдера приходят как есть, в формате его протокола, вместе с заголовками retry-after и x-should-retry — инструменты узнают их и повторяют запрос так же, как с официальным API.

Что мы храним#

  • О каждом запросе, который дошёл до провайдера, — числа: модель, ключ, протокол, токены входа, выхода и кэша, цену, статус, задержку и время до первого токена. Это и есть журнал запросов в кабинете.
  • Тексты промптов и ответов мы не храним и в логи не пишем.
  • От ключа хранится только хеш и начало; полный ключ в логи не попадает.

Это описание наших серверов. Чтобы модель ответила, тело запроса уходит её провайдеру как есть.

Свой код#

Официальные SDK работают без правок: поменяй base URL и ключ. Пример на OpenAI SDK:

Python
from openai import OpenAI

client = OpenAI(base_url="https://api.aicreator.app/v1", api_key="sk-aic-…")
reply = client.chat.completions.create(
    model="gpt-6-astra",
    messages=[{"role": "user", "content": "Hello"}],
)
print(reply.choices[0].message.content)
Node.js
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.aicreator.app/v1", apiKey: process.env.AIC_API_KEY });
const reply = await client.chat.completions.create({
  model: "gpt-6-astra",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(reply.choices[0].message.content);