La API Key de Codex no es solo una cadena de caracteres. Determina a nombre de quién se factura la solicitud, qué modelos se pueden invocar y cuánto impacto tiene una filtración. La mayoría de los errores 401 no se deben a una clave inválida, sino a nombres de variables inconsistentes, encabezados reescritos, un nivel de configuración incorrecto o credenciales antiguas en la caché local.

Este artículo sigue el orden «tipos de clave, creación, variables de entorno y archivos de configuración, perfiles, rotación, permisos mínimos, CI y diagnóstico de 401» y ofrece un método que puedes aplicar directamente. Los comandos y opciones de configuración dependen de la versión actual de Codex y de la documentación del gateway que uses.

Nota: OpenAI, Codex y ChatGPT son marcas comerciales o marcas registradas de OpenAI. Este artículo solo ofrece una explicación técnica y no tiene relación de afiliación con OpenAI. Los permisos de las claves, el alcance de las interfaces y la facturación se rigen por la documentación oficial de cada plataforma y las páginas del sitio.

1. Distingue primero tres tipos de clave y dos almacenes

Las credenciales relacionadas con Codex se confunden con facilidad; sepáralas por uso:

Nombre Uso típico Ubicación Atención
API Key de OpenAI Platform Inicio de sesión con codex login --with-api-key auth.json o llavero del sistema Factura según la tarifa estándar de la interfaz
CODEX_API_KEY codex exec, SDK y ejecuciones puntuales Solo el entorno del proceso actual No se escribe en disco; adecuada para CI
Clave de proveedor personalizado Se referencia con env_key a una variable de entorno Entorno del shell o gestor de secretos Habitual en gateways de equipo; facilita límites

El primer almacén es la «credencial de inicio de sesión» y lo controla cli_auth_credentials_store: file escribe auth.json dentro de CODEX_HOME, keyring usa el llavero del sistema, auto prueba el llavero y recurre al archivo si falla, y ephemeral solo mantiene la credencial en memoria del proceso actual. El segundo almacén es la «clave de proveedor»: env_key indica el nombre de la variable de entorno y Codex la lee en cada solicitud. Ojo: env_key es solo el nombre de la variable, no la variable en sí.

CODEX_HOME es ~/.codex por defecto y puede cambiarse a un directorio controlado. OPENAI_API_KEY es la variable de origen que lee el comando de inicio de sesión; CODEX_API_KEY es la credencial puntual de las ejecuciones no interactivas. Los nombres se parecen, pero el uso es distinto.

2. Crea una clave en cinco pasos

  1. Abre ZSQH AI Gateway o la plataforma que uses, regístrate e inicia sesión en la consola.
  2. Entra en la página «API Keys», crea una nueva y nombra con claridad el entorno y el uso, por ejemplo codex-work-mac.
  3. Define un límite de gasto y una fecha de caducidad. Para una clave de prueba, empieza con un límite bajo y ajústalo cuando confirmes el consumo real.
  4. Si la plataforma admite lista blanca de modelos o alcance por proyecto, marca solo los modelos que Codex necesita.
  5. Copia la clave completa y guárdala de inmediato en un gestor de contraseñas o de secretos. La mayoría de las consolas solo la muestran una vez.

Las claves suelen empezar por sk-, pero el prefijo no demuestra autenticidad ni indica permisos. Al copiar, revisa espacios al inicio y al final, saltos de línea y comillas sobrantes: es una causa frecuente de 401. Después de crearla, valida con una solicitud mínima antes de distribuirla al equipo.

3. Cómo combinar variables de entorno y config.toml

La práctica recomendada: en el archivo de configuración escribe solo el nombre de la variable y guarda la clave real en el entorno o en una herramienta de gestión de secretos. Ejemplo de ~/.codex/config.toml:

# ~/.codex/config.toml
model = "tu-model-id"
model_provider = "zsqh"

[model_providers.zsqh]
name = "ZSQH AI Gateway"
base_url = "https://ai.zhongshangqihang.com/v1"
wire_api = "responses"
env_key = "ZSQH_API_KEY"
env_key_instructions = "Crea una clave en la consola del gateway y expórtala como variable de entorno"

Luego expórtala en la misma shell desde la que inicias Codex:

export ZSQH_API_KEY="sk-tu-clave"

En macOS y Linux puedes poner esta línea en un archivo privado como ~/.zshrc.local, y hacer que el archivo principal solo referencie la variable. En Windows PowerShell: $env:ZSQH_API_KEY="sk-tu-clave". Los procesos lanzados desde el Dock, un IDE o una aplicación de escritorio pueden no leer las variables del shell; en ese caso, insértalas en el script de arranque o en las variables del sistema.

Si el gateway exige encabezados personalizados, puedes usar env_http_headers = { "X-API-Key" = "ZSQH_API_KEY" } en lugar de env_key, y configurar un catálogo local de modelos. Si la clave la emite dinámicamente una herramienta como Vault o KMS, puedes obtener el token con command en [model_providers.zsqh.auth], pero no junto con env_key. experimental_bearer_token permite escribir la clave directamente, pero no se recomienda y los entornos de equipo deberían evitarlo.

A nivel personal también puedes usar el inicio de sesión: printenv OPENAI_API_KEY | codex login --with-api-key guarda la credencial en auth.json o en el llavero; para borrarla, codex logout. En gateways de equipo se recomienda más env_key, porque los límites, permisos de modelos y revocación se gestionan de forma central.

4. Varias configuraciones y perfiles

Se recomienda separar al menos tres credenciales: uso personal diario, proyecto específico y automatización. Sus límites, permisos y ciclos de rotación son distintos; mezclarlas dificulta tanto la atribución del consumo como el diagnóstico.

Las versiones más recientes de Codex separan los perfiles en archivos independientes. En la configuración principal define dos proveedores, cada uno con una variable de entorno distinta:

# ~/.codex/config.toml
model = "tu-model-id"
model_provider = "zsqh_work"

[model_providers.zsqh_work]
base_url = "https://ai.zhongshangqihang.com/v1"
wire_api = "responses"
env_key = "ZSQH_WORK_KEY"

[model_providers.zsqh_test]
base_url = "https://ai.zhongshangqihang.com/v1"
wire_api = "responses"
env_key = "ZSQH_TEST_KEY"

Luego crea ~/.codex/test.config.toml con solo las claves de nivel superior que quieras sobrescribir:

model = "tu-model-id-de-prueba"
model_provider = "zsqh_test"

Ejecuta codex --profile test para cambiar. Ten en cuenta que, desde 0.134.0, la antigua tabla [profiles.xxx] y la clave de nivel superior profile = "..." ya no se leen, y el archivo de perfil tampoco debe anidar [profiles.xxx]: usa claves de nivel superior. Las versiones anteriores quizá acepten la forma antigua; revisa las notas de la versión antes de actualizar.

El .codex/config.toml de proyectos de confianza solo sirve para convenciones no sensibles; en él se ignoran model_provider, model_providers y el perfil, y nunca debes escribir una clave para confirmarla en el repositorio.

5. Rotación de claves: cuándo y cómo

El objetivo de la rotación no es cumplir un trámite, sino reducir la ventana de exposición tras una filtración. La salida de un empleado, la pérdida de un dispositivo, una sospecha de filtración, una exigencia del proveedor o un ciclo fijo (por ejemplo, cada 90 días) son buenos motivos.

  1. Crea una nueva clave en la consola con la fecha en el nombre, por ejemplo codex-prod-2026-10.
  2. Escribe primero la nueva clave en el gestor de secretos o en la variable de entorno y conserva temporalmente la antigua.
  3. Verifica con codex exec y una solicitud mínima que el modelo, el límite y los permisos funcionan.
  4. Revisa los registros de consumo de la clave antigua para confirmar que no quedan scripts ni miembros usándola.
  5. Desactiva la clave antigua y observa durante uno o dos días la tasa de errores y las solicitudes fallidas.
  6. Registra la fecha, el responsable y el alcance de la rotación para facilitar el traspaso y la auditoría.

No rotes en horas pico de producción. Mantener dos claves en paralelo durante un tiempo es más seguro que «borrar y crear». Si solo usas el inicio de sesión, tras la rotación ejecuta codex logout y vuelve a iniciar sesión para evitar credenciales antiguas en auth.json. Protege auth.json como una contraseña y no lo sincronices con discos públicos ni repositorios.

6. Permisos mínimos y prevención de filtraciones

  • Una clave por persona, subdividida por entorno; CI con una clave aparte y límites propios.
  • Asigna caducidad, presupuesto y límite de concurrencia; habilita solo los modelos necesarios.
  • Si la plataforma admite lista blanca de IP, limita a la red de oficina o a la salida del runner; si no, apóyate en límites y alertas.
  • En entornos empresariales, forced_login_method = "api" o "chatgpt" fuerza un método único y evita que los miembros mezclen credenciales.
  • En equipos personales, prioriza cli_auth_credentials_store = "keyring"; en equipos compartidos o CI usa ephemeral para reducir escrituras en disco.
  • Cubre en .gitignore archivos como .env, .env.*, auth.json y *.pem; antes de confirmar, usa secret scanning o un hook de pre-commit para detectar el patrón sk-.
  • No escribas claves predeterminadas en el código, no depures con echo $ZSQH_API_KEY y enmascara el encabezado Authorization en los registros.

Si confirmas una filtración, el orden es: desactivar o eliminar la clave, crear una nueva y revisar los registros de consumo y el historial del repositorio. Borrar el archivo no basta: la clave antigua puede estar copiada en otro lugar.

7. CI y uso no interactivo

El principio en CI es «la clave no entra en el código, ni en la imagen, ni en los registros».

  • Para una ejecución puntual, usa CODEX_API_KEY=<clave> codex exec --json "...", inyectada solo en ese comando; no la configures como variable de entorno del trabajo.
  • En GitHub Actions, prioriza la Action de Codex; no pongas la clave directamente en un paso de shell.
  • CI usa una clave independiente, con límite bajo y permisos estrechos, solo en ramas protegidas o flujos de trabajo de confianza.
  • Usa --ephemeral para evitar escribir archivos de sesión en disco; si no ejecutas dentro de un repositorio Git, añade --skip-git-repo-check cuando corresponda.
  • No uses credenciales gestionadas de ChatGPT en repositorios públicos ni en runners no confiables.

8. Diagnóstico de 401: revisa en este orden

401 significa fallo de autenticación, pero no implica necesariamente que la clave esté mal. Sigue este orden:

  1. Ejecuta codex login status para confirmar el método de autenticación realmente activo.
  2. Confirma que el nombre de la variable indicada por env_key está bien escrito y no está vacía en el proceso actual; revisa solo la longitud, sin imprimir el valor completo.
  3. Confirma desde qué entorno se inicia Codex. La terminal integrada del IDE, Docker, systemd o launchd pueden no heredar las variables del shell.
  4. Vuelve a copiar la clave desde la consola y descarta espacios, saltos de línea y comillas.
  5. Si usas credenciales de inicio de sesión, ejecuta codex logout y vuelve a iniciar sesión para descartar residuos en auth.json.
  6. Comprueba si forced_login_method entra en conflicto con el tipo de credencial actual; si no coincide, Codex puede salir directamente o rechazar solicitudes.
  7. Comprueba si la clave caducó, fue desactivada, no tiene saldo o carece de permiso para ese modelo.
  8. Confirma que la Base URL y la ruta /v1 son correctas y que el proxy no elimina ni reescribe el encabezado Authorization; si es necesario, contrasta con los registros del gateway.

Correspondencia de errores habituales:

Síntoma Causa habitual Tratamiento
401 Unauthorized Variable no exportada, nombre inconsistente, credencial caducada Revisa env_key; reabre la terminal; vuelve a iniciar sesión
403 Forbidden Sin permiso de modelo, restricción de IP, cuota congelada Revisa permisos y lista blanca en la consola
404 Not Found Base URL con /v1 de más o de menos, ruta incorrecta Comprueba la dirección y el alcance de la interfaz tramo por tramo
429 Too Many Requests Concurrencia o cuota excedida Reduce la concurrencia y revisa el límite de la clave
model not found Identificador de modelo incorrecto Copia el identificador exacto de la página de precios

Preguntas frecuentes

¿Una API Key de Codex y una suscripción de ChatGPT son lo mismo?

No. La suscripción de ChatGPT está orientada a los productos web y de escritorio; Codex puede usar inicio de sesión con cuenta o facturar por consumo con una API Key. Las cuotas, facturas y permisos difieren, y un equipo debe contabilizarlos por separado.

¿Qué relación hay entre env_key y OPENAI_API_KEY?

env_key es una opción de configuración cuyo valor es el nombre de una variable de entorno; OPENAI_API_KEY es uno de los nombres habituales y también la fuente que lee codex login --with-api-key. Puedes usar env_key = "OPENAI_API_KEY", pero se recomienda un nombre propio para el gateway y evitar mezclarlo con credenciales de inicio de sesión.

¿Se puede escribir la clave directamente en config.toml?

No se recomienda. Una clave en texto plano se filtra con facilidad en copias de seguridad, capturas o repositorios. Usa env_key para referenciar una variable o llama a un comando externo mediante [model_providers.xxx.auth].

¿Hay que detener el servicio para rotar una clave?

No. Crea y valida la nueva clave, cambia la configuración y desactiva la antigua después; mantener ambas en paralelo un tiempo evita interrupciones.

¿Por qué codex login status es correcto y las solicitudes siguen dando 401?

Un estado de inicio de sesión correcto solo indica que existe una credencial local, no que la clave del proveedor personalizado sea válida. Revisa la variable env_key, la Base URL, el saldo del gateway y los permisos de modelo; si la solicitud pasa por un proxy, comprueba si se reescriben los encabezados.

Próximos pasos

Si aún no tienes clave, puedes crear una de prueba con límite bajo desde el registro y configurarla y validarla siguiendo este artículo. Los modelos, límites y facturación figuran en precios de modelos; los precios cambian con las versiones de modelo y las políticas del proveedor, así que consulta la información vigente de la página.

Lecturas relacionadas: