Документация API go2llm

401 authentication_error и invalid x-api-key: почему ключ не принимается

Ошибка 401 означает, что сервер не смог сопоставить присланный ключ с существующей учётной записью. Anthropic API отвечает authentication_error с текстом invalid x-api-key, go2llm — кодом no-key и сообщением missing or unknown api key. Это всегда проблема заголовка или самого ключа, а не модели, баланса или региона: до инференса запрос не доходит.

Страница составлена 2026-09-11, обновлена 2026-09-11.

Как выглядит ошибка

Официальный Anthropic API возвращает на неверный ключ такой ответ со статусом 401:

{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "invalid x-api-key"
  }
}

go2llm на том же запросе возвращает собственный формат — статус 401 и код no-key:

{
  "error": {
    "type": "no-key",
    "code": "no-key",
    "message": "missing or unknown api key",
    "request_id": "gw_9c2b41a7e0f34d18b6c5a903d7e21f4b"
  }
}

Claude Code показывает ту же ситуацию иначе: вместо JSON пользователь видит предложение Please run /login. Это тот же 401 — CLI перехватывает статус и предлагает переавторизоваться вместо показа ответа сервера.

Воспроизводится ошибка одной командой:

curl -i https://go2llm.tech/v1/messages \
  -H "x-api-key: gk_sk_definitely_not_a_real_key" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-5","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'

Причины 401

1. Claude Code использует ANTHROPIC_API_KEY вместо ANTHROPIC_AUTH_TOKEN

Это причина номер один и почти нигде не описанная. Если на машине уже выполнялся вход в Claude Code под личным аккаунтом claude.ai или Anthropic Console, переменная ANTHROPIC_API_KEY может уступить сохранённому логину, и запрос уйдёт мимо go2llm — на api.anthropic.com, где ключ gk_sk_… неизвестен, и вернётся 401. Переменная ANTHROPIC_AUTH_TOKEN такого поведения не имеет: она всегда обращается к адресу из ANTHROPIC_BASE_URL.

2. Ключ не передан или передан в неправильном заголовке

Anthropic Messages API читает ключ из заголовка x-api-key, OpenAI Chat Completions — из Authorization: Bearer. go2llm принимает оба, но каждый на своём endpoint: x-api-key на POST /v1/messages, Authorization: Bearer на POST /v1/chat/completions и POST /v1/images/generations. Заголовок Authorization: gk_sk_… без слова Bearer не распознаётся и даёт 401 с кодом no-key.

3. В ключ попали лишние символы

Копирование из кабинета через терминал регулярно добавляет перевод строки, пробел или кавычку. Ключ go2llm начинается с префикса gk_sk_ и не содержит пробелов. Проверка: echo -n "$GO2LLM_API_KEY" | wc -c должно вернуть длину без символа перевода строки.

4. Ключ отозван, истёк или не разрешает эту модель

go2llm различает четыре причины отказа и возвращает разные коды. no-key — это 401, а вот inactive (ключ отозван), expired (истёк срок) и model (модель не в списке разрешённых для ключа) возвращаются со статусом 403, а не 401. Если в ответе 403 — смотрите страницу про 403, а не эту.

5. Ключ отправляется на чужой base URL

Ключ go2llm работает только на домене go2llm.tech. Base URL для OpenAI SDK — https://go2llm.tech/v1, для Anthropic SDK и Claude Code — https://go2llm.tech без /v1, потому что Anthropic SDK добавляет /v1 сам. Указание https://go2llm.tech/v1 в Anthropic SDK даёт запрос на /v1/v1/messages и ошибку маршрутизации.

6. Переменная окружения не долетела до процесса

export в одной вкладке терминала не виден в другой, а systemd-юниты, Docker-контейнеры и CI-раннеры не наследуют пользовательский профиль. Проверка внутри самого процесса: print(bool(os.environ.get("GO2LLM_API_KEY"))).

7. Ключ от другого сервиса

Ключ Anthropic начинается с sk-ant-, ключ OpenAI — с sk-proj- или sk-, ключ go2llm — с gk_sk_. go2llm не принимает ключи вендоров, и наоборот.

Как починить по шагам

Шаг 1. Проверьте, что ключ вообще работает, запросом без SDK и без переменных окружения:

curl -s -o /dev/null -w "%{http_code}\n" https://go2llm.tech/v1/messages \
  -H "x-api-key: ВСТАВЬТЕ_КЛЮЧ" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-5","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'

Ответ 200 означает, что ключ исправен и проблема в вашем клиенте. Ответ 401 — ключ не тот.

Шаг 2. Для Claude Code используйте именно ANTHROPIC_AUTH_TOKEN:

export ANTHROPIC_BASE_URL=https://go2llm.tech
export ANTHROPIC_AUTH_TOKEN=YOUR_API_KEY
export ANTHROPIC_MODEL=claude-sonnet-5
claude

Если ранее была выставлена ANTHROPIC_API_KEY, снимите её: unset ANTHROPIC_API_KEY.

Шаг 3. Для SDK проверьте пару «base URL + заголовок»:

import os
from anthropic import Anthropic

client = Anthropic(
    base_url="https://go2llm.tech",          # без /v1
    api_key=os.environ["GO2LLM_API_KEY"],    # ключ gk_sk_...
)

msg = client.messages.create(
    model="claude-opus-5",
    max_tokens=64,
    messages=[{"role": "user", "content": "Привет"}],
)
print(msg.usage)  # у go2llm здесь есть и cost_usd

Шаг 4. Проверьте статус ключа в кабинете: не отозван, не истёк, нужная модель в списке разрешённых, ваш текущий IP проходит IP allow-list.

Как избежать 401 в будущем

Обрабатывайте 401 как фатальную ошибку и не ретрайте: повтор с тем же ключом даст тот же 401 и только сожжёт лимит 20 RPM. Правильный обработчик различает коды:

import httpx

r = httpx.post(
    "https://go2llm.tech/v1/chat/completions",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"model": "gpt-5.6-sol", "max_tokens": 64,
          "messages": [{"role": "user", "content": "OK"}]},
    timeout=120.0,
)

if r.status_code == 401:
    err = r.json().get("error", {})
    code = err.get("code") or err.get("type")
    raise SystemExit(
        f"Ключ не принят ({code}): {err.get('message')}. "
        f"request_id={err.get('request_id')}. Ретрай не поможет."
    )

Храните ключ в секрет-менеджере или .env вне git, а не в коде. Для каждого окружения заводите отдельный ключ go2llm со своей квотой в долларах и своим IP allow-list — тогда компрометация ключа из CI не затрагивает прод. Ключ, созданный автоматически при регистрации, идёт без квоты: лимит выставляется вручную в кабинете.

Связанные ошибки

FAQ

Почему Claude Code пишет «Please run /login» вместо ошибки ключа? Claude Code перехватывает HTTP 401 и трактует его как истёкшую сессию. Если вы работаете через go2llm, выполнять /login не нужно — нужно выставить ANTHROPIC_AUTH_TOKEN и ANTHROPIC_BASE_URL=https://go2llm.tech, а ANTHROPIC_API_KEY снять через unset.

Можно ли использовать ключ Anthropic вида sk-ant-… на go2llm? Нет. go2llm принимает только собственные ключи с префиксом gk_sk_ и вернёт 401 no-key на чужой ключ. Обратное тоже верно: ключ gk_sk_… на api.anthropic.com даст authentication_error: invalid x-api-key.

Списываются ли деньги за запрос, который вернул 401? Нет. go2llm резервирует стоимость только после успешной авторизации ключа, поэтому 401 не затрагивает баланс. Стоимость успешного запроса приходит в usage.cost_usd.

Сколько ключей можно завести? Точное ограничение по количеству ключей в аккаунте мы пока не документировали — напишите в @go2llm_support, ответим и дополним страницу. У каждого ключа настраиваются квота в долларах, список разрешённых моделей, IP allow-list, срок действия и лимит RPM (по умолчанию 20).


Получить ключ и сделать первый запрос за 3 минуты → go2llm.tech. При регистрации на баланс начисляется $1, минимальное пополнение — $1. Цены на все модели — на странице тарифов, инструкции по подключению — в документации.