---
title: "Как устроен API: протоколы и списание — AI Creator API"
description: "Как работает AI Creator API: три протокола, имена моделей и алиасы, стриминг, резерв и списание с баланса, что мы храним о запросах."
url: https://llm.aicreator.app/docs/how-it-works/
lang: ru
updated: 2026-11-10
---

# Как устроен API

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

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

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

| Протокол                | Запрос                      | Кто пользуется                     |
| ----------------------- | --------------------------- | ---------------------------------- |
| Anthropic Messages      | `POST /v1/messages`         | Claude Code, Anthropic SDK         |
| OpenAI Responses        | `POST /v1/responses`        | Codex CLI, OpenAI SDK              |
| OpenAI Chat Completions | `POST /v1/chat/completions` | Cline, OpenCode, Aider, OpenAI SDK |

Один протокол в другой мы не переводим. Запрос к модели по протоколу, на котором её нет, вернёт 400 `model_not_available`. Форматы запросов и ответов — как у официальных API Anthropic и OpenAI; все пути и заголовки — в [справочнике API](https://llm.aicreator.app/docs/api/).

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

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

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

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

| Алиас    | Модель              |
| -------- | ------------------- |
| `opus`   | `claude-opus-5-5`   |
| `sonnet` | `claude-sonnet-5-5` |
| `haiku`  | `claude-haiku-5-5`  |
| `fable`  | `claude-fable-5-1`  |

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

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

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

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

Отказ на этом шаге ничего не стоит и в журнал запросов кабинета не попадает. Дальше запрос уходит провайдеру, ответ возвращается тебе в том виде, в каком пришёл, а с баланса списывается сумма по фактическим токенам. Ответ на запрос, который дошёл до провайдера, несёт заголовок `X-Billing-Id` — по нему запрос находится в выгрузке статистики. Коды отказов — в разделе [«Ошибки и лимиты»](https://llm.aicreator.app/docs/errors/).

## Стриминг

С `"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 минут. Подробности — в разделе [«Биллинг и статистика»](https://llm.aicreator.app/docs/billing/#charging).

## Чьи ошибки

Ошибки бывают двух видов. Наши — когда запрос остановили мы; у них общий 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)
```

```javascript title="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);
```
