Как узнать список доступных моделей через API и не сломаться при их смене

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

3 мин · · модели · API-ключи

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

Список моделей: GET /v1/models

Эндпоинт публичный — ключ для него не нужен:

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

Ответ в OpenAI-совместимом формате — объект со списком в поле data:

bash
{
  "object": "list",
  "data": [
    {"id": "claude-sonnet-5", "object": "model", "created": 1700000000, "owned_by": "zukko"},
    {"id": "gpt-5.6-sol", "object": "model", "created": 1700000000, "owned_by": "zukko"},
    {"id": "gpt-5.6-luna", "object": "model", "created": 1700000000, "owned_by": "zukko"},
    {"id": "glm-5.3", "object": "model", "created": 1700000000, "owned_by": "zukko"},
    {"id": "glm-5.3-flash", "object": "model", "created": 1700000000, "owned_by": "zukko"},
    {"id": "claude-opus-5-5", "object": "model", "created": 1700000000, "owned_by": "zukko"}
  ]
}

Это пример на момент написания: состав и порядок могут измениться. Для запросов нужно только поле id — его и передавайте в параметр model. Тот же список есть на странице «Модели» в кабинете, а описание эндпоинта — в документации.

Обратите внимание: список общий для всех. Если на вашем ключе настроен список разрешённых моделей (allowed_models), запрос к модели вне этого списка вернёт 403 model_not_allowed_for_key, даже если модель есть в /v1/models.

Python: получить список

Через requests:

bash
import requests

def get_available_models(timeout: float = 5.0) -> list[str]:
    r = requests.get("https://api.zukko.pro/v1/models", timeout=timeout)
    r.raise_for_status()
    return [m["id"] for m in r.json()["data"]]

print(get_available_models())

Через OpenAI SDK, если он уже есть в проекте:

bash
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_ваш_ключ")
models = [m.id for m in client.models.list()]
print(models)

Что происходит при обращении к отключённой модели

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

  • 503 + model_disabled — модель отключена, повторять запрос бессмысленно, нужно выбрать другую;
  • 503 без model_disabled — временный сбой провайдера, имеет смысл повторить с паузой.
bash
import openai

def is_model_disabled(err: openai.APIStatusError) -> bool:
    return err.status_code == 503 and "model_disabled" in err.response.text

err.response — объект ответа httpx, поэтому проверка работает и с OpenAI SDK, и с Anthropic SDK (у anthropic.APIStatusError есть те же поля status_code и response).

Устойчивый вызов: цепочка запасных моделей

Задайте предпочитаемую модель и запасные. При model_disabled код переходит к следующей, при временном 503 — делает паузу и повторяет.

bash
import time
import openai
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_ваш_ключ")

MODEL_CHAIN = ["claude-opus-5-5", "claude-sonnet-5", "gpt-5.6-sol"]

def chat(messages: list, chain: list[str] = MODEL_CHAIN, retries: int = 2):
    for model in chain:
        for attempt in range(retries + 1):
            try:
                return client.chat.completions.create(model=model, messages=messages)
            except openai.APIStatusError as e:

Если при старте приложения хочется сразу отсеять отключённые модели, отфильтруйте цепочку по списку из /v1/models:

bash
def usable_chain(chain: list[str]) -> list[str]:
    try:
        available = set(get_available_models())
    except requests.RequestException:
        return chain
    return [m for m in chain if m in available] or chain

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

Модель — в конфиг, а не в код

Вынесите название модели в переменную окружения — тогда замена модели не требует релиза:

FETCH_KEY=fetch_... LLM_MODEL=claude-sonnet-5
bash
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://api.zukko.pro",
    api_key=os.environ["FETCH_KEY"],
)
MODEL = os.getenv("LLM_MODEL", "claude-sonnet-5")

response = client.messages.create(
    model=MODEL,
    max_tokens=1024,
    messages=[{"role": "user", "content": "Привет"}],
)
print("".join(b.text for b in response.content if b.type == "text"))

Здесь Anthropic SDK, поэтому адрес указан без /v1 — SDK добавляет его сам. Для OpenAI SDK адрес — https://api.zukko.pro/v1.

Кэширование списка

Запрашивать /v1/models перед каждым вызовом незачем. Достаточно обновлять список при старте и затем раз в какое-то время, например раз в час:

bash
import time

_cache = {"models": None, "ts": 0.0}

def get_models_cached(ttl: int = 3600) -> list[str]:
    now = time.time()
    if _cache["models"] is None or now - _cache["ts"] > ttl:
        _cache["models"] = get_available_models()
        _cache["ts"] = now
    return _cache["models"]

Даже с кэшем держите обработку model_disabled в коде вызова: модель могут отключить между обновлениями списка.

Почему список меняется

  • Вендоры выпускают новые версии, и они появляются в каталоге.
  • Старые версии отключаются — у вендора или в шлюзе.
  • Модель может быть отключена временно.

Новости о каталоге публикуются в Telegram-канале Zukko. Но код не должен зависеть от того, успели ли вы прочитать новость: опирайтесь на /v1/models и обработку model_disabled. Если ещё нет ключа для запросов к моделям, создайте его в разделе API-ключи.

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

Нужен ли ключ для GET /v1/models?

Нет, эндпоинт публичный. Ключ нужен для запросов к самим моделям — /v1/chat/completions, /v1/messages и другим.

Показывает ли список только модели, разрешённые моему ключу?

Нет, список общий. Ограничения ключа (allowed_models) проверяются при запросе к модели: если модели нет среди разрешённых, вернётся 403 model_not_allowed_for_key.

Что вернёт запрос к отключённой модели?

HTTP 503 с кодом model_disabled в теле ответа. Не повторяйте такой запрос — переключитесь на другую модель из цепочки или из актуального списка.

Как часто меняется список?

Регулярного графика нет. Поэтому код должен проверять список при старте и корректно обрабатывать model_disabled в любой момент.

zukko

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

за Claude Code & ChatGPT

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

Список моделей API: GET /v1/models на curl и Python · Zukko