---
name: ai-gateway-fastapi
description: "Provisions one OpenAI-compatible API key that reaches every major model (OpenAI, Anthropic, Google, Meta, Mistral, DeepSeek…) for a FastAPI app with `npx extraorbital add ai` (no signup, no card) and wires it into FastAPI with `openai`. Use when a FastAPI project needs AI Gateway, an LLM, an OpenAI API key, an Anthropic API key, a Gemini key, OPENAI_API_KEY, ANTHROPIC_API_KEY or OpenRouter, or when OPENROUTER_API_KEY is missing or unset in .env."
---

# AI Gateway in FastAPI

<!-- Generated from ExtraOrbital's service registry by `pnpm skills:build` in platform/app. Edit the generator, not this file. -->

ExtraOrbital provisions one OpenAI-compatible API key that reaches every major model (OpenAI, Anthropic, Google, Meta, Mistral, DeepSeek…) in one command and writes the credentials into the project's env file. For anything this recipe does not cover, use the `extraorbital` skill or https://extraorbital.dev/llms.txt.

## 1. Provision

```bash
npx extraorbital add ai
```

Run it from the project root. It is idempotent (a second run returns the same resource) and writes to `.env.local` if the project has one, otherwise `.env`, keeping that file out of git. Add `--json` to parse the result; credential values are redacted there, and you should never print them either.

| Variable | |
| --- | --- |
| `OPENROUTER_BASE_URL` | OpenAI-compatible base URL |
| `OPENROUTER_API_KEY` | The key; spends from the team's budget |

Free on the Prototype plan: First $5.00 of small models.

## 2. Install the client

```bash
pip install pydantic-settings openai
```

## 3. Connect

`pydantic-settings` reads `.env` and `.env.local` itself; if `app/config.py` already exists, add the fields to its `Settings`.

**`app/config.py`**

```python
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    # ExtraOrbital writes .env.local when the project has one, else .env; the later file wins.
    model_config = SettingsConfigDict(env_file=(".env", ".env.local"), extra="ignore")

    OPENROUTER_API_KEY: str
    OPENROUTER_BASE_URL: str


settings = Settings()
```

**`app/ai.py`**

```python
from openai import AsyncOpenAI

from app.config import settings

ai = AsyncOpenAI(api_key=settings.OPENROUTER_API_KEY, base_url=settings.OPENROUTER_BASE_URL)
# Model ids carry the author prefix: openai/…, anthropic/…, google/…
AI_MODEL = "~openai/gpt-mini-latest"
```

## 4. Use it

**`app/api/ai_gateway.py`**

```python
from fastapi import APIRouter

from app.ai import AI_MODEL, ai

router = APIRouter()
# In app/main.py: from app.api import ai_gateway; app.include_router(ai_gateway.router)


@router.get("/api/ai-gateway")
async def check_ai_gateway():
    completion = await ai.chat.completions.create(
        model=AI_MODEL, messages=[{"role": "user", "content": "Say hello in five words."}]
    )
    return {"text": completion.choices[0].message.content}
```

## 5. Verify

```bash
npx extraorbital list        # the resource is listed as active
fastapi dev app/main.py
curl http://localhost:8000/api/ai-gateway
```

A JSON answer means the credentials, the client and the route all work. Delete the route afterwards if the app does not need it.

## Pitfalls

- No vendor's own key can be provisioned. `npx extraorbital add openai` (or an `.env.example` declaring `OPENAI_API_KEY`) provisions this gateway, points `OPENAI_BASE_URL`/`OPENAI_API_KEY` at it so existing code runs unchanged, and exits `8`: not a failure.
- `gpt-5.2` is not an id here; `openai/gpt-5.2` is. On the free Prototype plan a key reaches small models only; the list with prices is at https://extraorbital.dev/api/gateway/models.
- It also speaks the Anthropic Messages API and works with the Vercel AI SDK and LangChain: https://extraorbital.dev/docs/resources/ai-gateway/sdks.md
- Keep the key on the server.
- A blocking client (`boto3`, `stripe`) belongs in a plain `def` route, which FastAPI runs in a threadpool; in `async def` it stalls every other request.
- With `uv`, `uv add` the same packages instead of `pip install`.
- Exit code 3 means the account is past its free allowance: show the human the link the command printed and wait. Do not retry or work around it.

Docs: https://extraorbital.dev/docs/resources/ai-gateway.md
