ДЛЯ РАЗРАБОТЧИКОВ
Руководство разработчика
Единый API к десяткам LLM-провайдеров. Совместим с OpenAI и Anthropic SDK — меняются только base URL и ключ. Base URL: https://api.vozmiapi.ru/v1. Ключи выглядят как sk-am-….
1. Быстрый старт
Три шага: получить ключ, сделать первый запрос, встроить в свой код.
- Зарегистрируйтесь и войдите в кабинет.
- Раздел API-ключи → «Создать ключ». Сырой ключ
sk-am-…показывается один раз — сохраните его. - Подставьте ключ и base URL в примеры ниже. Стартовый баланс уже начислен — можно сразу пробовать.
curl https://api.vozmiapi.ru/v1/chat/completions \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [{"role": "user", "content": "Привет!"}]
}'from openai import OpenAI
client = OpenAI(
base_url="https://api.vozmiapi.ru/v1",
api_key="sk-am-...",
)
resp = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Привет!"}],
)
print(resp.choices[0].message.content)Формат provider/model (например openai/gpt-4o, anthropic/claude-3-5-sonnet). Полный список — публичный эндпоинт GET https://api.vozmiapi.ru/v1/models или страница Модели.
2. Аутентификация
Два независимых механизма:
- API (chat, messages, embeddings и т.д.) — заголовок
Authorization: Bearer sk-am-…. - Кабинет (управление ключами, баланс, статистика) — JWT
access_token, выдаётся при логине, живёт 7 дней.
POST /api/v1/auth/register
curl -X POST https://api.vozmiapi.ru/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"...","name":"Alice"}'POST /api/v1/auth/login
Возвращает access_token (JWT). После 5 неудачных попыток за 15 минут — 429 + retry_after_sec (см. Rate limits).
GET /api/v1/auth/meJWT
GET /api/v1/api-keysJWT
Список ваших ключей (без самих секретов).
POST /api/v1/api-keysJWT
Тело: { name, rate_limit_rpm?, credit_cap_kop? }. Сырой ключ возвращается только в ответе на создание.
3. OpenAI SDK
Полная совместимость с chat.completions.create(). Единственное изменение в вашем коде — base URL и ключ. Остальное (модели, роли, параметры) работает как есть.
from openai import OpenAI
client = OpenAI(
base_url="https://api.vozmiapi.ru/v1", # ← единственное изменение
api_key="sk-am-...", # ← и ключ
)
resp = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[
{"role": "system", "content": "Ты — лаконичный ассистент."},
{"role": "user", "content": "Объясни smart-blend одним предложением."},
],
temperature=0.7,
)
print(resp.choices[0].message.content)import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.vozmiapi.ru/v1', // ← единственное изменение
apiKey: 'sk-am-...', // ← и ключ
});
const resp = await client.chat.completions.create({
model: 'openai/gpt-4o-mini',
messages: [{ role: 'user', content: 'Привет!' }],
});
console.log(resp.choices[0].message.content);Endpoint напрямую: POST https://api.vozmiapi.ru/v1/chat/completions. Также поддержаны /completions (legacy), /moderations.
4. Anthropic SDK
Совместимо с messages.create().
/v1/messages к base URL, поэтому здесь base URL заканчивается на /api (а не /api/v1). Итоговый запрос уходит на https://api.vozmiapi.ru/v1/messages.from anthropic import Anthropic
client = Anthropic(
base_url="https://api.vozmiapi.ru/api", # SDK добавит /v1/messages
api_key="sk-am-...",
)
msg = client.messages.create(
model="anthropic/claude-3-5-sonnet",
max_tokens=1024,
messages=[{"role": "user", "content": "Привет!"}],
)
print(msg.content[0].text)import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
baseURL: 'https://api.vozmiapi.ru/api', // SDK добавит /v1/messages
apiKey: 'sk-am-...',
});
const msg = await client.messages.create({
model: 'anthropic/claude-3-5-sonnet',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Привет!' }],
});
console.log(msg.content[0].text);Прямой вызов без SDK: POST https://api.vozmiapi.ru/v1/messages. Поддержаны image content blocks, tools / tool_use / tool_result и SSE-стриминг.
5. Streaming (SSE)
Добавьте "stream": true — ответ приходит SSE-чанками в формате OpenAI (data: {...}, финал — data: [DONE]).
curl -N https://api.vozmiapi.ru/v1/chat/completions \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o-mini",
"stream": true,
"messages": [{"role": "user", "content": "Считай до 5"}]
}'stream = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Напиши хокку про API"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)Для точного учёта токенов в стриме шлюз запрашивает stream_options.include_usage у провайдера автоматически.
6. Tools / function calling
Передайте tools в формате OpenAI. Если модель решает вызвать функцию, ответ приходит с finish_reason: "tool_calls" и массивом tool_calls.
curl https://api.vozmiapi.ru/v1/chat/completions \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o",
"messages": [{"role": "user", "content": "Погода в Бишкеке?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Текущая погода по городу",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}],
"tool_choice": "auto"
}'resp = client.chat.completions.create(
model="openai/gpt-4o",
messages=messages,
tools=tools,
)
call = resp.choices[0].message.tool_calls[0]
# call.function.name == "get_weather"
# call.function.arguments == '{"city": "Бишкек"}' (JSON-строка)
result = get_weather(**json.loads(call.function.arguments))
# Второй заход: возвращаем результат тем же tool_call_id
messages += [
resp.choices[0].message,
{"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)},
]
final = client.chat.completions.create(model="openai/gpt-4o", messages=messages)
print(final.choices[0].message.content)Совет: указывайте модели с флагом tools в каталоге. В Anthropic-формате то же самое через tools + tool_use / tool_result content blocks.
7. Vision (изображения на вход)
В content сообщения передайте массив частей: text + image_url. Ссылка может быть URL или data:-URI с base64.
curl https://api.vozmiapi.ru/v1/chat/completions \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o",
"messages": [{
"role": "user",
"content": [
{ "type": "text", "text": "Что на картинке?" },
{ "type": "image_url",
"image_url": { "url": "https://example.com/cat.jpg" } }
]
}]
}'import base64
with open("photo.jpg", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
resp = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Опиши изображение"},
{"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{b64}"}},
],
}],
)
print(resp.choices[0].message.content)8. Images (генерация)
POST /api/v1/images/generationsAPI key
curl https://api.vozmiapi.ru/v1/images/generations \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-d '{
"model": "openai/dall-e-3",
"prompt": "рысь в стиле минимализма, векторный логотип",
"n": 1,
"size": "1024x1024"
}'OpenAI-совместимый ответ (массив data[].url или b64_json). Также есть POST /api/v1/images/edits (multipart, с маской).
9. Embeddings
POST /api/v1/embeddingsAPI key
curl https://api.vozmiapi.ru/v1/embeddings \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-d '{
"model": "openai/text-embedding-3-small",
"input": ["первый текст", "второй текст"]
}'resp = client.embeddings.create(
model="openai/text-embedding-3-small",
input=["первый текст", "второй текст"],
)
vectors = [d.embedding for d in resp.data]Биллинг — по prompt_tokens (completion для embeddings нет). Smart-blend не применяется — одна модель = одно embedding-пространство.
10. Rerank
POST /api/v1/rerankAPI key
curl https://api.vozmiapi.ru/v1/rerank \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-d '{
"model": "cohere/rerank-multilingual-v3.0",
"query": "как подключить оплату",
"documents": [
"Интеграция ЮKassa занимает 1 день",
"Рецепт борща",
"СБП работает через QR"
],
"top_n": 2
}'Ответ — passthrough провайдера (ранжированные документы с relevance_score). Биллинг по сумме токенов query + documents.
11. Audio (TTS / STT)
POST /api/v1/audio/speechAPI key
curl https://api.vozmiapi.ru/v1/audio/speech \
-H "Authorization: Bearer sk-am-..." \
-H "Content-Type: application/json" \
-o speech.mp3 \
-d '{
"model": "openai/tts-1",
"input": "Привет! Это синтез речи через возьми API.",
"voice": "alloy",
"response_format": "mp3"
}'Ответ — бинарный аудиопоток (audio/mpeg). Обратная операция (распознавание) — POST /api/v1/audio/transcriptions (Whisper, multipart-загрузка файла).
12. Smart-blend
Smart-blend классифицирует запрос по сложности и для простых задач прозрачно подменяет дорогую модель на более дешёвую того же класса — экономия без потери качества. Сложные (hard) запросы всегда идут на запрошенную модель.
| Уровень | Поведение |
|---|---|
| off | Подмены нет — всегда запрошенная модель. |
| low | Подмена только для тривиальных запросов. |
| medium | Тривиальные и часть стандартных (баланс по умолчанию). |
| high | Максимальная экономия: всё, кроме hard. |
Per-request (заголовок):
curl https://api.vozmiapi.ru/v1/chat/completions \
-H "Authorization: Bearer sk-am-..." \
-H "X-AiMost-Blend: off" \
-H "Content-Type: application/json" \
-d '{ "model": "openai/gpt-4o", "messages": [...] }'Account-wide (preferences):
curl -X PATCH https://api.vozmiapi.ru/v1/auth/preferences \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{ "blend_enabled": true, "blend_aggressiveness": "medium" }'Заголовки ответа при активном blend:
X-AiMost-Requested-Model— что запросили.X-AiMost-Served-Model— что реально обслужили.X-AiMost-Blend-Reason—trivial/standard/hard/opt-out/disabled/no-target.X-AiMost-Saved-Kop— сколько копеек сэкономлено подменой.
13. Кеширование
Идентичные запросы (exact-hash по телу и модели) отдаются из кеша мгновенно. При попадании в кеш списывается только 10% стоимости генерации.
Заголовки ответа:
X-AiMost-Cache—hit-l1(из кеша) илиmiss(живой вызов провайдера).X-AiMost-Cache-Age-Sec— возраст закешированного ответа в секундах (только при hit).
Кеш чувствителен к любому изменению тела (модель, сообщения, температура и т.д.) — разные параметры дают разный хеш. Стриминг из кеша не отдаётся (стрим всегда живой).
14. Ошибки API
Тело ошибки — в стиле OpenRouter: { "error": { "code", "message", "metadata" } }. HTTP-код совпадает с code.
| Код | Значение |
|---|---|
| 400 | Некорректный запрос (нет model / messages, битый JSON). |
| 401 | Нет / неверный ключ или JWT. |
| 402 | Недостаточно средств (insufficient_balance) — пополните баланс. |
| 403 | Доступ запрещён (провайдер вне allowlist, data-policy, не тот scope ключа). |
| 404 | Неизвестная модель или маршрут. |
| 429 | Rate limit (лимит ключа в минуту или брутфорс логина) — см. retry_after_sec. |
| 5xx | Ошибка шлюза / провайдера (502 upstream_unreachable, 503 — сервис недоступен). |
{
"error": {
"code": 402,
"message": "insufficient_balance",
"metadata": { "balance_kop": "0" }
}
}15. Rate limits
- Per-key RPM. У каждого ключа есть
rate_limit_rpm(запросов в минуту), настраивается при создании / черезPATCH /api/v1/api-keys/:id. Превышение →429. - Брутфорс логина. 5 неудачных попыток
/auth/loginза 15 минут →429с полемretry_after_sec(сколько ждать до следующей попытки).
{ "error": { "code": 429, "message": "too_many_attempts",
"metadata": { "retry_after_sec": 540 } } }16. Billing
Биллинг в рублях, внутренняя единица — копейка (amount_kop, balance_kop — целые как строка). Модель списания: reserve (резерв под запрос) → settle (финальный расчёт по факту токенов). Стоимость каждой генерации логируется.
GET /api/v1/creditsJWT
Текущий баланс: { data: { balance_kop } }.
GET /api/v1/generationsJWT
Лог генераций с пагинацией ?page=1&per_page=20 (max 100). Одна запись — GET /api/v1/generations/:id, выгрузка — GET /api/v1/generations.csv.
GET /api/v1/usage/summaryJWT
Дневная агрегация для графиков. ?days=30 (1..90).
GET /api/v1/depositsJWT
История пополнений баланса.
Пополнение через ЮKassa / СБП подключается на этапе интеграции с платёжным провайдером — эндпоинты (POST /api/v1/payments/yookassa/create и webhook /api/v1/webhooks/yookassa) уже заложены и активируются после подключения ключей ЮKassa.
17. Webhooks (исходящие)
Настраиваются в кабинете: /dashboard/webhooks. После наступления события шлём POST с JSON-телом на ваш URL. Секрет whsec_… выдаётся один раз при создании.
Каталог событий:
generation.completed— генерация завершена (активно).generation.failed— генерация с ошибкой.payment.succeeded— платёж зачислен.payment.failed— платёж отклонён.balance.low— баланс ниже порога.api_key.limit_reached— упёрлись в лимит ключа.referral.reward_accrued— начислено реферальное вознаграждение.
Сейчас доставляется generation.completed; остальные события из каталога подключаются по мере готовности.
Подпись и повторы:
- Заголовок
X-AiMost-Webhook-Signature=HMAC_SHA256(secret, raw_body)в hex. Дополнительно —X-AiMost-Eventс именем события. - Таймаут доставки — 5 секунд.
- После 10 неуспешных доставок подряд webhook автоматически отключается (успешная доставка сбрасывает счётчик).
import crypto from 'crypto';
function verify(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody) // именно СЫРОЕ тело, до JSON.parse
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader),
);
}18. Интеграции
Любой инструмент с «OpenAI-compatible» провайдером подключается за две настройки: base URL = https://api.vozmiapi.ru/v1 и ключ = sk-am-….
Cursor
Settings → Models → OpenAI API Key. Включите «Override OpenAI Base URL», укажите https://api.vozmiapi.ru/v1, вставьте ключ sk-am-…, добавьте нужную модель (например openai/gpt-4o) в список Custom Models.
Cline (VS Code)
API Provider → «OpenAI Compatible». Base URL https://api.vozmiapi.ru/v1, API Key sk-am-…, Model ID anthropic/claude-3-5-sonnet (или любую из каталога).
aider
aider \
--openai-api-base https://api.vozmiapi.ru/v1 \
--openai-api-key sk-am-... \
--model openai/gpt-4oЛибо через env: OPENAI_API_BASE=https://api.vozmiapi.ru/v1 и OPENAI_API_KEY=sk-am-….
OpenCode
{
"provider": {
"vozmiapi": {
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "https://api.vozmiapi.ru/v1",
"apiKey": "sk-am-..."
},
"models": {
"openai/gpt-4o": {},
"anthropic/claude-3-5-sonnet": {}
}
}
}
}OAuth-подключение (Cline / Cursor «Sign in»)
Вместо ручного копирования ключа инструмент может открыть device-style flow: браузер ведёт на https://api.vozmiapi.ru/oauth/consent?callback_url=…&state=…. Пользователь логинится, жмёт «Разрешить» — мы создаём ключ и одноразовый code (TTL 5 мин), редиректим обратно на callback_url?code=…&state=…. Инструмент обменивает code на ключ: POST /api/v1/oauth/token ({ code, callback_url }) или, с PKCE, POST /api/v1/auth/keys ({ code, code_verifier }).
Справочник: прочие эндпоинты
GET /api/v1/models
Публичный (без auth). Все активные модели с тарифами (копейки за 1M токенов input/output), context length, флаги tools/vision.
GET /health
Liveness — всегда 200, { ok: true, status: "live" }.
GET /ready
Readiness: Postgres / Redis / LiteLLM. 200 если БД+Redis ok, 503 иначе.
GET /metrics
Prometheus exposition format: aimost_requests_total, aimost_tokens_total, aimost_blend_downgrades_total, aimost_cache_* и др.
Админские эндпоинты (JWT + role=admin) под /api/v1/admin/*: upstream-accounts, self-hosted-nodes, model-routing, users, cache/stats, sync-pricing, audit.