Ошибка 403 model_not_allowed_for_key

Ключ рабочий, баланс есть, а модель отвечает 403. Разбираем, как список разрешённых моделей привязывается к конкретному ключу и как это поправить.

4 мин · · Обновлено · ошибки

Ключ проходит аутентификацию, баланс не пустой, а запрос всё равно падает с 403. Причина почти всегда не в самом ключе, а в его настройках — конкретно, в списке моделей, которые ему разрешено вызывать.

Что означает эта ошибка

bash
{"error": {"message": "Model 'claude-opus-5-5' is not allowed for this API key", "code": "model_not_allowed_for_key"}}

У каждого API-ключа в кабинете можно задать не только дневной или месячный лимит расхода в долларах, но и список моделей, которые этому конкретному ключу разрешено вызывать. Если модель из запроса не входит в этот список, шлюз отклоняет запрос ещё до обращения к провайдеру — так же, как при пустом балансе: неудачная попытка ничего не стоит.

Это отдельный механизм от 429 (key_daily_limit_reached / key_monthly_limit_reached) — там причина в исчерпанном бюджете, здесь причина в самой модели, независимо от того, сколько осталось от лимита ключа.

Зачем вообще ограничивать модели на ключе

Обычно так делают, когда один аккаунт выдаёт разные ключи под разные цели: например, ключ для тестового окружения или для стороннего подрядчика ограничивают дешёвыми моделями вроде glm-5.3-flash или gpt-5.6-luna, а доступ к более дорогому claude-opus-5-5 оставляют только на основном ключе. Если такой ограниченный ключ случайно попадёт в код, который начнёт слать запросы к более дорогой модели, шлюз просто откажет — вместо того, чтобы тихо списывать деньги с чужого лимита.

Как проверить список разрешённых моделей

Настройка находится в кабинете, на странице конкретного ключа: https://zukko.pro/app/api-keys — открываете нужный ключ и смотрите блок с разрешёнными моделями и лимитами расхода. Если список пуст или не задан явно, обычно разрешены все модели каталога; если задан — работают только перечисленные.

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

bash
curl https://api.zukko.pro/v1/models

Этот список — это все модели, доступные в принципе на шлюзе, а не то, что разрешено именно вашему ключу. Разница между «есть в каталоге» и «разрешено на этом ключе» и есть источник 403.

Что делать, если 403 вылезает неожиданно

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

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

Смените модель в запросе, если ограничение осознанное. Если ключ специально ограничен, например, только gpt-5.6-sol и glm-5.3, и это правильно с точки зрения бюджета — проще перейти на разрешённую модель, чем менять политику ключа.

bash
ALLOWED_FALLBACK = {
    "claude-opus-5-5": "claude-sonnet-5",
    "gpt-5.6-sol": "gpt-5.6-luna",
}

def call_with_fallback(model, messages, api_key):
    try:
        return call_api(model, messages, api_key)
    except ModelNotAllowedError:
        fallback = ALLOWED_FALLBACK.get(model)
        if fallback:
            return call_api(fallback, messages, api_key)
        raise

Отличие от похожих ошибок

Стоит не путать 403 model_not_allowed_for_key с соседними кодами:

  • 404 model_not_found — модели с таким именем нет в каталоге вообще, опечатка в id.
  • 400 model_retired — модель была в каталоге, но снята с обслуживания; в ответе указана замена.
  • 503 model_disabled — модель выключена в каталоге для всех, а не для конкретного ключа; замены в ответе нет.
  • 403 model_not_allowed_for_key — модель существует и работает, но именно этому ключу её вызывать запрещено политикой.

Если сомневаетесь, какая именно причина, текст ошибки и код (code в JSON) однозначно указывают, какой из этих случаев произошёл — их не нужно угадывать по внешним признакам.

Как быстро проверить это перед деплоем

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

bash
for model in claude-sonnet-5 claude-opus-5-5 gpt-5.6-sol; do
  echo "Проверяю $model..."
  curl -s -o /dev/null -w "%{http_code}\n" https://api.zukko.pro/v1/messages \
    -H "Authorization: Bearer fetch_ваш_ключ" \
    -H "Content-Type: application/json" \
    -H "anthropic-version: 2023-06-01" \
    -d "{\"model\":\"$model\",\"max_tokens\":8,\"messages\":[{\"role\":\"user\",\"content\":\"ping\"}]}"
done

Код 200 означает, что модель разрешена и ключ рабочий; 403 с model_not_allowed_for_key — сигнал поправить список моделей на странице ключа до того, как это увидят пользователи в проде, а не после первого репорта об ошибке.

Ограничения ключа не наследуются и не суммируются

Если сервис распределяет нагрузку между несколькими ключами, лимиты и разрешения каждого считаются независимо: дневной лимит одного ключа не влияет на лимит другого, и разрешённые модели одного ключа не открывают доступ через другой. Список разрешённых моделей приходится синхронизировать вручную на каждом ключе отдельно, через кабинет https://zukko.pro/app/api-keys — общей групповой настройки на несколько ключей сразу нет.

Итого

403 model_not_allowed_for_key — это не сбой и не проблема баланса, а результат настройки конкретного ключа в кабинете: у него задан список разрешённых моделей, и запрошенной модели в нём нет. Правится на странице ключа в https://zukko.pro/app/api-keys — либо добавлением модели в список, либо переключением кода на уже разрешённую модель.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.