Tout l’intérêt des API compatibles OpenAI est que le SDK fonctionne immédiatement. Lorsqu’il renvoie 401, le bug se trouve presque toujours dans les deux lignes modifiées : base_url et api_key. Voici les modes d’échec dans l’ordre où ils se produisent réellement.
L’erreur
{
"error": {
"type": "invalid_api_key",
"message": "Invalid or missing API key.",
"code": "invalid_api_key"
}
}Causes et solutions en bref
| Cause | Solution |
|---|---|
| base_url sans suffixe /v1 (ou avec un double suffixe) | La plupart des passerelles attendent exactement https://host/v1 — le SDK ajoute lui-même /chat/completions. |
| Clé provenant d’un autre hôte | Les clés sk-… authentifient uniquement auprès du service qui les a émises ; vérifiez la correspondance préfixe ↔ hôte. |
| Proxy d’entreprise / WAF supprimant l’en-tête Authorization | Testez depuis un réseau propre et configurez le proxy pour transmettre Authorization. |
| La variable d’environnement OPENAI_API_KEY remplace votre clé explicite | Le SDK lit les variables d’environnement par défaut — dans certaines configurations, une variable obsolète l’emporte silencieusement ; transmettez api_key explicitement. |
Vérifiez l’URL exacte appelée par le SDK
Affichez client.base_url et appelez GET /v1/models — l’endpoint authentifié le moins coûteux. Si /models fonctionne, l’authentification est correcte et l’erreur se trouve ailleurs :
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])Utilisez Curl avec le même hôte pour écarter le SDK
Si curl fonctionne avec Authorization: Bearer mais pas le SDK, comparez la requête réelle du SDK (définissez OPENAI_LOG=debug) — neuf fois sur dix, un proxy ou une variable d’environnement a réécrit un élément.
Si vous appelez via Kunavo
L’endpoint de Kunavo suit strictement le format OpenAI à https://api.kunavo.com/v1 avec une authentification Bearer, et GET /v1/models sert de test d’authentification. Si votre code fonctionne avec api.openai.com, remplacer base_url par l’adresse de Kunavo est la seule modification nécessaire — même SDK, même format filaire, une seule clé pour Claude, GPT et les modèles multimédias.
Questions fréquentes
401 contre 403 sur une passerelle — quelle différence ?
401 = les identifiants eux-mêmes n’ont pas été acceptés (clé absente ou invalide). 403 = la clé est valide, mais l’action n’est pas autorisée (clé désactivée, compte suspendu, modèle non autorisé). Lisez le corps de l’erreur — les API compatibles indiquent la raison dans error.message.
Pourquoi mon code fonctionne-t-il localement mais renvoie 401 dans CI ?
CI est un environnement différent : le secret n’est pas défini, il correspond à un autre service ou un proxy supprime l’en-tête. Journalisez repr(key[:12]) et base_url depuis CI pour voir ce qui est réellement envoyé.
Guides associés
La sémantique détaillée des erreurs est disponible dans référence des erreurs ; obtenir une clé prend une minute via inscription et la guide d’authentification.