Зачем заводить отдельный API-ключ на каждый проект
Один ключ на все проекты — это пять минут экономии сейчас и путаница при первом же инциденте. Что именно даёт разделение ключей по проектам.
5 мин · · Обновлено · API-ключи
Проще всего выпустить один ключ fetch_... и вставить его во всё — в личный пет-проект, в рабочий сервис, в скрипт для тестов. Экономит пять минут при настройке и создаёт ровно те проблемы, которые обычно всплывают в худший момент.
Лимит одного проекта не должен быть лимитом всех
На странице ключа в /app/api-keys можно задать дневной и месячный лимит расхода в долларах и список разрешённых моделей — но это настройка конкретного ключа, а не аккаунта целиком. Если ключ один на пять проектов, лимит приходится ставить с запасом на все пять сразу, то есть по факту он не защищает ни один из них: баг в одном сервисе может съесть весь дневной лимит, и остальные четыре просто перестанут получать ответы с 429 key_daily_limit_reached, хотя сами ни в чём не виноваты.
С отдельным ключом на проект лимит считается для этого проекта:
# ключ для internal-скрипта аналитики — низкий потолок
curl https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_ключ_analytics" \
-H "Content-Type: application/json" \
-d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"..."}]}'Если этот скрипт зациклится, он упрётся в свой лимит и остановится — прод с отдельным ключом продолжит работать как ни в чём не бывало.
Список разрешённых моделей ограничивает не только бюджет, но и площадь ошибки
Ключ можно ограничить конкретными моделями. Для проекта, которому нужен только gpt-5.6-luna для генерации коротких ответов, нет смысла разрешать ему claude-opus-5-5 — случайная опечатка в конфиге или чужой код, который получил доступ к этому ключу, физически не сможет прогнать через него дорогую модель. Попытка вернёт 403 model_not_allowed_for_key.
Это работает и в обратную сторону: если один проект специально держат на дорогой модели ради качества, а другой — на дешёвой ради экономии, разделение ключей делает эту границу технической, а не договорной. Не нужно надеяться, что никто не забудет, какую модель использовать в каком месте кода — ключ сам не даст вызвать не ту.
Раздельный учёт расхода по ключам
GET /v1/usage отдаёт историю списаний с курсорной пагинацией — но общую на весь аккаунт: все ключи вместе, фильтра по ключу нет, и баланс тоже один на аккаунт. Поэтому делить расход по проектам приходится на своей стороне: логируйте X-Zukko-Cost-Micros по ключу (для нестриминговых запросов), а если нужно строгое разделение, в том числе для потоковых запросов, — заведите отдельный аккаунт:
curl https://api.zukko.pro/v1/usage \
-H "Authorization: Bearer fetch_ваш_ключ"Заголовок X-Zukko-Cost-Micros приходит в каждом обычном (не потоковом) ответе — если ключ один на все проекты, эти цифры смешаны и бесполезны для юнит-экономики отдельного продукта. Если ключей несколько и вы пишете стоимость в лог вместе с ключом, расход каждого проекта считается сам, без ручного разбора логов по признаку "какой это был вызов". X-Fetch-Balance-Cents при этом показывает баланс всего аккаунта (в микродолларах, несмотря на название), он общий для всех ключей.
Отзыв одного ключа не трогает остальные
Ключ показывается один раз при создании и может быть скомпрометирован — засветиться в логах, в публичном репозитории, в конфиге, который кто-то не должен был видеть. Если ключ один на всё, отозвать его — значит остановить все проекты разом, пока не выпустишь новый и не обновишь его везде. Если ключи разделены, реакция на утечку — это работа с одним проектом, а не аварийное отключение всего, что использует API.
Idempotency-Key и кэш работают в рамках запроса, а не ключа — но масштаб инцидента всё равно разный
Заголовок Idempotency-Key защищает от повторного списания за один и тот же запрос, а кэш по заголовку X-Zukko-Cache: true (или temperature: 0 — у моделей, которые его принимают, не у Claude) работает на уровне пользователя и запроса. Ни то, ни другое не заменяет разделение ключей — они решают задачу "не заплатить дважды за одно и то же", а не задачу "не дать одному проекту утащить бюджет другого".
Когда одного ключа действительно достаточно
Если это личный проект без внешних участников и без риска, что код с ключом попадёт куда-то ещё — разделение ключей просто лишняя настройка. Порог, после которого разделение того стоит: как только к коду получает доступ кто-то ещё (коллега, фрилансер, CI с внешними раннерами) или проект переходит из "поиграться" в "на нём что-то реально работает".
Как это выглядит на практике
Заводишь ключ в кабинете под явным назначением, сразу выставляешь лимит и список моделей, кладёшь в переменные окружения именно этого проекта:
export FETCH_API_KEY_PROJECT_A=fetch_...
export FETCH_API_KEY_PROJECT_B=fetch_...Дальше каждый проект обращается к своей переменной, и вопрос "чей это был расход" перестаёт требовать расследования.
Снятие модели с обслуживания — тоже проще пережить по отдельности
Когда модель снимают с обслуживания, ответ прямо называет замену: {"error":{"message":"Модель 'X' снята с обслуживания. Используйте 'Y'","code":"model_retired"}}. Если модель просто выключена в каталоге, ответ другой — 503 с кодом model_disabled, и замену приходится выбирать самому по GET https://api.zukko.pro/v1/models. Если ключ один на несколько проектов и все они завязаны на одну и ту же модель, миграцию приходится делать сразу и одновременно для всех — откатить только часть трафика не получится, ключ либо разрешает старое имя, либо новое.
С отдельными ключами на проект список разрешённых моделей у каждого свой, и переход на замену можно сделать поэтапно: сначала обновить allowed-models на ключе одного проекта, проверить, что всё работает с новым идентификатором, и только потом катить то же самое на остальные. Один и тот же организационный факт — модель заменили — превращается либо в аварийный релиз сразу везде, либо в спокойный поэтапный роллаут, и разница как раз в том, разделены ключи или нет.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Ключи OpenAI API в открытом доступе: почему ими нельзя пользоватьсяОткуда берутся «бесплатные» ключи на GitHub, почему пользоваться ими опасно и для вас, и для владельца, и как защитить собственный ключ от такой же утечки.
- Ошибки GLM API: почему не работает запрос и как это исправитьНеверный id модели, переполненный контекст 128K, ключ, баланс, лимиты: типичные причины ошибок GLM API и быстрый способ найти свою.
- xAI Grok API: подключение Grok 4.7, цена и контекст 256KКак вызвать grok-4.7 через OpenAI-совместимый API, что делать с лимитом контекста 256K и сколько стоят типичные запросы. Плюс сравнение с Grok 4.6.
- This organization has been disabled в Claude API: что это и как продолжитьКлюч Anthropic внезапно отвечает «organization has been disabled». Объясняем, что это за ошибка, что проверить и как перенести SDK и Claude Code на другой провайдер.