OpenAI 호환 API의 핵심은 SDK가 그대로 작동한다는 점입니다. 따라서 401이 발생할 때 버그는 거의 항상 변경한 두 줄, 즉 base_url과 api_key에 있습니다. 실제 발생 순서에 따라 실패 유형을 설명합니다.
오류
{
"error": {
"type": "invalid_api_key",
"message": "Invalid or missing API key.",
"code": "invalid_api_key"
}
}원인과 해결 방법 한눈에 보기
| 원인 | 해결 방법 |
|---|---|
| base_url에 /v1 접미사가 없음(또는 중복됨) | 대부분의 게이트웨이는 https://host/v1을 정확히 요구합니다. SDK가 자체적으로 /chat/completions를 추가합니다. |
| 다른 호스트의 키 | sk-… 키는 해당 키를 발급한 서비스에서만 인증됩니다. 접두사와 호스트가 일치하는지 확인하세요. |
| 기업 프록시/WAF가 Authorization 헤더를 제거함 | 깨끗한 네트워크에서 테스트하고 프록시가 Authorization을 통과시키도록 구성하세요. |
| OPENAI_API_KEY 환경 변수가 명시적 키를 덮어씀 | SDK는 기본적으로 환경 변수를 읽습니다. 일부 설정에서는 오래된 환경 변수가 조용히 우선됩니다. api_key를 명시적으로 전달하세요. |
SDK가 호출하는 정확한 URL 확인
client.base_url을 출력하고 GET /v1/models를 호출하세요. 이는 가장 저렴한 인증 엔드포인트입니다. /models가 작동한다면 인증은 정상이고 오류는 다른 곳에 있습니다:
from openai import OpenAI
client = OpenAI(
base_url="https://api.kunavo.com/v1", # exactly one /v1
api_key="sk-kn-...", # explicit beats env vars
)
print(client.base_url)
print([m.id for m in client.models.list().data][:5])동일한 호스트를 curl로 호출해 SDK 문제 배제
Authorization: Bearer를 사용한 curl은 작동하지만 SDK가 작동하지 않는다면 SDK의 실제 요청을 비교하세요(OPENAI_LOG=debug 설정). 열 번 중 아홉 번은 프록시나 환경 변수가 무언가를 다시 작성한 경우입니다.
Kunavo를 통해 호출하는 경우
Kunavo의 엔드포인트는 https://api.kunavo.com/v1에서 엄격한 OpenAI 형태를 따르고 Bearer 인증을 사용하며, GET /v1/models가 인증 스모크 테스트로 작동합니다. 코드가 api.openai.com에 대해 실행된다면 base_url을 Kunavo로 가리키는 것이 유일한 변경입니다. 동일한 SDK, 동일한 와이어 형식으로 Claude, GPT, 미디어 모델에 하나의 키를 사용할 수 있습니다.
자주 묻는 질문
게이트웨이의 401과 403 — 차이는 무엇인가요?
401 = 자격 증명 자체가 승인되지 않음(키 누락/유효하지 않음). 403 = 키는 유효하지만 해당 작업이 허용되지 않음(비활성화된 키, 정지된 계정, 허용되지 않은 모델). 오류 본문을 읽으세요. 호환 API는 error.message에 이유를 넣습니다.
코드가 로컬에서는 작동하지만 CI에서 401이 되는 이유는 무엇인가요?
CI는 다른 환경입니다. 비밀 값이 설정되지 않았거나 다른 서비스에 설정되었거나 프록시가 헤더를 제거했을 수 있습니다. CI 내부에서 repr(key[:12])와 base_url을 기록해 실제로 무엇이 전송되는지 확인하세요.
관련 가이드
오류 의미에 대한 자세한 내용은 오류 참조에서 확인할 수 있습니다. 가입 및 인증 가이드를 통해 1분이면 키를 받을 수 있습니다.