## Quickstart

If your admin has already configured a provider and at least one model, you can be sending requests in two minutes.

1. **Get your API key**  
   Open **Settings → My Models** in the Barndoor portal and click **Create Key**. Copy the `bd-…` token immediately — you won’t be able to see it again.

2. **Find your endpoint**  
   On the same page, the **LLM Gateway Endpoint** card shows your base URL — it looks like `https://app.barndoor.ai/api/llm-gateway/v1`.

3. **Send a request**  
   ```bash
   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"}]
     }'
   ```
   Use a `model` name from the **Available Models** list — either a plain alias (`gpt-4o-mini`) or a provider-qualified name (`openai/gpt-4o-mini`).

The rest of this guide expands on each piece — admin setup, client integrations, advanced features, and troubleshooting.

---

## Admin: Configure the Gateway

Skip this section if your admin has already set up providers and models. Jump to **Get Your Endpoint and API Key**.

All admin configuration happens in **LLM Management** in the Barndoor portal — a single hub whose left-hand nav groups every piece of the gateway. Work top to bottom: provision your connections and models, mint keys, then layer on governance.

| Group | Section | What it configures |
| --- | --- | --- |
| **Connections** | **Credentials** | The actual upstream credentials (API key, AWS role, Vertex service account, etc.). |
| **Connections** | **Providers** | A named upstream that references one set of credentials and a model family. |
| **Models** | **Models** | The catalog of upstream models exposed via this provider. |
| **Models** | **Model Pricing** | Per-million-token input/output costs used for usage and budget reporting. |
| **Models** | **Model Routes** | The client-facing model name (for example `gpt-4o-mini`) and the ordered list of providers / upstream models it resolves to. |
| **Keys** | **API Keys** | `bd-…` keys issued on a user’s behalf — assigned to a user, a group, or neither (developers mint their own under **Settings → My Models**). |
| **Controls** | **Budgets**, **Rate Limits**, **Model Access** | Governance policies — token/spending budgets, RPM/TPM throttles, and model allow/denylists. Covered in **Configuring LLM Controls**.

Per-request usage and cost reporting live separately, under **Reporting → LLM Usage Dashboard**.

### Step 1: Add Provider Credentials

Most credentials live in **LLM Management → Credentials**, where you save reusable secrets that one or more providers can share. A few setups have their own flow:

- **Anthropic OAuth passthrough** is configured exclusively on the **Providers** tab (there are no Credentials to save) — see **Anthropic OAuth passthrough** below.
- **AWS Bedrock** and **Google Vertex AI** can be set up from either tab — pre-create reusable Credentials and attach them on the Providers tab, or configure them inline when you create the Provider. The Providers-tab flow walks you through a guided checklist and is the easiest first-time path.

**OpenAI / Anthropic / Azure OpenAI (API key)**

The simplest case — pick the provider and paste a key.

1. Click **Add Credentials**. The dialog opens with a **Model Provider** searchable picker at the top; everything else is disabled until you make a selection.
2. Pick the provider (OpenAI, Anthropic, Azure OpenAI, etc.). The **Name** field auto-fills with a sensible default (you can edit it), the **Base URL** populates with the catalog default, and provider-specific fields appear (for example Azure’s `endpoint_mode` and `api_version`).
3. Paste the API key.
4. Save. The key is stored in Barndoor’s encrypted secret store and is never returned to the browser.

Multiple providers can reference the same saved credential — useful for sharing one OpenAI key across several routes, or pinning a specific provider per team via **Model Routes**.

**AWS Bedrock**  
Bedrock supports three authentication methods. **IAM role federation is the recommended production setup**; the others are useful for pilots or environments that can’t grant cross-account roles.

| Method | When to use |
| --- | --- |
| **AWS IAM Role** | Production. Barndoor assumes a role in your AWS account at request time — no long-lived secrets stored. |
| **Static AWS Keys** | Pilot or fallback. Access key + secret key (+ optional session token). |
| **Bedrock API Key** | If your team prefers AWS’s first-party Bedrock API key feature. |

Fields common to every method:

- **AWS Region** — where Barndoor sends Bedrock Runtime requests (free text, e.g. `us-east-1`). Make sure the models you want are enabled in that region in AWS.
- **Bedrock API Family** — pick **Claude / Anthropic Messages** for Claude models on Bedrock, or **Bedrock Converse** for the broader Converse-API model set (Llama, Titan, etc.).

### Setting up IAM Role federation

The Providers tab walks you through this end-to-end with a **Bedrock setup checklist** — recommended for first-time setup.

1. Open **Providers → Add Provider → AWS Bedrock → Connect**.
2. Fill in **AWS Region**, **Customer IAM Role ARN**, and **Bedrock API Family**. Barndoor auto-generates an **External ID** and shows you its own **Barndoor Principal ARN** for this environment in the same dialog.
3. Click **Copy trust policy** — Barndoor builds the JSON template for you, pre-filled with its principal ARN and your external ID.
4. In **AWS IAM**, create (or update) the role you named in step 2 and paste the copied trust policy into its trust relationship.
5. Grant the role permission to invoke Bedrock — at minimum `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream`. (The AWS-managed `AmazonBedrockReadOnly`-style policies do **not** include these actions.) For a POC, `Resource: "*"` is fine; **for production, narrow `Resource` to the specific Bedrock model ARNs / inference profiles and regions your team actually routes to.**
6. Back in Barndoor, click **Validate role access**. The portal attempts the exact STS assume-role chain it uses at runtime and surfaces the AWS error verbatim if something’s off — iterate on the trust policy / role permissions until it validates.
7. Click **Save**. The credentials are stored and the **AWS Trust Info** dialog opens; you can reopen it anytime from the credential’s row menu to recheck the principal or external ID.

### Setting up Static AWS Keys

Paste the **AWS Access Key ID**, **AWS Secret Access Key**, and an optional **AWS Session Token** (if you’re using temporary credentials). Region and Bedrock API Family work the same as the role flow. There’s no Validate button for this mode — failures show up on the first real request.

### Setting up a Bedrock API Key

Paste the **Bedrock API Key** issued by the AWS Bedrock console. Region and Bedrock API Family work the same as above.

If you want to expose Bedrock from multiple regions or model families, create one Provider per (region, family) combination and let **Model Routes** decide which alias points where.

### Google Vertex AI

Vertex supports three authentication methods. Pick the one that matches your GCP posture:

| Method | When to use |
| --- | --- |
| **Workload Identity / ADC** | The easiest path. Barndoor uses its platform-managed Google identity to authenticate; you grant that identity Vertex access on your project. No keys to paste. |
| **Service Account Impersonation** | Recommended for production. Create a service account in your GCP project with Vertex permissions, then grant Barndoor’s runtime principal `roles/iam.serviceAccountTokenCreator` on it. Barndoor impersonates your service account at request time. |
| **Service Account Key** | Pilot or fallback. Paste a service-account email + private key (the contents of a downloaded JSON key file). |

Fields common to every method:

- **GCP Project ID** — your project.
- **Vertex AI Location** — region (default `us-central1`).
- **Vertex API Family** — **Gemini Generate Content** for Gemini models, or **Claude / Anthropic Messages** for Claude on Vertex.

## Setup steps

1. In the portal, pick the auth method and fill in the fields.
2. In your GCP project, enable the **Vertex AI API** and any partner-model access (e.g. Claude on Vertex requires explicit model enablement).
3. Grant **`roles/aiplatform.user`** (or a more specific Vertex role) on the project to whichever principal will actually call Vertex — Barndoor’s runtime identity (Workload Identity / ADC), your target service account (impersonation), or the key’s service account.
4. For Service Account Impersonation only: grant **`roles/iam.serviceAccountTokenCreator`** on your target service account to Barndoor’s runtime principal.
5. Click **Validate Vertex Access**. Barndoor fetches a token via your chosen auth method and asks Vertex about a model in your chosen API family — confirming end-to-end that both auth and model access work.

The **Service Account Key** dialog asks for the **email** and **private key** as separate fields (the two values inside a downloaded JSON key file), plus an optional **Token URI**. Paste them into the form fields — raw JSON file upload is not supported.

**Streaming on Vertex Gemini is not yet supported by the gateway** — Gemini Generate Content responses come back non-streaming. Streaming on Claude on Vertex (`Claude / Anthropic Messages` family) works normally.

### Anthropic OAuth passthrough (Claude Code subscribers)

Use this mode when your developers use **Claude Code** with personal or subscription Claude accounts and you want each request to bill against that user’s Anthropic subscription rather than a shared API key. Instead of storing a Claude API key, Barndoor authenticates _itself_ with the standard `bd-…` gateway API key and **forwards each caller’s Claude OAuth token** (`sk-ant-oat…`) to Anthropic on the upstream request.

Anthropic OAuth passthrough is configured on the **Providers** tab, not Credentials — there’s nothing to save in Credentials.

## What callers send

Every request carries **two** headers:

| Header | Value | Purpose |
| --- | --- | --- |
| `x-api-key` | `bd-…` | Authenticates the caller to the Barndoor Gateway. |
| `Authorization` | `Bearer sk-ant-oat…` | The caller’s Claude OAuth token, forwarded to Anthropic verbatim. |

Claude Code emits both automatically — see the **Claude Code accordion** under Connect Your Tools for the exact env-var setup.

## Smoke-test with curl

To verify the dual-header path end-to-end without Claude Code:

```bash
export BARNDOOR_LLM_GATEWAY_ENDPOINT="https://app.barndoor.ai/api/llm-gateway/v1"
export BD_API_KEY="bd-…"
export CLAUDE_OAUTH="sk-ant-oat…"   # from your local Claude login

curl -i "$BARNDOOR_LLM_GATEWAY_ENDPOINT/messages" \
  -H "content-type: application/json" \
  -H "x-api-key: $BD_API_KEY" \
  -H "authorization: Bearer $CLAUDE_OAUTH" \
  -d '{
    "model": "claude-opus-4-8",
    "max_tokens": 32,
    "messages": [{"role": "user", "content": "Say pong."}]
  }'
```

A `200` with a normal Anthropic response body confirms both headers flowed correctly. A `401` typically means one of the two headers is missing or malformed.

## Limitations to know about

- **Endpoint scope:** OAuth tokens are forwarded only on **`POST /v1/messages`** (and Claude Code’s pre-flight `/v1/messages/count_tokens`). Hitting `/v1/chat/completions` against an Anthropic OAuth provider returns `401` with a message asking the caller to use the Messages endpoint.
- **Token management:** Barndoor never stores or refreshes Claude OAuth tokens. Token expiry and refresh are handled entirely by Claude Code on the caller’s machine.
- **Failover:** Missing-OAuth-token errors are treated as caller errors (`401`), not upstream failures, so they don’t trigger failover to other routes for the same alias.

## Pairing OAuth with a fallback (worked example)

A common production setup is to put OAuth passthrough first and an AWS Bedrock provider second on the same alias, so Claude OAuth absorbs everyday traffic and Bedrock takes over if Anthropic is degraded.

1. Create the **Anthropic Claude OAuth** provider as described above.
2. Create an **AWS Bedrock** provider.
3. In **Model Routes**, make a single alias (e.g. `claude-opus-4-8`) with two entries:
   - Entry 1 — provider: **Anthropic Claude OAuth**, upstream model: the Anthropic public API model id (e.g. `claude-opus-4-8`).
   - Entry 2 — provider: **AWS Bedrock**, upstream model: the Bedrock model id (e.g. `us.anthropic.claude-opus-4-8`).
4. Callers send requests for `claude-opus-4-8`. The gateway tries OAuth first, and falls over to Bedrock on a failover-eligible upstream error.

Provider credentials are encrypted at rest and never leave Barndoor in the clear once saved. When you rotate a credential, update it in Barndoor so the gateway picks up the new value on the next request.

### Step 2: Create a Provider

A **Provider** is the named upstream that uses one credential. From the **Providers** tab, click **Add Provider** to open the **Add a Provider** card grid:

1. Filter the catalog with **All / Official / Custom** at the top. **Official** is Barndoor’s vetted catalog (OpenAI, Anthropic, AWS Bedrock, Google Vertex, Azure OpenAI, and many more). **Custom** is for OpenAI-compatible providers you wire up yourself.
2. Click the card for the upstream you want to add — Anthropic shows two cards (the standard API-key path and the **Anthropic OAuth** path), most others show one. A dialog opens with the catalog defaults pre-filled.
3. Pick the **Credentials** to use — either an existing saved credential from the dropdown, or **Enter API key on this provider** to set up an inline credential as part of the save.
4. Give the provider a friendly **Name** (this is what shows up in audit logs and response observability headers).
5. Optionally override the **Base URL**.

You can create multiple providers backed by the same vendor.

### Step 3: Enable Models

Open the **Models** tab and toggle on every upstream model your org should be able to call. These are the _upstream_ model identifiers.

### Step 4: Configure Model Pricing (optional)

Barndoor already costs every request against its **managed default catalog** of market-rate prices, so the cost-aware features below work without any setup:

- **Spending budgets** in **LLM Controls**
- **`estimated_cost`** values recorded on every per-request audit event
- **Per-team / per-user / per-model attribution** in the **Reporting → LLM Usage Dashboard**

### Step 5: Define Model Routes

This is the most important step. A **Model Route** maps a _client-facing_ model name to one or more (provider, upstream model) targets in priority order. It’s where you turn a logical name like `gpt-4o-mini` into a routing decision.

1. Open **Model Routes** and click **Create Route**.
2. Set the **Route Name** clients will use, e.g. `gpt-4o-mini` or `team-coding-model`. This is the name callers put in the `model` field.
3. Pick a **Provider** and check one or more of its **Provider Models** to use as targets. The first target is the primary; the rest are failover targets used if the primary returns a 5xx, network error, or exhausted 429.
4. Configure per-target **429 retry** behavior (optional).

Any route you create here is **bare-callable** — clients can use the bare name (`gpt-4o-mini`) directly. (Models you merely toggle on in the **Models** tab without giving them a route are only reachable via the provider-prefixed form, `openai/gpt-4o-mini`.)

### Step 6: Add Governance (optional)

Once routes are live, you’ll likely want to layer on usage policies — token budgets, rate limits, and model access. All of these live under the **Controls** group of **LLM Management** (Budgets, Rate Limits, Model Access).

- **Token Budgets** — daily / weekly / monthly token (and optional spending) caps with alert thresholds.
- **Rate Limits** — RPM / TPM caps.
- **Model Access Policies** — allowlist or denylist specific models, providers, or upstream-model combinations.

### Step 7: Create an Org API Key (optional)

If you need a service-account-style key not tied to a single user, use **LLM Management → API Keys → Create Key**.

## User: Get Your Endpoint and API Key

1. **Open My Models**  
   In the Barndoor portal, navigate to **Settings → My Models**. The top of the page shows your **LLM Gateway Endpoint** — copy this base URL.

2. **Create an API key**  
   Under **My API Keys**, click **Create Key**, give it a descriptive name (e.g. `Cursor on laptop`), and click **Create**. The dialog shows a `bd-…` token — **copy it now**.

3. **Pick a model**  
   The **Available Models** section lists every model your admin has enabled and that your access policies allow.

| Model routes | Standalone models |
   | --- | --- |
   | `gpt-4o-mini`, `claude-sonnet-5`, … | use the `provider/model` form (e.g. `openai/gpt-4o-mini`). |

Treat `bd-…` keys like passwords. Use environment variables to store them in your apps and editor configs.

## Sending Requests

The gateway speaks two API dialects on the same port:

| Endpoint | Use it from |
| --- | --- |
| `POST /v1/chat/completions` | OpenAI SDKs, LangChain, LlamaIndex, most chatbots |
| `POST /v1/completions` | Legacy OpenAI text-completion clients |
| `POST /v1/embeddings` | OpenAI / LangChain embeddings clients |
| `POST /v1/responses` | OpenAI Responses API clients |
| `POST /v1/messages` | Anthropic Messages clients (Claude Code) |
| `POST /v1/messages/count_tokens` | Anthropic clients that pre-flight token counts |
| `GET /v1/models` | Any client that lists models on startup |

Both `Authorization: Bearer <key>` and `x-api-key: <key>` headers are accepted.

## List Available Models

Enumerate what a key can call instead of hardcoding model names.

```bash
curl https://app.barndoor.ai/api/llm-gateway/v1/models -H "Authorization: Bearer bd-…"
```

### Streaming Chat Completion

Set `
