LLM API и интеграция

Лимит расходов на API-ключ: как не получить огромный счёт

Лимит расходов на API-ключ: как не получить огромный счёт

От огромного счёта за API защищают три настройки ключа: отдельный ключ на каждый сценарий, дневной и месячный лимит расходов в рублях и список разрешённых моделей. Величину лимита берут из фактического расхода за неделю — дневной равен самому дорогому дню, умноженному на два, — а ответ 429 key_limit_exceeded код обрабатывает как штатную остановку, а не как сбой. Заодно лимит работает датчиком: ключ, упёршийся в потолок раньше обычного, сообщает о проблеме раньше, чем её увидит бухгалтерия.

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

Откуда берётся счёт, которого никто не ждал

Три сценария, и во всех трёх расход идёт без участия человека.

  • Зациклившийся агент. Инструмент возвращает ошибку, модель пробует снова, и так по кругу. С каждым кругом растёт история диалога, поэтому каждый следующий запрос дороже предыдущего: он тащит за собой всю переписку. Ночь такого цикла — тысячи запросов с растущим входом.
  • Утёкший ключ. Ключ попал в репозиторий, в лог или в переписку, и им пользуется кто-то другой. Чужая нагрузка не экономит: берёт дорогие модели и работает круглосуточно.
  • Ошибка в цикле. Повтор при ошибке без паузы и без предела попыток, пакетная задача, запущенная дважды, список, который из-за бага читается заново. Самый скучный сценарий и самый частый.

Общее у всех трёх: человек узнаёт о проблеме по счёту или по остановке сервиса, то есть через часы или дни. Защита должна срабатывать раньше и без него. Как агенты разгоняют расход и из каких множителей складывается их месяц, разобрано в статье сколько стоит ИИ-агент в месяц.

Предоплаченный баланс от этого не спасает. Он ограничивает ущерб суммой на счёте, а когда она заканчивается, останавливаются все сценарии разом: вместе с зациклившимся агентом замолкает бот поддержки, который ни в чём не виноват. Лимит на уровне ключа останавливает один сценарий и на заранее выбранной сумме, остальные ключи продолжают работать.

Зачем отдельный ключ на каждый сценарий

Лимит имеет смысл только у ключа с одной задачей. Если бот поддержки, агент разработчика и тестовый стенд живут на общем ключе, нет правильной величины лимита: любая цифра либо душит рабочий трафик, либо ничего не защищает.

Разумное деление выглядит так:

  • по ключу на каждый рабочий сценарий: бот поддержки, разбор заявок, ночная обработка документов;
  • отдельный ключ на каждого агента, включая агента в редакторе кода;
  • ключ разработки и ключ тестового стенда;
  • по ключу на каждого подрядчика, с отзывом по окончании работ.

Побочная польза — учёт. В журнале видно, какой сценарий сколько стоит, без разбора логов. Где хранить ключи, как их ротировать и что делать при утечке, подробно разобрано в статье как хранить API-ключи; здесь речь только про их границы.

Какие ограничения можно поставить на ключ

В KeyDealer у каждого ключа настраиваются четыре границы: дневной лимит расходов в рублях, месячный лимит расходов в рублях, месячный лимит в токенах и список разрешённых моделей. При исчерпании лимита API отвечает 429 key_limit_exceeded, а журнал показывает по каждому запросу ключ, модель, токены входа и выхода и стоимость; тексты запросов не хранятся.

Рублёвые лимиты — основная защита, потому что они считают деньги напрямую, независимо от ставки модели. Лимит в токенах полезен там, где нужно ограничить объём работы, например у тестового стенда или у подрядчика. Список моделей закрывает отдельный риск, о нём ниже.

Как выбрать величину лимита

Лимит берут из фактического расхода, а не наугад. Угаданный низко лимит останавливает рабочий трафик, и через неделю его снимают совсем. Угаданный высоко не защищает ни от чего.

Порядок такой:

  1. Первую неделю сценарий работает с месячным лимитом, заведомо выше ожиданий, но конечным.
  2. По журналу считается расход по дням: сколько ушло в каждый день и какой день был самым дорогим.
  3. Дневной лимит — самый дорогой день недели, умноженный на два.
  4. Месячный лимит — недельный расход, умноженный на 4,3, плюс треть запаса на рост нагрузки.

Пример расчёта для четырёх ключей одной компании:

КлючРасход за неделюСамый дорогой деньДневной лимитМесячный лимит
Бот поддержки1 400 ₽250 ₽500 ₽8 000 ₽
Ночная обработка документов700 ₽180 ₽400 ₽4 000 ₽
Агент разработчика2 100 ₽650 ₽1 300 ₽12 000 ₽
Тестовый стенд150 ₽60 ₽150 ₽900 ₽

Суммы расхода в таблице условные, лимиты округлены вверх, коэффициенты рабочие. Пересматривать лимит стоит раз в месяц и при каждом изменении сценария: новая модель, новый канал, рост числа пользователей. Как переводить токены в рубли для любой позиции, показано в материале про стоимость миллиона токенов.

Зачем нужен дневной лимит, если есть месячный

Они ловят разные беды, и ставить нужно оба.

Дневной лимит ловит всплеск. Зациклившийся агент или повтор без паузы выбирают месячный лимит за одну ночь, и дальше сценарий стоит до конца месяца или до ручного вмешательства. С дневным лимитом ущерб ограничен сутками, а на следующий день ключ снова работает.

Месячный лимит ловит ползучий рост. Утёкший ключ, которым пользуются умеренно, не упрётся в дневной потолок ни разу. За месяц он при этом наберёт сумму, которую вы не планировали. Месячный лимит превращает такую утечку в остановку, а не в счёт.

Лимит не заменяет ограничителей внутри самого агента — потолка числа шагов и расхода на одну сессию. Это разные уровни: ограничитель агента срабатывает на одной задаче, лимит ключа — на всём сценарии. Как ставить первые, разобрано в статье как сделать ИИ-агента.

Зачем ограничивать список моделей

Ключ под классификацию обращений не должен уметь вызывать флагман. Ставки в каталоге различаются в десятки раз, и одна строка в конфигурации превращает копеечный сценарий в дорогой.

Ставки на 25 сентября 2026 года, в базовом каталоге одинаковые на вход и на выход:

Позиция₽ за 1 млн токеновКаким ключам разрешать
deepseek-v4-flash1классификация, разбор заявок
qwen-3-7-plus3короткие ответы
gemini-3-flash6бот поддержки
sonnet-530тексты, агент разработчика
opus-530сложные задачи, отдельный ключ
gpt-6-astra60многошаговые задачи, отдельный ключ

Список разрешённых моделей закрывает два сценария. Первый — ошибка своих: разработчик поменял модель в конфигурации «проверить, будет ли лучше» и забыл вернуть. Второй — чужие руки: утёкший ключ с доступом к одной дешёвой позиции стоит злоумышленнику мало, и ущерб от него растёт медленно.

Список заодно фиксирует решение о модели: смена модели в сценарии превращается из правки конфигурации в осознанное изменение настроек ключа.

Что происходит, когда лимит исчерпан

API отвечает статусом 429 с кодом key_limit_exceeded в теле ошибки. Сервис при этом исправен: сработала граница, которую вы поставили сами.

Главное — не путать его с rate_limit_exceeded. Статус у них одинаковый, смысл противоположный. Отказ по частоте лечится паузой и повтором, как описано в статье лимиты запросов и что делать. Отказ по лимиту ключа от повторов не проходит: бюджет не восстановится через секунду, а повторы только засорят журнал.

В документации есть важная деталь: key_limit_exceeded приходит, когда остатка лимита не хватает на активные запросы и на максимальный вывод нового запроса. Значит, отказ возможен до того, как лимит списан целиком. Разумный max_tokens у запроса помогает использовать остаток до конца, а максимальный без нужды делает отказ более ранним.

Как обработать key_limit_exceeded в коде

Код разбирает поле code в теле ошибки и на этом коде останавливает задачу, а не повторяет её.

import os
from openai import OpenAI, RateLimitError

client = OpenAI(base_url="https://api.keydealer.ru/v1",
                api_key=os.environ["KD_KEY_SUPPORT"])

def answer(messages):
    try:
        return client.chat.completions.create(
            model="gemini-3-flash", messages=messages, max_tokens=800)
    except RateLimitError as e:
        if e.code == "key_limit_exceeded":
            notify_team("Ключ поддержки упёрся в лимит")  # ваш канал оповещений
            raise BudgetStopped()                        # штатная остановка, без повторов
        raise  # rate_limit_exceeded: пауза и повтор выше по стеку

Что должно произойти после остановки:

  • Состояние задачи сохраняется. Пакетная обработка запоминает, на каком документе остановилась, и продолжит с него, а не с начала.
  • Пользователь видит понятный текст. Бот поддержки отвечает, что сейчас подключит человека, а не показывает техническую ошибку.
  • Команда получает оповещение. Сигнал об исчерпании лимита приходит в ваш код в виде ответа 429, поэтому оповещение строится на вашей стороне: первый key_limit_exceeded за день пишет в рабочий канал.

Остальные коды ошибок и реакция на каждый собраны в таблице в статье ошибки API нейросетей.

Что значит, если ключ упёрся раньше обычного

Лимит, выбранный от фактического расхода, в нормальный день не срабатывает. Значит, срабатывание — это сигнал разобраться, а не повод поднять потолок.

Журнал показывает по каждому запросу модель, токены входа и выхода и стоимость, и по этим полям видны типовые причины:

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

Порядок действий при подозрении на утечку — сначала отозвать ключ, потом разбираться — разобран в материале крадут API-ключи: что нашла разведка Google. Поднимать лимит, не поняв причину, — значит платить за ту же ошибку дважды.

Как настроить всё за пятнадцать минут

  1. Выпишите сценарии, которые сейчас ходят в API, и заведите по ключу на каждый.
  2. Каждому ключу оставьте в списке разрешённых только те модели, которые он реально вызывает.
  3. Поставьте временный месячный лимит в рублях, заведомо выше ожиданий, и неделю соберите расход.
  4. По журналу посчитайте дневной и месячный лимит по формулам выше.
  5. Добавьте в код разбор key_limit_exceeded и оповещение команды.
  6. Отзовите старый общий ключ.

Чего мы не утверждаем

Лимит не защищает ключ от кражи. Он ограничивает ущерб и ускоряет обнаружение. Хранение, ротация и отзыв — отдельная работа.

Коэффициенты в формулах — рабочие, а не универсальные. У сценария с сильной недельной сезонностью запас нужен больше, у ровного фонового процесса — меньше.

Мы не видим тексты ваших запросов. Журнал показывает модель, токены и стоимость, поэтому смысловой разбор инцидента — какой шаг агента зациклился — делается по вашим собственным логам.

Что нужно, чтобы попробовать

Ключ заводится на keydealer.ru/login, оплата российской картой в рублях, без зарубежной карты. Один ключ открывает каталог: на 25 сентября 2026 года это 56 позиций, из них 44 доступны, 46 текстовых с рублёвой ставкой и 10 генерируют изображения.

Лимиты и список моделей задаются у каждого ключа отдельно, поэтому разложить нагрузку можно сразу: дешёвый ключ под классификацию, отдельный под агента, отдельный под тесты. Две позиции сейчас в режиме проверки — gemini-3-6-flash и fable-5, и включать их в список разрешённых для рабочего сценария пока рано.

Что держать в голове

Неожиданный счёт почти никогда не бывает атакой из ниоткуда. Чаще это собственный агент, собственный цикл повторов или ключ, забытый в репозитории. Во всех трёх случаях расход идёт без человека, поэтому и защита должна работать без него.

Защита складывается из слоёв. Отдельный ключ даёт сценарию собственную границу, дневной лимит режет всплеск, месячный — ползучий рост, список моделей не даёт дешёвому сценарию стать дорогим. Код отличает key_limit_exceeded от отказа по частоте и останавливается, а не повторяет.

И главное: лимит — это ещё и датчик. Если ключ упёрся раньше обычного, сначала журнал и причина, потом решение о потолке. Как мы проверяем факты и что храним из запросов — на странице о проекте. Завести ключи с лимитами под свои сценарии: keydealer.ru/login.

Частые вопросы

Зачем ставить лимит расходов на API-ключ?

Чтобы ошибка стоила одного дня работы сценария, а не всего баланса. Зациклившийся агент, утёкший ключ или повтор без паузы тратят деньги быстрее, чем это замечает человек. Лимит останавливает расход сам, без вашего участия и в любое время суток.

Какой лимит поставить, если непонятно, сколько нужно?

Неделю поработать с высоким, но конечным лимитом и посмотреть фактический расход по дням в журнале. Дневной лимит — самый дорогой день недели, умноженный на два. Месячный — недельный расход, умноженный на четыре с третью, плюс запас на рост.

Что делать при ошибке 429 key_limit_exceeded?

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

Чем key_limit_exceeded отличается от rate_limit_exceeded?

Первый означает, что закончился бюджет ключа, который задали вы. Второй — что запросы идут чаще допустимого, и его лечат паузой и повтором. Оба приходят со статусом HTTP 429, поэтому код должен разбирать поле code в теле ошибки, а не только статус.

Зачем ограничивать список моделей на ключе?

Чтобы ключ под простую задачу не мог уйти на дорогую позицию из-за ошибки в конфигурации или в чужих руках. Ставки дешёвых и флагманских позиций различаются в десятки раз, и список разрешённых моделей закрывает этот разрыв одной настройкой.

Нужен ли дневной лимит, если уже стоит месячный?

Да. Месячный лимит зациклившийся агент может выбрать за одну ночь, и сценарий простоит до конца месяца или до ручного вмешательства. Дневной ограничивает ущерб сутками и оставляет бюджет на остальные дни.

Источники