«Invalid API key» значит, что сервер получил запрос, но не смог сопоставить строку в заголовке x-api-key (или Authorization: Bearer для OpenAI-совместимого формата) с действующим ключом. Anthropic возвращает на это HTTP 401 с типом authentication_error, а не ошибку в теле запроса: значит, дело не в модели и не в промпте, а в том, что до сервера дошло как учётные данные. Причин обычно четыре, и все проверяются без обращения в поддержку.
Как выглядит эта ошибка
В сыром виде ответ сервера выглядит так:
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
}
}
Дальше формулировка меняется в зависимости от того, откуда вы смотрите:
- curl покажет этот JSON целиком в теле ответа с кодом
401. - Python и Node SDK оборачивают его в исключение аутентификации (
anthropic.AuthenticationErrorв Python) и печатают то же сообщение в трейсбеке. - Claude Code выведет ошибку в терминал при первом же обращении к модели: CLI просто передаёт то, что вернул API, добавляя от себя разве что подсказку проверить переменные окружения.
- Cursor и другие IDE с настройкой пользовательского API покажут её при первом тестовом запросе после сохранения ключа, обычно с пометкой
authentication errorв статусе подключения.
Текст один и тот же везде: invalid x-api-key. Разбираем причины по порядку, от самой частой к самой редкой.
Причина 1: ключ неверный, с опечаткой или отозван
Самый banальный вариант. Ключ Anthropic имеет формат sk-ant-api03-... и выдаётся один раз в момент создания: если вы скопировали его не полностью или вставили лишний символ, сервер увидит строку, которая ни на что не похожа, и ответит той же ошибкой, что и на полностью случайный набор символов.
Отозванный ключ ведёт себя идентично невалидному: разницы в сообщении нет. Ключи отзывают вручную из консоли, а также автоматически, если у ключа настроен срок действия и он истёк. Проверка простая: откройте список ключей в консоли и убедитесь, что нужный ключ там есть и активен. Если ключа в списке нет, создавайте новый: старое значение восстановить нельзя.
Причина 2: ключ выпущен не в той организации
Про эту причину чаще всего забывают, потому что ключ выглядит рабочим: он существует, не просрочен, скопирован без ошибок. Личный ключ Anthropic привязан к конкретной организации в консоли и перестаёт проходить аутентификацию, если вас удалили из этой организации или вы сами вышли из неё. Та же логика работает, если у вас несколько организаций (например, личный аккаунт и рабочий) и ключ создан в одной, а вы ожидаете, что он подойдёт для другой: лимиты, модели и биллинг у них разные, и ключ из одной организации не подхватит настройки другой.
Отдельный частный случай: ключ, который работает сразу в нескольких рабочих пространствах (workspaces), может потребовать явного заголовка с идентификатором рабочего пространства в запросе. Без него сервер иногда не может понять, к какому пространству отнести запрос, и возвращает ту же ошибку аутентификации. Если вы администрируете организацию с несколькими пространствами, это первое, что стоит проверить после самого ключа.
Причина 3: пробел или перенос строки в переменной окружения
Ключ копируется из консоли одним движением, но по пути в переменную окружения ему есть где испортиться:
- вставка через терминал, который автоматически добавляет перенос строки в конце;
- ключ, сохранённый в
.envфайле с пробелом после знака равенства; - копирование из документа или чата, где текст был обёрнут и в середину строки попал невидимый перенос.
Такой ключ выглядит правильно при простом просмотре, но сервер сравнивает его посимвольно, и лишний байт ломает совпадение. Быстрая проверка в терминале:
echo -n "$ANTHROPIC_API_KEY" | wc -c
echo -n "$ANTHROPIC_API_KEY" | cat -A | tail -c 20
Первая команда покажет длину значения: если она на один-два символа больше ожидаемой, где-то затесался лишний пробел или \n (в выводе cat -A он покажет себя как $ в неожиданном месте). Второй способ, ещё надёжнее: удалить переменную и задать её заново, набрав export руками, а значение ключа вставить без кавычек по краям.
Причина 4: перепутаны ключ и адрес сервера
Ключ Anthropic sk-ant-... и ключ Claudexia sk_cdx_... рассчитаны на разные базовые адреса. Если ключ sk_cdx_... уходит на api.anthropic.com, сервер Anthropic его вообще не распознает как свой формат и ответит authentication_error. Та же история в обратную сторону: ключ sk-ant-..., отправленный на https://api.claudexia.tech, тоже не пройдёт, потому что шлюз ждёт ключ собственного формата.
Эта путаница чаще всего возникает при переходе с одного сервиса на другой: обновили base_url в одном месте конфигурации, а старый ключ остался в переменной окружения или в настройках IDE, и наоборот. Проверяйте пару «ключ плюс адрес» вместе, а не по отдельности.
Как быстро всё это продиагностировать
Порядок проверки, который закрывает все четыре причины за пару минут:
- Посмотрите первые 10-12 символов ключа:
sk-ant-значит Anthropic,sk_cdx_значит Claudexia. Сверьте с тем, на какойbase_urlон отправляется. - Проверьте длину значения переменной окружения командой выше, чтобы исключить пробел или перенос строки.
- Откройте список ключей в консоли (Anthropic или личном кабинете Claudexia) и убедитесь, что ключ там есть, активен и создан в нужной организации или рабочем пространстве.
- Если всё совпадает, а ошибка держится, создайте новый ключ и замените старый: иногда быстрее выпустить новый, чем искать, где именно повреждено старое значение.
Если проблема в самом ключе Anthropic
Если после проверки выясняется, что дело не в опечатке или окружении, а в самом ключе Anthropic: он отозван, организация закрыла доступ, или вы просто хотите не зависеть от одного ключа, к моделям Claude можно подключиться через отдельный ключ Claudexia, никак не связанный с прежним аккаунтом.
Ключ создаётся в личном кабинете, в разделе «API-ключи», и имеет формат sk_cdx_.... Для прямых вызовов API и SDK базовый адрес: https://api.claudexia.tech.
import anthropic
client = anthropic.Anthropic(
api_key="sk_cdx_ВАШ_КЛЮЧ",
base_url="https://api.claudexia.tech",
)
message = client.messages.create(
model="claude-sonnet-4.6",
max_tokens=1024,
messages=[{"role": "user", "content": "Привет"}],
)
print(message.content[0].text)
Для Claude Code настройка идёт через две переменные окружения без входа в консоль Anthropic вообще, шаг за шагом для Linux, macOS и Windows расписано в статье «Claude Code в России». Полный разбор остальных кодов ошибок API, 429, 500, 529, собран в гиде по ошибкам Claude API. Актуальные модели и цены на них смотрите на странице моделей, а завести ключ и оформить доступ к API можно на странице «Купить Claude API».
FAQ
Почему curl отдаёт «invalid x-api-key», хотя я точно скопировал ключ правильно?
Чаще всего дело в невидимых символах: перенос строки на конце значения или пробел после знака равенства в .env файле. Проверьте длину значения командой echo -n "$ANTHROPIC_API_KEY" | wc -c и сравните с ожидаемой длиной ключа.
Может ли ключ перестать работать сам по себе, без действий с моей стороны?
Да. Личный ключ Anthropic привязан к организации в консоли и перестаёт проходить аутентификацию, если вас удалили из этой организации. Ключи со сроком действия также истекают автоматически по расписанию, заданному при создании.
В чём разница между 401 и 403, если оба про доступ?
401 authentication_error значит, что сам ключ не распознан как действительный. 403 permission_error значит, что ключ рабочий, но у него нет прав на конкретный ресурс или модель: например, модель отключена для вашего тарифа или ключ ограничен по списку разрешённых моделей.
Ключ Claudexia и ключ Anthropic взаимозаменяемы?
Нет. Формат разный (sk_cdx_... против sk-ant-...), и каждый ключ работает только со своим базовым адресом: Claudexia на https://api.claudexia.tech, Anthropic на api.anthropic.com. Замена одной строки, base_url, обычно и есть весь объём изменений в коде при переходе.
Нужно ли менять заголовок запроса при переходе на Claudexia?
Нет, если вы используете Anthropic SDK или совместимый формат: заголовок остаётся x-api-key, меняется только значение ключа и base_url. Для OpenAI-совместимого формата используется Authorization: Bearer, и правило то же самое.
Ошибка появилась только что, хотя вчера всё работало. Что изменилось?
Проверьте в первую очередь консоль ключей: возможно, ключ отозвали вручную, у него истёк срок действия, или изменился состав организации. Если ключ на вид цел, но со вчерашнего дня менялось окружение (переустановка зависимостей, обновление .env, смена терминала), в первую очередь подозревайте лишний символ, попавший в переменную при копировании.