> ## Documentation Index
> Fetch the complete documentation index at: https://docs.barndoor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Connecting Your Tools to the LLM Gateway

> Grab your API key, model route name, and gateway endpoint from the Barndoor portal, then point Cursor, Claude Code, Codex, or the OpenAI / Anthropic SDKs at the gateway.

<Info>
  This page is for developers. It assumes an admin has already configured a provider and at least one model — if **Available Models** is empty for you, ask your admin to work through the [Quickstart Guide](/how-tos/llm-gateway-quickstart) first.
</Info>

## What You Need

Every tool below needs the same three values, all of which live in **Settings → My Models** in the Barndoor portal:

| Value                    | Looks like                                   | Where to get it                                                                                                                 |
| ------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **API key**              | `bd-…`                                       | [app.barndoor.ai/settings/models?section=api-keys](https://app.barndoor.ai/settings/models?section=api-keys) → **Create Key**   |
| **Model route name**     | `gpt-4o-mini`, `claude-sonnet-5`             | [app.barndoor.ai/settings/models?section=models](https://app.barndoor.ai/settings/models?section=models) → **Available Models** |
| **LLM Gateway endpoint** | `https://app.barndoor.ai/api/llm-gateway/v1` | [app.barndoor.ai/settings/models?section=endpoint](https://app.barndoor.ai/settings/models?section=endpoint)                    |

<Frame>
  <img src="https://mintcdn.com/barndoor/x6czZKU8D69Pp3tU/images/llm-gateway/08-my-models-page.png?fit=max&auto=format&n=x6czZKU8D69Pp3tU&q=85&s=b0724ecf512d586c5af9898158c7647f" alt="Settings → My Models page showing the endpoint card, API keys table, and available models" width="1101" height="1025" data-path="images/llm-gateway/08-my-models-page.png" />
</Frame>

<Steps>
  <Step title="Create an API key">
    Open [**Settings → My Models → My API Keys**](https://app.barndoor.ai/settings/models?section=api-keys) and click **Create Key**. Give it a descriptive name (for example `Cursor on laptop`) and click **Create**.

    The dialog shows a `bd-…` token — **copy it now**. Barndoor only stores a one-way hash of the key, so the raw value cannot be shown again.

    <Frame>
      <img src="https://mintcdn.com/barndoor/R2cAUz0zJ6SKh319/images/llm-gateway/01-create-api-key.png?fit=max&auto=format&n=R2cAUz0zJ6SKh319&q=85&s=283c9fba5e070a0fe7aa9a2cb47bc081" alt="Create API Key dialog in the Barndoor portal" width="503" height="273" data-path="images/llm-gateway/01-create-api-key.png" />
    </Frame>
  </Step>

  <Step title="Copy a model route name">
    Under [**Available Models**](https://app.barndoor.ai/settings/models?section=models), the portal lists every model your admin has enabled and that your access policies allow. Use the name exactly as shown:

    * **Model routes** (`gpt-4o-mini`, `claude-sonnet-5`, …) — use the plain name in the `model` field of your request.
    * **Standalone models** — use the `provider/model` form (for example `openai/gpt-4o-mini`).

    See [Model Naming](/how-tos/llm-gateway-quickstart#model-naming) for how the gateway resolves each form.
  </Step>

  <Step title="Copy your gateway endpoint">
    The [**LLM Gateway Endpoint**](https://app.barndoor.ai/settings/models?section=endpoint) card shows your base URL — it looks like `https://app.barndoor.ai/api/llm-gateway/v1`.

    <Frame>
      <img src="https://mintcdn.com/barndoor/R2cAUz0zJ6SKh319/images/llm-gateway/02-endpoint-card.png?fit=max&auto=format&n=R2cAUz0zJ6SKh319&q=85&s=78167b24f32ab874bc8be0ea01c20cb2" alt="LLM Gateway Endpoint card on the Settings → My Models page" width="1006" height="170" data-path="images/llm-gateway/02-endpoint-card.png" />
    </Frame>

    <Note>
      OpenAI-style clients take the `/v1` form. Anthropic-style clients (the Anthropic SDK, Claude Code) append `/v1` themselves — give those the bare `https://app.barndoor.ai/api/llm-gateway` form.
    </Note>
  </Step>

  <Step title="Confirm all three work">
    Before configuring a tool, try all three from a shell. This separates auth problems from model-name problems, which look alike once an editor is in the middle:

    ```bash theme={null}
    curl https://app.barndoor.ai/api/llm-gateway/v1/chat/completions \
      -H "Authorization: Bearer bd-…" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": "Say hello"}]
      }'
    ```

    A `401` means the key or URL is wrong; a `404` means the model route name is wrong. More request shapes — streaming, embeddings, Anthropic Messages — are in [Sending Requests](/how-tos/llm-gateway-quickstart#sending-requests).
  </Step>
</Steps>

<Warning>
  Treat `bd-…` keys like passwords. Use environment variables (not source control) to store them in your apps and editor configs.
</Warning>

<Info>
  **Self-hosted and private-cloud deployments:** if Barndoor is running on your own infrastructure, swap `app.barndoor.ai` for your organization's portal hostname everywhere on this page. The path (`/api/llm-gateway/v1`) is the same.
</Info>

***

## Connect Your Tools

<AccordionGroup>
  <Accordion title="OpenAI Python SDK" icon="python">
    ```python theme={null}
    from openai import OpenAI

    client = OpenAI(
        base_url="https://app.barndoor.ai/api/llm-gateway/v1",
        api_key="bd-…",
    )

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": "Hello, gateway!"}],
    )
    print(response.choices[0].message.content)
    ```

    Streaming, function calling, embeddings, and the Responses API all work the same way as against OpenAI directly.
  </Accordion>

  <Accordion title="OpenAI Node SDK" icon="js">
    ```ts theme={null}
    import OpenAI from "openai";

    const client = new OpenAI({
      baseURL: "https://app.barndoor.ai/api/llm-gateway/v1",
      apiKey: process.env.BARNDOOR_API_KEY,
    });

    const response = await client.chat.completions.create({
      model: "gpt-4o-mini",
      messages: [{ role: "user", content: "Hello, gateway!" }],
    });
    console.log(response.choices[0]?.message?.content);
    ```
  </Accordion>

  <Accordion title="Anthropic SDK" icon="brain">
    ```python theme={null}
    import anthropic

    client = anthropic.Anthropic(
        base_url="https://app.barndoor.ai/api/llm-gateway",
        api_key="bd-…",
    )

    message = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=256,
        messages=[{"role": "user", "content": "Hello"}],
    )
    print(message.content[0].text)
    ```

    <Note>
      The Anthropic SDK appends `/v1/messages` to `base_url` itself, so the base URL should *not* include `/v1`.
    </Note>
  </Accordion>

  <Accordion title="Claude Code" icon="terminal">
    Claude Code talks to the gateway via `ANTHROPIC_BASE_URL`. The exact env-var setup depends on which kind of Anthropic provider your admin configured — a **shared API key** provider (everyone bills against one Anthropic key) or an **OAuth passthrough** provider (each developer bills against their personal Claude subscription). See [Step 1 → Anthropic OAuth passthrough](/how-tos/llm-gateway-quickstart#anthropic-oauth-passthrough-claude-code-subscribers) for the admin side.

    <Note>
      Claude Code appends `/v1/messages` to `ANTHROPIC_BASE_URL` itself, so the base URL must **not** include `/v1`. If you copied the URL from **Settings → My Models**, strip the trailing `/v1`.
    </Note>

    <Tabs>
      <Tab title="Shared API-key provider">
        Use when the admin set up an Anthropic provider that authenticates upstream with a centralized API key.

        ```bash theme={null}
        export ANTHROPIC_BASE_URL="https://app.barndoor.ai/api/llm-gateway"
        export ANTHROPIC_AUTH_TOKEN="bd-…"          # your LLM Gateway key from Settings → My Models
        export ANTHROPIC_MODEL="claude-sonnet-5"   # a model or route alias enabled in My Models
        export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
        claude
        ```

        Claude Code sends `bd-…` as `Authorization: Bearer`. The gateway authenticates the request with that key, then uses the admin-stored Anthropic API key to call Anthropic.

        <Note>
          **Admins can issue keys on someone's behalf** from **LLM Management → API Keys**, assigned to a specific user, to a group, or to neither — a key with no assignee works for anyone in the organization who holds it.

          Prefer a per-user or per-group key. An unassigned key carries no user identity, so per-user spend drill-down has nothing to attribute traffic to, and `user`-scoped model access policies can never match it. A group-assigned key keeps group-scoped policies working while still being one key for many people.
        </Note>

        <Warning>
          `ANTHROPIC_AUTH_TOKEN` takes the **bare key** — `bd-…`, not `x-api-key: bd-…`. The `x-api-key:` prefix belongs only in `ANTHROPIC_CUSTOM_HEADERS`, and only in the OAuth passthrough setup. Mixing the two produces a `401` because the gateway hashes the whole string as if it were a key.
        </Warning>

        Without `ANTHROPIC_MODEL`, Claude Code requests its default Anthropic model IDs (for example `claude-opus-4-8`, `claude-haiku-4-5`), which then must be enabled in **Settings → My Models** under those exact names. Setting `ANTHROPIC_MODEL` to one of your [Model Routes](/how-tos/llm-gateway-quickstart#step-5-define-model-routes) aliases avoids that dependency, and `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1` populates the `/model` picker from the gateway's `/v1/models`. That applies to **this** mode only — in OAuth passthrough Claude Code doesn't look models up, so the picker stays on its built-in names no matter what the flag is set to.

        <Note>
          This mode requires every model you request to resolve to a provider with a **stored credential** (shared Anthropic API key, Bedrock, …). If a request lands on an **OAuth passthrough** provider, the gateway rejects it with `401 — Anthropic provider requires an incoming Claude OAuth bearer token`; switch to the OAuth passthrough setup for those routes.
        </Note>
      </Tab>

      <Tab title="OAuth passthrough provider">
        Use when the admin set up an **Anthropic OAuth passthrough** provider — every request bills against the user's personal Claude subscription. Claude Code already attaches your logged-in OAuth bearer in `Authorization`, so Barndoor's gateway key has to go in a separate `x-api-key` header so the two don't collide:

        ```bash theme={null}
        export ANTHROPIC_BASE_URL="https://app.barndoor.ai/api/llm-gateway"
        unset  ANTHROPIC_API_KEY
        unset  ANTHROPIC_AUTH_TOKEN
        export ANTHROPIC_CUSTOM_HEADERS="x-api-key: bd-…"   # your LLM Gateway key from Settings → My Models
        export ANTHROPIC_MODEL="claude-opus-4-8"            # a model or route alias enabled in My Models
        claude
        ```

        Make sure you're logged into Claude (`claude /login` if not). Claude Code refreshes the `sk-ant-oat…` OAuth bearer for you and the gateway forwards it verbatim to Anthropic. Set `ANTHROPIC_MODEL` to whichever alias you've configured in [Model Routes](/how-tos/llm-gateway-quickstart#step-5-define-model-routes) — the `ANTHROPIC_DEFAULT_*_MODEL` variables only apply to provider configs (Bedrock, Vertex, …), not `ANTHROPIC_BASE_URL` gateways. `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` has no effect in this mode — Claude Code makes no startup `/v1/models` call when it authenticates by OAuth passthrough, so the `/model` picker stays on its built-in names and `ANTHROPIC_MODEL` is what actually decides the route.
      </Tab>
    </Tabs>

    <Tip>
      **Verify your env before launching `claude`.** A wrong combination is the most common setup pitfall, and the failure mode is often a silent retry rather than a useful error.

      ```bash theme={null}
      env | grep -E '^ANTHROPIC_|^CLAUDE_CODE_'
      ```

      | Setup             | Expect to see                                                  | Expect to be absent                                                                     |
      | ----------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
      | Shared API key    | `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN` (bare `bd-…` key) | `ANTHROPIC_CUSTOM_HEADERS`, `ANTHROPIC_API_KEY`                                         |
      | OAuth passthrough | `ANTHROPIC_BASE_URL`, `ANTHROPIC_CUSTOM_HEADERS`               | `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY`, `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` |

      Then confirm the key and base URL work before launching `claude` — this isolates auth problems from model-name problems:

      ```bash theme={null}
      curl "$ANTHROPIC_BASE_URL/v1/models" -H "Authorization: Bearer bd-…"
      ```

      A model list means auth is good (any remaining failure is model naming); a `401` means the key or URL is wrong.
    </Tip>

    <Tip>
      **Spot-check which route served the request.** The `model` field in the Anthropic response always echoes back the model that actually answered — so if you've configured a failover alias like `claude-opus-4-8` with an Anthropic OAuth primary and a Bedrock fallback, an Anthropic-style ID confirms the primary served it, and a Bedrock-style ID (e.g. `us.anthropic.claude-opus-4-8`) means failover engaged. This works on every response, success or not — the [observability headers](/how-tos/llm-gateway-quickstart#observability-headers) carry the same info on successful chat / messages responses.
    </Tip>

    <AccordionGroup>
      <Accordion title="`jq: Could not open file ~/.claude/.credentials.json`" icon="circle-question">
        Recent Claude Code versions don't expose a plaintext credentials file. If you have a shell snippet that pipes `jq` over that path to extract an OAuth token, remove it — Claude Code handles the OAuth token internally and your only job is to set the env vars in the tabs above.
      </Accordion>
    </AccordionGroup>
  </Accordion>

  <Accordion title="Cursor IDE" icon="code">
    Cursor lets you add custom OpenAI-compatible providers under **Settings → Models → OpenAI API Key → Override OpenAI Base URL**:

    1. Toggle **Custom OpenAI API Key**.
    2. Set the base URL to `https://app.barndoor.ai/api/llm-gateway/v1`.
    3. Paste your `bd-…` key as the API key.
    4. Add the model names (for example `gpt-4o-mini`, `claude-sonnet-5`) that you want Cursor to be able to select.

    <Frame>
      <img src="https://mintcdn.com/barndoor/R2cAUz0zJ6SKh319/images/llm-gateway/09-cursor-custom-openai.png?fit=max&auto=format&n=R2cAUz0zJ6SKh319&q=85&s=71834110e909a55f5d23fbfac1f4a0b8" alt="Cursor Settings → Models with the Barndoor LLM Gateway configured as a custom OpenAI base URL" width="894" height="379" data-path="images/llm-gateway/09-cursor-custom-openai.png" />
    </Frame>
  </Accordion>

  <Accordion title="Codex CLI / Desktop" icon="terminal">
    Codex uses the OpenAI **Responses** API (`wire_api = "responses"`), not Chat Completions. Point a custom provider at the gateway and keep `/v1` on the base URL — Codex appends `/responses` itself.

    ```toml theme={null}
    model_provider = "barndoor"
    model = "gpt-4o-mini"

    [model_providers.barndoor]
    name = "Barndoor"
    base_url = "https://app.barndoor.ai/api/llm-gateway/v1"
    wire_api = "responses"
    env_key = "BARNDOOR_API_KEY"
    ```

    ```bash theme={null}
    export BARNDOOR_API_KEY="bd-…"
    codex
    ```

    `env_key` is the environment variable *name*; the `export` is the secret value. A missing `/v1` produces `401 invalid JWT header: InvalidToken`.

    Full steps for CLI and Desktop, plus troubleshooting: **[Use Codex with the LLM Gateway](/how-tos/use-codex-with-llm-gateway)**.
  </Accordion>

  <Accordion title="LangChain" icon="link">
    ```python theme={null}
    from langchain_openai import ChatOpenAI

    llm = ChatOpenAI(
        model="gpt-4o-mini",
        base_url="https://app.barndoor.ai/api/llm-gateway/v1",
        api_key="bd-…",
    )
    print(llm.invoke("Hello, gateway!").content)
    ```

    `ChatAnthropic`, `OpenAIEmbeddings`, and the rest of the OpenAI-style integrations behave the same way — set `base_url`/`anthropic_api_url` and `api_key`.
  </Accordion>

  <Accordion title="cURL / scripts" icon="terminal">
    Use any of the examples in [Sending Requests](/how-tos/llm-gateway-quickstart#sending-requests). For CI and shell scripts, export the URL and key once:

    ```bash theme={null}
    export BARNDOOR_BASE_URL="https://app.barndoor.ai/api/llm-gateway/v1"
    export BARNDOOR_API_KEY="bd-…"

    curl "$BARNDOOR_BASE_URL/models" -H "Authorization: Bearer $BARNDOOR_API_KEY"
    ```
  </Accordion>
</AccordionGroup>

***

## Related

* [Using the LLM Gateway](/how-tos/use-llm-gateway) — overview, architecture, and prerequisites
* [Quickstart Guide](/how-tos/llm-gateway-quickstart) — admin setup, request reference, and [troubleshooting](/how-tos/llm-gateway-quickstart#troubleshooting)
* [Use Codex with the LLM Gateway](/how-tos/use-codex-with-llm-gateway) — the full Codex CLI and Desktop walkthrough
* [Get the most out of your Claude subscription](/how-tos/llm-gateway-failover) — run Claude Code on your own Claude seat and fail over when you hit the cap
