Первые шаги
Evrona совместима с OpenAI API: если у вас уже есть код на официальном SDK — поменяйте адрес и ключ, и он заработает.
- 01
- 02
Внесите деньги на баланс и выпустите API-ключ в кабинете.
- 03
Вставьте ключ в сниппет ниже и отправьте запрос.
curl https://evrona.ru/v1/chat/completions \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.4-mini",
"messages": [
{
"role": "user",
"content": "Здравствуйте!"
}
]
}'Выберите модель: её ID вместе с нужным эндпоинтом подставятся в код сами. Подсветка показывает единственное место, куда попадает ваш ключ — выпустите его в кабинете, на странице ключей, и поставьте вместо заглушки.
| Base URL / Endpoint | https://evrona.ru/v1 |
|---|---|
| Ключ API | ev-ВАШ_КЛЮЧ |
| Model ID | openai/gpt-5.4-mini |
base_url — адрес выше, к которому добавлен суффикс /v1. Какая модель отвечает, решает параметр model.
Model ID копируют из каталога целиком, не обрезая префикс до «/»: скажем, google/gemini-3.7-flash или anthropic/claude-sonnet-4.6.
Как подключить программу
Чтобы завести любую программу с OpenAI-совместимым API, хватит трёх значений (Claude Code и Anthropic SDK сюда не входят: у них собственный протокол, смотрите карточку ниже):
| Base URL / Endpoint | https://evrona.ru/v1 |
|---|---|
| Ключ API | ev-ВАШ_КЛЮЧ |
| Model ID | openai/gpt-5.4-mini |
Когда поле называется просто «Base URL», программа сама добавит путь /chat/completions — дописывать его руками не надо. И проверьте, что в адресе не вышло /v1/v1.
Проверить ключ без всякой программы просто: отправьте запрос из блока «Первые шаги» выше.
Шлюз отклоняет ошибкой unsupported_parameter строгий JSON-режим (response_format), снятый с производства формат functions и параметры аудио-вывода (audio, modalities). Картинки на вход доступны моделям с пометкой «Понимает изображения»: кадр едет частью content типа image_url со ссылкой data:image/png;base64,… Внешние ссылки шлюз не скачивает; модель без этой способности отвечает unsupported_capability, а звука на входе нет вовсе. Ни один такой случай не проходит молча — за ответ, полученный не по вашим правилам, вы не платите. Вызов функций работает: до 128 инструментов в запросе, а вызовы приезжают и обычным ответом, и потоком. Простая переписка и потоковая выдача доступны на всех моделях каталога.
Готовые инструкции
Claude Code
Codex CLI- Aider
Qwen Code
OpenCode
Hermes Agent
Cursor
Cline
n8n
Telegram Bot
OpenClaw
LangChain
LlamaIndex
Редакторы кода и расширения: Cursor, Cline, Roo Code, Kilo Code
В настройках провайдера укажите «OpenAI Compatible» и заполните три поля выше. Агентные режимы, в которых расширение само читает и правит файлы, работоспособны: вызов функций шлюз поддерживает. В Cursor адрес вписывают в Settings → Models, в поле «Override OpenAI Base URL», и ключ кладут туда же; ваш ключ работает в чате и агенте, а Tab и подсказки внутри кода остаются на моделях Cursor. Если список моделей не подтянулся, наберите Model ID руками.
SillyTavern
Пройдите API Connections → Chat Completion → Source: Custom (OpenAI-compatible). Base URL впишите в Custom Endpoint, а ниже — ключ и Model ID. Когда чат отвечает, а проверка статуса падает, включите Bypass API status check.
n8n
Заведите OpenAI-креденшл, в поле Base URL впишите наш адрес с /v1 и вставьте ключ. Модель в AI-узле выбирают по полному Model ID. Узел AI Agent тоже на месте: он держится на вызове функций, который шлюз поддерживает.
Janitor AI
В настройках прокси заполните Proxy URL (это Base URL с /v1), API Key и Model. Путь /chat/completions Janitor дописывает сам. Сохраните сперва конфигурацию прокси и только потом настройки персонажа.
OpenCode
В файле ~/.config/opencode/opencode.json опишите провайдера конфигом ниже, затем запустите opencode и выберите модель командой /models.
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"Evrona": {
"npm": "@ai-sdk/openai-compatible",
"name": "Evrona",
"options": {
"baseURL": "https://evrona.ru/v1",
"apiKey": "ev-ВАШ_КЛЮЧ"
},
"models": {
"openai/gpt-5.4-mini": { "name": "GPT-5.4 Mini" },
"anthropic/claude-sonnet-4.6": { "name": "Claude Sonnet 4.6" }
}
}
}
}Anthropic SDK и Claude Code
Работают через нативный эндпоинт Anthropic — POST /v1/messages, где max_tokens обязателен. Ключ шлюз берёт и из заголовка Authorization: Bearer, и из x-api-key. Адрес шлюза задавайте без /v1: путь Claude Code дописывает сам, а лишний /v1 обернётся 404. count_tokens возвращает оценку числа токенов, а не точное значение; поле cache_control шлюз принимает, но пропускает мимо — вручную размечать кэш нельзя. Зато кэш включается сам у моделей, которым на странице «Модели» проставлена ставка кэш-входа: когда начало запроса повторяет предыдущее, эти токены идут по льготной ставке, а их количество приезжает в usage.cache_read_input_tokens. Пошаговая настройка с переменными окружения лежит в разделе «Интеграции».
Текстовый чат — ответ модели
Ответ модели на переписку. Умеет stream=true (SSE). Формат запроса и ответа такой же, как у OpenAI.
Чтобы включить поток, передайте "stream": true. Чанки идут в виде data: {...}, а в конце приходит data: [DONE].
Работает: текстовый чат вместе с вызовами инструментов через tools и tool_choice, картинки на вход у моделей с такой способностью, создание и правка изображений, создание видео. В чате response_format, functions, audio и modalities как и раньше дают 400: молча проглотить параметр мы не станем.
Поля запроса чата
Речь о теле POST /v1/chat/completions. Обязательных полей всего два — model и messages; остальные можно опустить, у каждого есть разумное значение по умолчанию.
| Имя поля | Тип значения | Назначение |
|---|---|---|
modelнужно всегда | string | Берётся из каталога целиком — префикс до «/» обрезать нельзя. |
messagesнужно всегда | array | Переписка в виде списка, где у каждого сообщения есть role (system, user, assistant, tool) и content. Прошлые запросы модель не помнит, поэтому всю нужную историю кладите сюда. |
stream | boolean | При true ответ идёт потоком, по мере генерации. Куски приезжают строками data: {…}, а поток закрывает data: [DONE]. |
temperature | 0 … 2 | Насколько разнятся ответы: чем ниже, тем предсказуемее и суше; чем выше, тем свободнее и разнообразнее. |
top_p | 0 … 1 | Второй способ управлять разбросом. Крутите только что-то одно: либо temperature, либо top_p. |
max_tokens | ≥ 1 (max 32 000) | Потолок длины ответа: всё, что выше 32 000, шлюз подрезает до 32 000. От него зависит размер резерва — смотрите «Тарифы и списания». |
max_completion_tokens | ≥ 1 (max 32 000) | То же поле под более новым именем OpenAI. Когда приходят оба, побеждает max_completion_tokens. |
stop | string | string[] | Не больше четырёх строк, на которых генерация останавливается. В ответ сама строка не попадает. |
stream_options | object | С {"include_usage": true} в последнем куске потока приедет счётчик токенов. |
tools | array (≤ 128) | Описания функций, доступных модели для вызова. Сами вызовы приезжают в choices[].message.tool_calls. |
tool_choice | string | object | none — не вызывать вовсе, auto — оставить решение модели, required — вызов обязателен, объект — вызвать именно эту функцию. |
reasoning_effort | none | minimal | low | medium | high | xhigh | max | Как долго модель рассуждает перед ответом. У рассуждающих моделей низкий уровень отвечает быстрее и дешевле, высокий — подробнее; сила эффекта зависит от самой модели. Модели без рассуждения параметр принимают и отвечают как обычно, а на моделях Grok он пока не применяется. Значение вне списка даёт 400. |
user | string | Идентификатор конечного пользователя на вашей стороне. Мы передаём его как есть, и на цену он не влияет. |
functions, response_format, audio, modalities — в ответ придёт 400 с кодом unsupported_parameter. Отказ сделан нарочно: тихо пропустить поле и выставить счёт за ответ, собранный не по вашим правилам, хуже честной ошибки.
Что лежит в ответе
Формат такой же, как у OpenAI, — официальные SDK разбирают его без переделок.
| Имя поля | Тип значения | Назначение |
|---|---|---|
id | string | Идентификатор запроса — его стоит указать, когда пишете в поддержку. |
model | string | ID той модели, которая дала ответ. |
choices[].message.content | string | null | Текст ответа; null, когда модель вместо текста позвала инструмент. |
choices[].message.tool_calls | array | Вызовы функций — если модель до них дошла. |
choices[].finish_reason | string | Что остановило генерацию: stop — модель договорила до конца, length — дошла до max_tokens, tool_calls — просит инструмент. |
usage.prompt_tokens | number | Входные токены: из них складывается первая половина счёта. |
usage.prompt_tokens_details.cached_tokens | number | Сколько входных токенов отдал кэш. Они уже учтены в prompt_tokens, а у моделей со ставкой кэш-входа посчитаны по льготной цене. |
usage.completion_tokens | number | Выходные токены: это вторая половина счёта. |
usage.total_tokens | number | Входные и выходные вместе. |
Картинки в запросе
Модель, умеющая смотреть на картинки, принимает их прямо в переписке: скриншот ошибки, фото чека, макет. Отдельный эндпоинт не нужен — кадр едет частью сообщения рядом с текстом, в том же POST /v1/chat/completions. На /v1/messages и /v1/responses всё точно так же.
Как вложить картинку
В сообщении роли user поле content превращается в массив частей: текст — часть типа text, картинка — часть типа image_url, где url это строка вида data:image/png;base64,… — тип картинки плюс её байты в base64. Порядок частей не меняется: модель видит их ровно так, как вы прислали. Поле detail (auto, low, high) уходит модели как есть. Сообщение может состоять из одних картинок, вообще без текста.
{
"role": "user",
"content": [
{ "type": "text", "text": "Какой текст на этом скриншоте?" },
{
"type": "image_url",
"image_url": { "url": "data:image/png;base64,iVBORw0KGgo…", "detail": "auto" }
}
]
}Внешние ссылки шлюз не тянет: картинка по http или https вернёт 400 invalid_request с подсказкой. Переведите файл в base64 у себя — в любом языке это одна строка кода.
curl https://evrona.ru/v1/chat/completions \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5",
"messages": [{ "role": "user", "content": [
{ "type": "text", "text": "Какой текст на этом скриншоте?" },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,'"$(base64 -w0 shot.png)"'" } }
]}]
}'Что допускается
- Форматы: PNG, JPEG, WebP. Тип определяется по первым байтам файла, а не по его имени: «png», внутри которого лежит что-то другое, получит 400 ещё у нас и до модели не доедет.
- На одну картинку — не больше 5 МБ двоичных данных; в base64 тот же файл разрастается примерно на треть.
- Не больше 50 картинок на запрос, причём в счёт идут все картинки переписки, а не только последнего сообщения.
- Тело запроса с картинками — не больше 24 МБ. Этот предел важнее числа картинок: 50 штук пройдут только если они мелкие.
- Тело крупнее 2 МБ читается только под действующий ключ с положительным балансом, и на загрузку отведено 30 с — дальше придёт 408 request_timeout с заголовком Retry-After. Крупных загрузок одновременно идёт ограниченное число: следующая получит 429 с Retry-After, повторите её через указанный срок.
- Свыше 20 картинок в одном запросе часть моделей берёт только мелкими — до 2000 px по длинной стороне.
Кто из моделей смотрит картинки
Способность проверена живой пробой, а не обещанием: сегодня картинки принимают 40 моделей каталога. У них же стоит пометка «Понимает изображения» на странице «Модели», а GET /v1/workspace/rates отдаёт их в поле capabilities. Модель без этой способности отвечает 400 unsupported_capability и денег не берёт.
Во что обходится картинка
Картинка тарифицируется входными токенами модели, а сколько их — решает сама модель: обычно порядка 1 089 токенов за кадр 1024×1024, у отдельных моделей в разы больше. Списываем ровно то, что модель вернула в usage.prompt_tokens, — формула та же, что у текста. Под запрос откладывается оценка с запасом, лишнее возвращается на баланс (см. «Тарифы и списания»). Оценку того же порядка отдаёт ответ POST /v1/messages/count_tokens.
Картинки, пришедшие от агента
Картинка из результата инструмента — агент открыл файл-картинку или снял скриншот — тоже доезжает до модели. В протоколе OpenAI результат инструмента везёт только текст, поэтому шлюз досылает такие картинки отдельным пользовательским ходом сразу за серией результатов, и порядок переписки от этого не страдает. Настраивать ничего не надо.
На /v1/responses картинка — это часть input_image, а значение detail: original считается равным high. На /v1/messages это блок image с source типа base64; source типа url шлюз не тянет, как и в чате. Блоки document и file по-прежнему дают 400: файлы на входе мы пока не принимаем.
Когда приходит отказ
400 invalid_request — формат не тот, байты не сошлись с типом, превышен размер или число картинок, картинка оказалась в сообщении system, developer или assistant. 400 unsupported_capability — модель картинок не принимает. 400 context_length_exceeded — картинки вместе с текстом не помещаются в контекст модели. 408 request_timeout — тело не дочитано целиком за отведённый срок. 413 payload_too_large — тело перешло предел. Ни за один из этих отказов денег не берут.
Байты картинок нигде не сохраняются: они живут в памяти на время запроса и уходят модели. В статистике остаётся только их число — поле images_in в GET /v1/workspace/spend.
Создание изображений
POST /v1/images/generations работает синхронно, а тело и ответ совместимы с OpenAI Images. Списывается фиксированная цена одного изображения, умноженная на количество (n).
curl https://evrona.ru/v1/images/generations \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-image-2",
"prompt": "a red cat wearing glasses",
"n": 1
}'Модель должна быть типа «изображение» (см. GET /v1/models). Ответ — массив data, в каждом элементе b64_json: кадр в base64. Ссылку мы не отдаём, даже если её дала модель, — кадр приезжает байтами. У потокенной модели в ответе есть usage: ровно те числа, по которым списано. Заголовок x-request-id в ответе — идентификатор записи списания, по нему запрос находится в GET /v1/workspace/spend.
Промпт — не длиннее 15 000 символов. Поля image, images, mask, aspect_ratio, image_size, resolution генерация не принимает: ответ будет 400 unsupported_parameter. Если картинка нужна на входе, обращайтесь к POST /v1/images/edits.
Правка готовой картинки
POST /v1/images/edits переделывает готовую картинку по текстовому описанию: сменить фон, дорисовать деталь, повторить стиль. Тело идёт как multipart/form-data, по образцу OpenAI Images API: файл или несколько плюс prompt. В ответ приходит кадр в base64.
curl https://evrona.ru/v1/images/edits \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ" \
-F model=openai/gpt-image-2 \
-F prompt="Поменяй фон на светлый градиент" \
-F image=@cat.pngЧто в ответе:
{
"created": 1757700000,
"data": [{ "b64_json": "iVBORw0KGgo…" }],
"usage": { "input_tokens": 116, "output_tokens": 1650, "total_tokens": 1766 }
}Формат кадра остаётся за моделью: одна вернёт PNG, другая JPEG. Мы его не обещаем и не перекодируем — читайте data[0].b64_json как байты картинки, а тип, если он нужен, определяйте по первым байтам.
Поле usage приходит далеко не всегда: у модели с ценой за кадр его нет вовсе — платите за кадр, а не за токены. Разбивка input_tokens_details и output_tokens_details появляется лишь тогда, когда её дала модель, поэтому проверяйте наличие поля, а не полагайтесь на него.
Поля формы
| Имя поля | Тип значения | Назначение |
|---|---|---|
modelнужно всегда | string | Модель типа «изображение», которая умеет редактировать. Чат-модель вернёт 404 model_not_found, а картиночная без этой способности — 400 unsupported_capability. |
promptнужно всегда | string (≤ 15 000) | Что нужно сделать с картинкой. Не длиннее 15 000 символов. |
imageнужно всегда | file × 1 … 4 | Файл: PNG, JPEG или WebP, определённый по первым байтам, и не больше 5 МБ каждый. Одна картинка идёт в поле image, несколько — в image[] (именно так их шлёт SDK OpenAI), всего до 4 файлов в запросе. Gemini 3.1 Flash Image принимает только одну картинку: на несколько ответ будет 400 с param=image. |
n | 1 … 4 | Сколько кадров вернуть; по умолчанию один. Живая проба покрывает один кадр за запрос — на большем числе поведение моделей мы ещё не мерили. |
size | auto | 1024x1024 | 1024x1536 | 1536x1024 | Размер кадра. При auto — это и значение по умолчанию — размер выбирает модель, как правило по пропорциям вашего фото. 1024x1536 даст вертикальный кадр, 1536x1024 горизонтальный, 1024x1024 квадратный. Любое другое значение вернёт 400. У модели с ценой за кадр доступен один 1024x1024. |
response_format | b64_json | Единственное значение — b64_json, оно же по умолчанию. url вернёт 400 unsupported_parameter: хранилища у нас нет, а значит, и ссылке взяться негде. |
mask, output_format, output_compression, partial_images, stream в значении true, background: transparent, input_fidelity: high. Каждое из них меняет байты результата или его цену у модели, и проглотить их молча означало бы вернуть не то, что заказывали. Маску в этой версии не поддерживает ни одна модель: присылайте картинку целиком.
Принимаем, но модели не отдаём
quality, user, background в значении opaque или auto, input_fidelity в значении low. Запрос с этими полями пройдёт, но результат и цена выйдут такими же, как без них.
Сроки и параллельные запросы
На правку уходит от минуты до нескольких минут. Модель мы ждём до 570 секунд, а дальше отвечаем 504 upstream_timeout без списания — поэтому таймаут своего клиента задавайте не ниже 600 секунд. Параллельных запросов на правку с одного аккаунта: 2; следующий получит 429 с заголовком Retry-After. После 5 отклонённых подряд запросов (400) правка для аккаунта замирает примерно на минуту, так что длину промпта и значения полей разумнее проверить до отправки.
Тарифы и списания
Цена та же, что у генерации на этой модели: отдельного тарифа за правку нет. На потокенной модели вход и выход считаются по её ставкам, а usage в ответе показывает ровно те числа, по которым прошло списание. На модели с ценой за кадр списывают цену кадра, умноженную на число кадров. Под запрос откладывается оценка с запасом, лишнее возвращается, а сбой модели не стоит ничего.
Заголовок Content-Length обязателен: загрузка без него (chunked) вернёт 400 invalid_request. Когда клиент отдаёт файл потоком, прочитайте его в память или проставьте размер сами.
В ответе есть заголовок x-request-id — идентификатор записи списания. По нему запрос находится в GET /v1/workspace/spend (поле id) и в кабинете; SDK OpenAI кладёт его в request_id.
Кто из моделей умеет править
Сегодня редактирование включено у 2 моделей каталога. У них стоит пометка «Редактирование» на странице «Модели», а GET /v1/workspace/rates отдаёт способность image_edit в поле capabilities.
Создание видео
Видео собирается асинхронно: запрос заводит задачу и тут же возвращает её id. Параметр seconds передавать обязательно — это длительность ролика, и от неё считается цена.
curl https://evrona.ru/v1/videos/generations \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"model": "alibaba/wan-2.6",
"prompt": "a paper boat drifting on a calm pond",
"seconds": 5
}'
# {"id": "9b2f…", "status": "processing", "created": 1755648000}Опрашивайте готовность раз в 5–10 секунд. status: processing — работа идёт, succeeded — готово и в ответе лежит url ролика, failed — не получилось, причина в поле error. Чаще всего генерация укладывается в 30 секунд — 3 минуты, но изредка поставщик отвечает дольше, поэтому не бросайте опрос раньше 10 минут. Ссылка ведёт в хранилище поставщика и живёт 24 часа после готовности — успейте скачать файл за это время.
curl https://evrona.ru/v1/jobs/JOB_ID \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ"
# {"id": "9b2f…", "status": "succeeded", "url": "https://…/clip.mp4"}Цена запроса — ставка за секунду, умноженная на seconds. Деньги уходят в резерв при заведении задачи и списываются только после готовности ролика; если генерация не удалась, резерв возвращается целиком.
Модели и допустимые длительности
| ID модели | Длительность (seconds) | Размер кадра | Аудио |
|---|---|---|---|
alibaba/wan-2.6 | 2–10 | 720p | со звуком |
bytedance/seedance-2.0-fast | 4–15 | 720p | без звука |
bytedance/seedance-2.0 | 4–15 | 720p | без звука |
google/veo-3.1-fast | 4–8 | 1080p | без звука |
google/veo-3.1 | 4–8 | 1080p | без звука |
Нужна модель типа «видео» — такие перечисляет GET /v1/models. Ставки за секунду смотрите на странице моделей.
Ролик собирается только из текста. Фото в роли первого кадра мы пока не принимаем: запрос с любым из полей image, images, image_url, input_reference, first_frame, last_frame, reference_images получит 400 unsupported_parameter, и списания не будет.
Справочник эндпоинтов
Модели
Перечень доступных моделей в формате OpenAI. Отключённые в список не попадают.
Текст
Ответ модели на переписку. Умеет stream=true (SSE). Формат запроса и ответа такой же, как у OpenAI.
Нативный протокол Anthropic: Claude Code и Anthropic SDK работают без переделок. Авторизация как у нативных клиентов — заголовок x-api-key, хотя Bearer тоже принимается. Стриминг (SSE) и вызовы инструментов на месте; max_tokens передавать обязательно.
Прикидывает число входных токенов, не обращаясь к модели: это оценка, а не точный счёт, и баланс она не тратит.
Формат OpenAI Responses API: Codex CLI и SDK OpenAI работают без переделок. Состояния мы не держим — историю присылает клиент, previous_response_id не поддержан, ответы по id не сохраняются, поэтому GET и DELETE отвечают 404. Инструменты function и стрим (SSE) на месте.
Медиа
Изображения синхронно, по правилам OpenAI Images. Кадр приезжает в base64.
Правит готовую картинку по описанию: на входе multipart/form-data, на выходе кадр в base64.
Заводит задачу на генерацию видео. Тариф считается по секундам, поле seconds передавать обязательно; в ответе — задача со status processing.
Состояние задачи генерации. processing — работа идёт, succeeded — готово, url ролика лежит в ответе, failed — не получилось, и деньги не списаны.
Аккаунт
Read-only API аккаунта: баланс, розничные цены, детализация и аналитика по ключу. Разобрано в разделе «Account API».
Тарифы и списания
Как устроен расчёт
- Деньги вносятся на баланс заранее: ни счетов в конце месяца, ни подписок у нас нет.
- Каждый запрос стоит ровно своё: цена складывается из модели и количества токенов.
- Баланс убывает сразу же после ответа. Если денег не хватило, запрос вернёт 402: в минус аккаунт не уходит.
Откуда берётся сумма
У каждой модели собственная цена за 1 миллион токенов, и она разная для входа (вашего запроса) и выхода (ответа модели). Выход почти всегда стоит дороже входа. Актуальные цены всех моделей собраны в каталоге «Модели и цены».
ввод = входные_токены / 1 000 000 × цена_за_вход
вывод = выходные_токены / 1 000 000 × цена_за_выход
──────────────────────────────────────────────────────
сумма = ввод + выводОбе половины округляются вверх до миллионной доли доллара. Число токенов приходит из ответа модели — это то самое поле usage, которое видно у вас в коде.
Пример подсчёта
модель — openai/gpt-5.4-mini · вход по $0.1188 на 1M токенов · выход по $0.6336 на 1M токенов
Цены в примере не придуманы: они приходят из живого каталога — того же, что питает счёт.
Льготная ставка за кэш
Если запрос начинается тем же текстом, что и предыдущий — системный промпт, инструкции, длинный контекст, — модель достаёт это начало из кэша, а мы считаем такие токены по льготной ставке. Включать ничего не надо: кэш срабатывает сам, стоит одинаковому префиксу прийти подряд и быть достаточно длинным — примерно от тысячи токенов. Первый запрос, который кладёт текст в кэш, не дорожает ни на копейку: он стоит столько же, сколько стоил бы без кэша.
ввод = (входные_токены − токены_из_кэша) / 1 000 000 × цена_за_вход
+ токены_из_кэша / 1 000 000 × ставка_кэш-входаСколько токенов пришло из кэша, видно в ответе: usage.prompt_tokens_details.cached_tokens, на эндпоинте /v1/messages — usage.cache_read_input_tokens. Те же числа лежат в кабинете, в GET /v1/workspace/spend и в выгрузке CSV. Ставка кэш-входа указана на странице «Модели» и в GET /v1/workspace/rates. Скидка есть не у всех моделей: там, где ставка не указана, кэш считается по обычной цене входа.
Резерв, пока запрос идёт
Пока модель печатает, длина ответа неизвестна никому. Поэтому ещё до обращения к модели на балансе временно откладывается худший случай:
резерв = входные_токены / 1 000 000 × цена_за_вход
+ max_tokens / 1 000 000 × цена_за_выходНе хватает на резерв — запрос отклоняется сразу, не доходя до модели. А как ответ получен, списывается фактическая стоимость, и остаток резерва тем же мгновением возвращается на баланс.
max_tokens: 4 000Держите max_tokens рядом с ожидаемой длиной ответа: чем он выше, тем крупнее резерв и тем меньше баланса остаётся под параллельные запросы. Когда max_tokens не задан, резерв считают по потолку в 32 000 токенов.
В каких случаях списания нет
Ошибка на стороне модели (502, 504) ничего не стоит, и резерв возвращается целиком. Отклонённый запрос — неверный ключ, нехватка баланса, неподдерживаемое поле, слишком крупное тело — тоже бесплатен, ведь до модели он не доехал. А оценка токенов через /v1/messages/count_tokens бесплатна всегда.
Где видно расходы
В кабинете. Страница ключа держит журнал запросов — модель, токены и стоимость каждого, — а рядом выгрузку в CSV и график по дням. В разделе расходов лежит сводка за период с разбивкой по моделям. Тексты запросов и ответов мы не сохраняем, поэтому в статистике одни эти счётчики.
Account API — баланс, тарифы и расход по ключу
Read-only API аккаунта: берите баланс, розничные цены и usage ключа прямо из своего бэкенда, не заходя в кабинет. Базовый URL и готовые сниппеты собраны в разделе кабинета «Управление аккаунтом».
Авторизуйтесь тем же ключом, которым обращаетесь к моделям: заголовок Authorization: Bearer. Метод только GET; ключ должен быть активен — на паузе и после отзыва приходит 401. Ключ не стоит ставить в URL и тем более использовать в браузерном коде. Статистика считается по тому ключу, которым сделан запрос, а баланс и цены — общие для всего аккаунта.
Сколько сейчас на балансе аккаунта, в долларах; активные резервы из суммы уже вычтены.
Розничные тарифы моделей из GET /v1/models: за 1M токенов (вход, кэш-вход, выход) либо за единицу генерации — у видео это секунда. Способности модели перечислены машиночитаемо в поле capabilities: vision — модель принимает картинки на вход, image_edit — умеет править изображения. Себестоимость и маржу мы не отдаём.
Запросы ключа построчно: модель, операция, статус, токены и отдельно — сколько из них отдал кэш, число картинок во входе (images_in), списание, задержка и снимки цен на момент запроса. Сортировка — свежие первыми.
Сводка по ключу за период: totals, разбивка по моделям и по дням (UTC), ошибки шлюза в разрезе кодов.
Query-параметры
Ни один параметр не обязателен. Значение вне допустимых границ даёт 400 invalid_request, а имя параметра приходит в param.
| Имя поля | Тип значения | Значение по умолчанию | Назначение |
|---|---|---|---|
daysspend · insights | 1 … 90 | 30 | Сколько дней назад от текущего момента отсчитывать окно выборки. |
limitspend | 1 … 100 | 50 | Сколько записей детализации приходит на одной странице. |
pagespend | 0 … 200 | 0 | Номер страницы; нумерация с нуля. Есть ли следующая, подскажет has_more в ответе. |
Примеры запросов
curl https://evrona.ru/v1/workspace/balance \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ"
# {"object": "workspace.balance", "balance_usd": 4.981234, "currency": "USD"}curl "https://evrona.ru/v1/workspace/spend?days=7&limit=25" \
-H "Authorization: Bearer ev-ВАШ_КЛЮЧ"Что в ответе:
{
"object": "list",
"days": 7,
"limit": 25,
"page": 0,
"has_more": false,
"data": [
{
"id": "9b2f…",
"created_at": "2026-08-21T09:58:12.000Z",
"model": "openai/gpt-5.4-mini",
"operation": "chat",
"status": "success",
"tokens_in": 1200,
"cached_tokens_in": 0,
"images_in": 0,
"tokens_out": 800,
"cost_usd": 0.00065,
"price_input_usd_per_1m_tokens": 0.1188,
"price_cached_input_usd_per_1m_tokens": 0.0168,
"price_output_usd_per_1m_tokens": 0.6336,
"price_generation_usd": null,
"latency_ms": 812
}
]
}Ответ /v1/workspace/insights — один объект с полями:
totals · models[] · daily[] · errors.by_code[]
Детализация содержит одни метаданные. Тела промптов и ответов не сохраняются в принципе, а значит, отдать их нельзя ни через API, ни любым другим способом. IP и данные клиента мы тоже не раскрываем.
Возможные ошибки
Конверт ошибок один на весь шлюз — он разобран в разделе «Ошибки запросов». В этом API встречаются:
401 invalid_api_key · 400 invalid_request · 429 rate_limited
Лимиты и пределы
Лимиты стоят на страже и вашего баланса, и шлюза: случайный цикл в коде не должен сжечь деньги за минуту.
| Что ограничено | Предел |
|---|---|
| Частота обращений с одного ключа | пачка из 60, затем 10 в секунду |
| Объём тела запроса: чат и /v1/messages | 2 МБ |
| Объём тела запроса с картинками: чат, /v1/messages, /v1/responses, правка изображений | 24 МБ |
| Объём тела запроса: изображения, видео | 256 КБ |
| Длина промпта: все сообщения и схемы инструментов вместе | 400 000 знаков |
| Длина промпта для картинок: создание и правка | 15 000 знаков |
| Параллельных правок изображений на аккаунт | 2 |
| Потолок токенов в ответе (max_tokens) | 32 000 токенов |
| Инструментов на один запрос | 128 |
| Стоп-строк в запросе | 4 |
| Денежный лимит ключа: сутки, неделя, месяц | на ваше усмотрение |
| Расписание ключа: в какие часы и дни он действует | на ваше усмотрение |
За превышение частоты приходит 429 rate_limited: подождите и повторите — ключ при этом не блокируют и не штрафуют. Тело крупнее 2 МБ читается только под действующий ключ с положительным балансом: на загрузку отведено 30 с, а крупных загрузок одновременно идёт ограниченное число — лишняя получит 429 с заголовком Retry-After. Денежный лимит и расписание вы выставляете сами, в кабинете на странице ключа. Перебор неверных ключей с одного адреса мы вдобавок притормаживаем.
Считаются знаки, а не байты: кириллическая буква — один знак, эмодзи обычно два.
Терпение шлюза по отношению к модели. В чате — до 280 секунд до начала ответа и до 240 секунд тишины в середине. На запросах картинок — до 570 секунд. Не начался ответ за этот срок — приходит 504 upstream_timeout, и списания нет. Без stream ответ приезжает целиком, поэтому на долгих ответах stream лучше включать. Если ответ оборвался на середине или ваш клиент закрыл соединение раньше срока, запрос ложится в журнал со статусом «прервано»: платится обработанный запрос и та часть ответа, что успела прийти. Таймаут на своей стороне задавайте больше этих чисел.
Доступность и среднее время ответа каждой модели по часам показывает страница /uptime.
Коды ошибок шлюза
Формат у всех ошибок один и тот же, как у OpenAI, — поэтому SDK разбирают их без вашего участия:
{
"error": {
"message": "No enabled model matches that name. Request GET /v1/models to see what is available.",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model"
}
}Ветвитесь по code: он машиночитаем и остаётся прежним. Текст message написан для человека и со временем может быть переписан. Если ошибка в конкретном поле запроса, на него укажет param.
| Статус HTTP | code | Из-за чего приходит | Как исправить |
|---|---|---|---|
| 400 | invalid_request | Тело запроса не удалось разобрать: испорченный JSON, пропущено обязательное поле или значение вышло за допустимые границы. | Сверьтесь с разделом «Поля чат-запроса»: что именно не подошло, названо в param. |
| 400 | unsupported_parameter | В запросе есть поле, которого шлюз пока не умеет. | Выньте это поле из запроса; несовместимые перечислены в разделе «Поля чат-запроса». |
| 400 | unsupported_capability | Запрос просит у модели то, чего она не умеет: принять картинку на вход или отредактировать изображение. | Возьмите модель с нужной пометкой на странице «Модели» или по полю capabilities в GET /v1/workspace/rates. Запрос не тарифицирован. |
| 400 | context_length_exceeded | Запрос не помещается в контекст модели: переписка, картинки и схемы инструментов считаются вместе. | Укоротите переписку, уберите часть картинок или возьмите модель с более длинным контекстом: его размер указан на странице «Модели». |
| 401 | invalid_api_key | Ключ не тот, отозван или вообще не передан. | Проверьте, что ключ скопирован целиком, вместе с префиксом ev-, и не отозван в кабинете. |
| 402 | insufficient_balance | На балансе больше нет денег; пополнить его можно в кабинете. | Пополните баланс. Помогает и меньший max_tokens: резерв окажется скромнее. |
| 403 | key_schedule_blocked | Ключ вне разрешённого расписания. Настройте расписание в кабинете (/console/keys). | Отредактируйте расписание этого ключа в кабинете либо воспользуйтесь другим ключом. |
| 404 | model_not_found | Такой модели нет или она отключена. Актуальный список даёт GET /v1/models. | Копируйте ID из GET /v1/models полностью, не обрезая префикс до «/». |
| 404 | job_not_found | Задачи генерации под таким id не нашлось. | Сверьте id с тем, что вернул ответ на заведение задачи. |
| 404 | not_found | За этим адресом ничего не стоит. Ответы /v1/responses мы не храним, поэтому получить или удалить их по id не выйдет. | Проверьте адрес. Историю диалога храните у себя и присылайте полный input в каждом запросе. |
| 408 | request_timeout | Тело запроса не дочитано до конца в отведённый срок. | Повторите запрос; когда именно — подскажет заголовок Retry-After. На медленном канале присылайте картинки помельче. |
| 413 | payload_too_large | Тело запроса не влезает в предел. | Укоротите переписку или разложите её на несколько запросов. |
| 429 | rate_limited | С этого ключа идёт слишком много запросов; подождите и повторите. Частота выравнивается сама. | Подождите и повторите. Хорошо работает пауза, которая растёт с каждой попыткой. |
| 429 | spend_limit_exceeded | Достигнут лимит расходов ключа. Поднимите или снимите его в кабинете (/console/keys). | Поднимите лимит или снимите его совсем — в кабинете, на странице ключа. |
| 500 | internal_error | Что-то сломалось у нас. | Повторите запрос. Если ошибка не уходит, напишите в поддержку и приложите id из ответа. |
| 502 | provider_not_configured | К поставщику этой модели нет рабочего маршрута. | Возьмите другую модель и напишите нам: этой ошибки быть не должно. |
| 502 | upstream_error | Сбой у провайдера модели. За такой запрос мы не списываем. | Отправьте запрос снова или возьмите другую модель. Денег за него не списано. |
| 504 | upstream_timeout | Поставщик модели не успел ответить. | Отправьте запрос снова. На длинных ответах включайте stream: поток рвётся лишь тогда, когда поставщик молчит дольше 4 минут подряд. |
Ни за одну ошибку из таблицы мы не берём денег. Запрос, не доехавший до модели, и запрос, на который модель ответила ошибкой, не списываются, а резерв возвращается на баланс целиком.
Вопросы и ответы
Как перейти на другую модель?
Поменяйте значение параметра model. Остальной код трогать не нужно: запрос сам уйдёт к нужному провайдеру.
Можно ли взять официальный OpenAI SDK?
Да. Поставьте в base_url наш адрес с /v1, подставьте наш ключ — весь остальной код остаётся как был.
Из чего складывается стоимость?
Из токенов входа и выхода по тарифу модели на момент запроса. Формула и примеры расчёта лежат в разделе «Тарифы и списания».
Ограничено ли число запросов?
Да. На каждом ключе стоит частотный лимит, а денежные лимиты расходов вы задаёте сами. Все числа собраны в разделе «Ограничения».
Напишите в поддержку на support@evrona.ru или загляните в общий FAQ.
Нашли ошибку в документации? Сообщите нам.