GET https://api.kie.ai/openai/v1/models, not from memory or training data. This endpoint gives the list Codex can actually run.Authorization: Bearer. Every KIE endpoint, including the model listing, carries the API key in this one header. A header literally named apikey is rejected with 401.model explicitly. Codex's built-in default model name is not a name KIE serves, so even with everything else in the provider correct, every request fails until model is a slug from the listing.model_provider and model_providers in a project-level .codex/config.toml.curl.exe:curl.exe -s -H "Authorization: Bearer $env:KIE_API_KEY" `
https://api.kie.ai/openai/v1/models | jq -r '.models[].slug'.data[] is the OpenAI-compatible shape, where only id identifies the model and the rest (created, object, owned_by) is boilerplate. .models[] is the richer copy and the one to read: slug is the value for model, and context_window, default_reasoning_level and supported_reasoning_levels describe what the model accepts.config.toml, with the model at the top level:model = "gpt-5.5"
model_provider = "kie"
[model_providers.kie]
name = "KIE"
base_url = "https://api.kie.ai/openai/v1"
env_key = "KIE_API_KEY"
wire_api = "responses"base_url is the root that requests are sent to. Codex appends /responses itself, so the value is https://api.kie.ai/openai/v1, not the full request URL https://api.kie.ai/openai/v1/responses.env_key names the environment variable Codex reads the credential from and sends as a bearer token. It does not hold the key itself.wire_api = "responses" is the protocol KIE serves. It is also Codex's default and can be left out; it is written here so the table explains itself.kie here), but openai, ollama and lmstudio are reserved and cannot be overridden.~/.codex/config.toml. Export the credential in the same shell that starts codex, or add it to your shell profile:CODEX_HOME to keep the configuration somewhere other than ~/.codex.%USERPROFILE%\.codex\config.toml, with identical content.$env:KIE_API_KEY = "…"
setx KIE_API_KEY "…"model_reasoning_effort sets how much reasoning the model spends:model_reasoning_effort = "high"low, medium, high, xhigh, and since Codex 0.154 max, which is passed through to the backend unchanged (tested on gpt-6-astra). Pick one from the model's supported_reasoning_levels, or leave the key out to use the model's default_reasoning_level. Codex 0.153 and earlier reject max as an unknown value; upgrade Codex to use it.codex doctor reports what Codex loaded and whether it can reach the provider. The auth section should show that the provider's environment variable exists. The reachability section probes base_url plus /models and reports reachable when the pairing is correct.codex in a shell where KIE_API_KEY is set and send a message.Model metadata for '…' not found. Defaulting to fallback metadata.. That means the slug is not in Codex's bundled model table, which is true for every KIE slug. The session runs normally.apikey. KIE returns 401. Put the key in Authorization: Bearer.base_url. Codex appends /responses itself, so a base_url ending in /responses becomes /responses/responses.model must be a slug from the listing.model_provider and model_providers outside the user-level config, so a provider in the project's .codex/config.toml is silently skipped.openai, ollama and lmstudio cannot be overridden; rename the table.env_key. It takes the name of an environment variable. The key lives in that variable, not in the config file.setx does not affect the current window. It applies to windows opened afterwards. Set $env: as well to use it right away.curl. It is an alias for Invoke-WebRequest and does not accept these arguments. Use curl.exe.