401 yanıtı, bir kimlik bilgisinin reddedildiğini söyler; anahtar dizenizin mutlaka hatalı olduğunu değil. Benzer şekilde 403 de her zaman eksik yetki anlamına gelmez. Her iki sağlayıcı da, kimlik bilgisi tamamen geçerli olsa bile bazı durumlarda bu kodları döndürüyor. Önce şu istisnayı kontrol edin: Hata yanıtında maskelenmiş bir anahtarın ilk ve son karakterleri elinizdeki anahtarla uyuşmuyorsa, sunucuya ulaşan kimlik bilgisi göndermek istediğiniz bilgi değildir.
Aynı Görünen Üç Farklı 401 Senaryosu
Aşağıdaki durumların tamamı kimlik doğrulama hata türüyle birlikte HTTP 401 döndürüyor; ancak çözüm yolları birbirinin tam tersi. Mesajlar, kasten geçersiz anahtarlarla yaptığım altı isteğe bu iki endpoint'in verdiği yanıtlardır. Hatalı kimlik bilgisi yetkilendirme aşamasından önce reddedildiği için bunları yeniden üretmek adına gerçek bir anahtara ihtiyacınız yok.
| Gerçekte olan | Anthropic /v1/messages | OpenAI /v1/responses |
|---|---|---|
| Anahtar ulaştı ve reddedildi | API key is invalid. | Incorrect API key provided: sk-proj-**********-key. ve "code": "invalid_api_key" |
| Hiç kimlik bilgisi ulaşmadı | x-api-key header is required | Missing bearer or basic authentication in header |
| Kimlik bilgisi yanlış header'da ulaştı | Invalid bearer token | Missing bearer or basic authentication in header; önceki satırla tamamen aynı |
Anthropic bu üç durumu ayrı ayrı adlandırıyor. OpenAI endpoint'i ise hem “hiçbir şey göndermediniz” hem de “anahtarı okumadığım bir header'da gönderdiniz” durumunda aynı mesajı veriyor. Bu yüzden bir relay kullanıcısı, anahtarın shell'de tanımlı olduğu açıkça ortadayken eksik header hatasına bakakalabiliyor.
Yanıt header'ları bu belirsizliği tek başına çözmüyor; ancak reddedilmiş bir kimlik bilgisini yetkilendirme aşamasına hiç ulaşmamış olandan ayırabiliyor. Altı çağrıyı çalıştırın ve açıklama metni yerine header'ları inceleyin:
show(){ shift; curl -sS -D - -o /dev/stdout "$@" \
| grep -iE "^HTTP|www-authenticate|x-openai-authorization-error|request-id|x-should-retry|message"; }
A=(-X POST https://api.anthropic.com/v1/messages -H "anthropic-version: 2023-06-01"
-H "content-type: application/json"
-d '{"model":"claude-sonnet-4-5","max_tokens":8,"messages":[{"role":"user","content":"hi"}]}')
O=(-X POST https://api.openai.com/v1/responses -H "content-type: application/json"
-d '{"model":"gpt-5.6","max_output_tokens":16,"input":"hi"}')
show a1 "${A[@]}" -H "x-api-key: sk-ant-api03-not-a-real-key" # rejected
show a2 "${A[@]}" # never arrived
show a3 "${A[@]}" -H "Authorization: Bearer sk-ant-api03-not-a-real-key" # wrong header
show o1 "${O[@]}" -H "Authorization: Bearer sk-proj-not-a-real-key" # rejected
show o2 "${O[@]}" # never arrived
show o3 "${O[@]}" -H "x-api-key: sk-proj-not-a-real-key" # wrong header
2026-07-31 tarihinde ayırt edici satırlar şunlardı; yalnızca farklılaşan alanları bıraktım:
o1 rejected HTTP/2 401 x-openai-authorization-error: 401 "code": "invalid_api_key"
o2 never arrived HTTP/2 401 www-authenticate: Bearer realm="OpenAI API"
o3 wrong header HTTP/2 401 www-authenticate: Bearer realm="OpenAI API"
a1 rejected HTTP/2 401 "request_id": null (no request-id, no x-should-retry)
a2 never arrived HTTP/2 401 request-id: req_011CdZnC9j… x-should-retry: false
a3 wrong header HTTP/2 401 request-id: req_011CdZnCDN… x-should-retry: false
Her iki endpoint'te de reddedilen kimlik bilgisinde sağlayıcının kendi yetkilendirme alanı vardı ve challenge header'ı yoktu; yetkilendirme aşamasına ulaşmayan istekte ise bunun tersi görülüyordu. Tekrarlanan çağrılar aynı ayrımı verdi. Yine de bu, iki endpoint'e dair tarihli bir gözlemdir; belgelenmiş bir davranış değildir. Kendi sağlayıcınız için geçerli olduğunu varsaymak yerine yukarıdaki bloğu yeniden çalıştırın. İstek reddedilen anahtar satırına düşüyorsa OpenAI veya Claude anahtar sayfasında dört noktayı kontrol edin: değerin başında veya sonunda boşluk bulunması, anahtarın silinmiş ya da iptal edilmiş olması, çağırdığınızdan farklı bir proje veya kuruluş için oluşturulmuş anahtar kullanılması ve istemcide hâlâ önbellekte duran eski bir kopya. İlk üçü temiz çıkmadan anahtarı yeniden oluşturmayın.
CLI Gerçekte Hangi Kimlik Bilgisini Gönderiyor?
Bir kodlama CLI'ı sizin yapılandırmadığınız geçersiz bir anahtarı bildiriyorsa, sorun önbelleğe alınmış bir kimlik bilgisi değildir. Daha yüksek öncelikli bir kaynak devreye girmiştir. Claude Code, altı kaynağı sabit bir sırayla çözümler; bu belgelenmiş öncelik sırası, her birinin hangi header üzerinden gönderileceğini de belirler.
| Öncelik | Kaynak | Gönderilen header |
|---|---|---|
| 1 | Bulut sağlayıcısı kimlik bilgileri (CLAUDE_CODE_USE_BEDROCK, _VERTEX, _FOUNDRY) | sağlayıcıya özgü |
| 2 | ANTHROPIC_AUTH_TOKEN | Authorization: Bearer |
| 3 | ANTHROPIC_API_KEY | X-Api-Key |
| 4 | apiKeyHelper script çıktısı | döndürüldüğü biçimde |
| 5 | CLAUDE_CODE_OAUTH_TOKEN | OAuth |
| 6 | /login ile yapılan abonelik girişi | OAuth |
Geçerli bir ANTHROPIC_API_KEY, abonelik girişinizden daha üst sıradadır; dolayısıyla /login bunu devre dışı bırakmaz. -p bayrağıyla da anahtar mevcutsa her zaman kullanılır. Anthropic'in kendi çözüm listesi şu sırayı öneriyor: CLI'ı başlattığınız shell'de env | grep ANTHROPIC çalıştırın, ardından /status kullanın; aboneliği kullanmak istiyorsanız değişkeni unset edin. env kontrolü yalnızca tablodaki 2 ve 3. satırları kapsar. Çözümlenen kaynağın bulut sağlayıcısı, yardımcı script veya giriş olup olmadığını gösteren komut /status'tur.
“Ben bunu hiç tanımlamadım” dediğiniz kimlik bilgisi
Şu rapor, sorunun nasıl göründüğünü iyi özetliyor:
"Claude, hiçbir API ortam değişkeni ayarlı olmamasına ve claude code'u pro max hesabıma başarıyla bağlamış olmama rağmen API faturalandırma modunda takılı kaldı"
Bir maintainer'ın ilk sorusu, apiKeyHelper yapılandırılıp yapılandırılmadığı oldu. Yapılandırılmıştı ve gövdesinin tamamı PLACEHOLDER_NOT_IMPLEMENTED_ON_MAC_YET yazdırıyordu. Çöp değer döndüren, sıfırdan farklı kodla çıkan veya hiçbir çıktı vermeyen bir yardımcı script yer tutucu bir kimlik bilgisi gönderir. API de script'i değil, anahtarı tarif eden bir 401 ile bunu reddeder. Claude Code artık bu hatayı üç deneme içinde adıyla bildiriyor; aynı kayda göre v2.1.208 öncesinde yardımcı script hataları, yaklaşık on sessiz yeniden denemeden sonra genel bir 401 olarak görünüyordu.
Ortam değişkenleri sizin haberiniz olmadan da ayarlanabilir. Anthropic, proje .env dosyasından eski bir anahtarı yükleyebilen kaynaklar arasında direnv, dotenv shell eklentileri ve IDE terminallerini sayıyor. Yardımcı script ayrıca beş dakika sonra veya HTTP 401 alındığında yeniden çağrılır; dolayısıyla bozuk bir script zamanlayıcıyla tekrar devreye girer.
Base URL bir gateway'i gösteriyorsa
ANTHROPIC_BASE_URL bir LLM gateway'ini gösteriyorsa, 401 sonrasındaki metin Anthropic'in değil gateway'in mesajıdır; /login bunu değiştiremez. Aynı durum, bir relay'e yönlendirilmiş OpenAI uyumlu istemciler için ters yönde de geçerlidir. Hata dizgesi url: https://openrouter.ai/api/v1/responses ile biten bir Codex raporundan:
"API anahtarlarıyla ilgili tüm ortam değişkenlerini temizlemeyi, auth dosyasını silmeyi denedim; işe yaramadı. Defalarca yeniden giriş yaptım, hata sürüyor"
Yerel kimlik bilgilerini temizlemek bunu düzeltemez; isteği kimin değerlendireceğini base URL belirler. Kimlik bilgisini endpoint'te duran hizmetle eşleştirin. Claude Code, bearer token ile kimlik doğrulayan gateway'ler için ANTHROPIC_AUTH_TOKEN'ı belgeliyor. Aynı değeri ANTHROPIC_API_KEY'e koyarsanız bunun yerine X-Api-Key olarak gönderilir; bu da yukarıdaki tablonun üçüncü satırıdır. Diğer istemciler kendi sözleşmelerine göre çalışır; sizin istemcinizin hangi header'ı gönderdiğini kontrol edin. Web'de Claude Code istisnadır: her zaman abonelik kimlik bilgilerini kullanır ve sandbox içinde bu değişkenlerden birini ayarlamak bunların önüne geçmez.
Anahtarın Geçerli Olduğu 403 Durumları
Bu bölümdeki örneklerin hiçbiri birinci elden yeniden üretilmedi; her biri belirli bir hesap durumu veya coğrafya gerektiriyor. Ancak sağlayıcı belgeleri, geçerli bir anahtarın da 403 üretebileceği konusunda açık.
OpenAI'nin hata referansında 403 - Country, region, or territory not supported yer alıyor. Bu, anahtara dokunmayan bir coğrafya kontrolüdür. Bunun iki satır üstünde ise karşıt durum bulunur: Proje veya kuruluş izin listesinin dışındaki bir IP'den istek geldiğinde dönen 401 - IP not authorized. Anahtar geçerlidir, çağıran taraf değildir.
Başarılı bir girişin ardından gelen API Error: 403 {"error":{"type":"forbidden","message":"Request not allowed"}} hatası için Anthropic üç neden sıralıyor; bunların hiçbiri yanlış yazılmış anahtar değil: etkin olmayan bir Pro veya Max aboneliği, "Claude Code" ya da "Developer" rolü olmayan bir Console hesabı veya isteğe müdahale eden kurumsal proxy. Platform API'de 403 - permission_error, anahtarın söz konusu kaynak için yetkisi olmadığı anlamına gelir; bu, kuruluş ve çalışma alanı ayarlarına göre denetlenir. compliance endpoint'lerinde ise yanlış scope'lara sahip geçerli bir anahtar, tasarım gereği 401 yerine 403 döndürür.
SSS
Claude API'de 403 hata kodu ne anlama gelir?
İki farklı anlamı olabilir. permission_error, anahtarınızın o kaynak için yetkisi olmadığını ve bunun kuruluş veya çalışma alanı ayarıyla ilgili olduğunu belirtir. Girişten sonra gelen Request not allowed ise abonelik durumuna, eksik bir Console rolüne veya proxy'ye işaret eder.
401 hatasında yeniden denemek mantıklı mı?
Tek başına 401 için hayır. Reddedilen veya hiç ulaşmayan kimlik bilgisi, 429'un aksine sonraki denemede de aynı sonucu verir. 429'da çözüm, geri çekilmeden önce Retry-After değerine uymaktır. Kendiliğinden düzelebilen tek 401, Claude Code'un zaten raporlamadan önce iki kez daha yeniden denediği apiKeyHelper durumudur.