Providers and keys

Every AI provider key the CLI recognises, and what it writes instead.

AI/LLM: this page is available in plain markdown at /docs/resources/ai-gateway/providers.md

A provider's API key can only be minted by that provider. What we can do is recognise that your project is asking for one and answer it with the gateway, which reaches the same models.

npx extraorbital add openai
✓ Provisioned openrouter/default (small models · $5.00 allowance)
✓ Wrote 4 variables to .env

  OPENROUTER_BASE_URL, OPENROUTER_API_KEY, OPENAI_BASE_URL, OPENAI_API_KEY

✗ openai — an OpenAI key cannot be provisioned directly

  OpenAI models are served through the AI Gateway. OPENAI_BASE_URL and
  OPENAI_API_KEY now point at it, so your OpenAI SDK works unchanged — prefix
  model ids with the author, e.g. openai/<model>.

Exit code 8. The credentials are on disk and your code runs; the non-zero code is there because the thing you literally asked for is not what you got, and a script should be able to notice that without parsing text.

Every recognised key

ProviderRecognised keysModel idsAlso written
OpenAIOPENAI_API_KEYopenai/…OPENAI_BASE_URLOPENAI_API_KEY
AnthropicANTHROPIC_API_KEYANTHROPIC_AUTH_TOKENanthropic/…, ~anthropic/…ANTHROPIC_BASE_URLANTHROPIC_API_KEY
Google GeminiGEMINI_API_KEYGOOGLE_GENERATIVE_AI_API_KEYGOOGLE_API_KEYgoogle/…Nothing — the gateway does not speak this API
xAIXAI_API_KEYGROK_API_KEYx-ai/…XAI_BASE_URLXAI_API_KEY
MistralMISTRAL_API_KEYmistralai/…MISTRAL_BASE_URLMISTRAL_API_KEY
DeepSeekDEEPSEEK_API_KEYdeepseek/…DEEPSEEK_BASE_URLDEEPSEEK_API_KEY
Meta LlamaLLAMA_API_KEYmeta-llama/…, meta/…Nothing — the gateway does not speak this API
QwenDASHSCOPE_API_KEYQWEN_API_KEYqwen/…Nothing — the gateway does not speak this API
MoonshotMOONSHOT_API_KEYmoonshotai/…MOONSHOT_BASE_URLMOONSHOT_API_KEY
Z.aiZAI_API_KEYZHIPUAI_API_KEYz-ai/…Nothing — the gateway does not speak this API
MiniMaxMINIMAX_API_KEYminimax/…Nothing — the gateway does not speak this API
Nous ResearchNOUS_API_KEYnousresearch/…Nothing — the gateway does not speak this API
CohereCOHERE_API_KEYCO_API_KEYcohere/…Nothing — the gateway does not speak this API
PerplexityPERPLEXITY_API_KEYPPLX_API_KEYperplexity/…PERPLEXITY_BASE_URLPERPLEXITY_API_KEY
GroqGROQ_API_KEYGROQ_BASE_URLGROQ_API_KEY
Together AITOGETHER_API_KEYTOGETHER_BASE_URLTOGETHER_API_KEY
Fireworks AIFIREWORKS_API_KEYFIREWORKS_BASE_URLFIREWORKS_API_KEY
CerebrasCEREBRAS_API_KEYCEREBRAS_BASE_URLCEREBRAS_API_KEY
Amazon BedrockAWS_BEARER_TOKEN_BEDROCKamazon/…Nothing — the gateway does not speak this API

The Also written column is the difference that matters. OpenRouter speaks the OpenAI and Anthropic wire protocols, so for those providers we can write their own variable names pointed at the gateway and nothing in your code has to change. For Gemini, Cohere and Bedrock it speaks neither — writing a gateway key into GEMINI_API_KEY would produce a variable that looks right and fails on the first call, so we write nothing and say so.

Those models are still reachable. Call them through the gateway with an OpenAI-compatible client or the Vercel AI SDK, which has no such limit.

What autopilot does

extraorbital provision reads the same list. A project declaring GEMINI_API_KEY in its .env.example gets one gateway resource, an explanation, and exit 8:

Provisioning 2 resources for .

  openrouter  GEMINI_API_KEY · declared in .env.example · via the AI Gateway
  mongo       MONGODB_URI · declared in .env.example

✓ Provisioned openrouter/default
✓ Provisioned mongo/default

✗ GEMINI_API_KEY — cannot be provisioned

  Google Gemini models are served through the AI Gateway, which does not speak
  Google Gemini's own API. Call them through the gateway with an
  OpenAI-compatible client or the Vercel AI SDK.

Several providers in one project collapse onto one gateway key rather than one each — the key is not per-vendor, so neither is the resource.

What gets written where

The fenced block records which providers it was written for, so extraorbital check --fix rewrites the same set rather than dropping the compat variables:

.env
# >>> extraorbital resource=openrouter project=cosmic-otter slug=default compat=openai
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
OPENROUTER_API_KEY=sk-or-v1-9c4e17b2…
OPENAI_BASE_URL=https://openrouter.ai/api/v1
OPENAI_API_KEY=sk-or-v1-9c4e17b2…
# <<< extraorbital resource=openrouter

Both _API_KEY variables hold the same secret. That is not a mistake: there is one key, and OPENAI_API_KEY is a second name for it that the OpenAI SDK knows to read.

If your project already sets one of these to a placeholder, the CLI comments that line out — dotenv keeps the first definition it sees, so an unfilled OPENAI_API_KEY= above the block would otherwise win over the credential below it.

Next

  • Models — what each provider offers, with prices
  • SDK recipes — the code for each