Admin: Configure the Gateway
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: connect a provider, enable models, give them route names, mint a key, send a test request, then layer on governance.
Step 1: Add Provider Credentials
Credentials are what authorize Barndoor against your upstream account. Save them once in LLM Management → Credentials and any number of providers can use them. You can also skip this step and create credentials inline while creating the provider in Step 2 — they’re saved to the Credentials section either way. The two OAuth passthrough providers store no credentials at all and are set up entirely on the Providers section:- Anthropic OAuth — see the Anthropic OAuth passthrough accordion below.
- OpenAI Codex OAuth — see Use Codex with the LLM Gateway.

API-key providers (OpenAI, Anthropic, Azure OpenAI, Google AI, and others)
API-key providers (OpenAI, Anthropic, Azure OpenAI, Google AI, and others)
- Click Add Credentials. The dialog opens with a Model Provider picker at the top; the rest of the form is disabled until you pick one.
- Pick the provider. The Base URL fills in with the catalog default, and any provider-specific fields appear.
- Give the credentials a Name (for example
Production Anthropic Key) — this is how you’ll find them when creating a provider. - Paste the API key.
- Click Create. The key is stored in Barndoor’s encrypted secret store and is never returned to the browser.
AWS Bedrock
AWS Bedrock
us-east-1). Make sure the models you want are enabled in that region in AWS.Setting up an AWS IAM Role
The dialog walks you through this with a Bedrock setup checklist.- Pick AWS IAM Role as the Bedrock Auth Method.
- Fill in AWS Region and your Customer IAM Role ARN. Barndoor generates an External ID and shows its own Barndoor Principal ARN for this environment in the same dialog.
- Click Copy trust policy — Barndoor builds the JSON for you, pre-filled with its principal ARN and your external ID.
- In AWS IAM, create (or update) the role you named in step 2 and paste the copied trust policy into its trust relationship.
- Grant the role permission to invoke Bedrock — at minimum
bedrock:InvokeModelandbedrock:InvokeModelWithResponseStream. (The AWS-managed read-only Bedrock policies do not include these actions.) For a proof of concept,Resource: "*"is fine; for production, narrowResourceto the specific Bedrock model ARNs / inference profiles and regions you route to. - Back in Barndoor, click Validate role access. The portal attempts the same assume-role chain it uses at runtime and shows the AWS error verbatim if something’s off — adjust the trust policy or role permissions until it validates.
- Click Create. The AWS Trust Info dialog opens; you can reopen it any time from the credentials’ row menu (AWS trust info) 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). 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.Google Vertex AI
Google Vertex AI
- GCP Project ID — your project.
- Vertex AI Location — the region (default
us-central1).
Setup steps
- Pick the auth method and fill in the fields.
- In your GCP project, enable the Vertex AI API and any partner-model access (for example, Claude on Vertex requires explicit model enablement).
- Grant
roles/aiplatform.user(or a narrower Vertex role) on the project to whichever principal actually calls Vertex — Barndoor’s runtime identity (Workload Identity / ADC), your target service account (impersonation), or the key’s service account. - For Service Account Impersonation only: grant
roles/iam.serviceAccountTokenCreatoron your target service account to Barndoor’s runtime principal. - Click Validate Vertex Access. Barndoor fetches a token with your chosen method and asks Vertex about a model, confirming that both auth and model access work.
response_format through the gateway yet. Streaming requests to a Gemini Generate Content provider are rejected with a 400. Claude on Vertex and the OpenAI-compatible family stream normally. For Gemini with streaming, use a Google AI (Gemini) provider instead.Microsoft Foundry
Microsoft Foundry
Anthropic OAuth passthrough (Claude Code subscribers)
Anthropic OAuth passthrough (Claude Code subscribers)
bd-… gateway API key and forwards the caller’s own Claude OAuth token (sk-ant-oat…) to Anthropic on the upstream request.Setup
- Go to Providers → Add Provider and pick the Anthropic OAuth card (one of the two Anthropic cards).
- Name the provider (for example
Anthropic via Claude OAuth). Credentials shows Claude OAuth passthrough — no stored credential, and no API key field appears. - Click Create, and enable the Claude models you want to expose.
- Add those models to a Model Route.
What callers send
Every request carries two headers:Smoke-test with curl
To verify the two-header path without Claude Code:200 with a normal Anthropic response body confirms both headers flowed correctly. A 401 means one of the two headers is missing or malformed.Limitations to know about
- Endpoint scope: the Claude OAuth token is forwarded only on
POST /v1/messages. A request that reaches an Anthropic OAuth provider through any other endpoint — for example/v1/chat/completions— fails with401and the messageAnthropic provider requires an incoming Claude OAuth bearer token. (/v1/messages/count_tokensis answered by the gateway itself and never reaches Anthropic.) - Token management: Barndoor never stores or refreshes Claude OAuth tokens. Expiry and refresh are handled by Claude Code on the developer’s machine.
- A missing token doesn’t fail over. It’s treated as a caller error (
401), not an upstream failure, so the gateway doesn’t move on to the route’s other targets.
Pairing OAuth with a fallback
A common production setup puts the OAuth provider first and a cheaper or shared provider second on the same route, so each developer’s subscription absorbs everyday traffic and the fallback takes over when the subscription hits its limit or Anthropic is degraded. Get the most out of your Claude subscription walks through that setup end to end.Step 2: Create a Provider
A Provider is a named upstream connection that uses one set of credentials. Open Providers and click Add Provider to open the Add a Provider card grid:- Search, or filter the catalog with All / Official / Custom. Official cards come from Barndoor’s provider catalog (see Supported Providers). The Custom Provider card connects any OpenAI-compatible endpoint you configure yourself.
- Click the card for the upstream you want. Anthropic shows two cards — the standard API-key card and Anthropic OAuth. A dialog opens with the catalog defaults filled in.
-
Give the provider a Name. Pick it with care: it appears in the providers list, in usage reports, and in the provider-prefixed model names callers can use (for example
OpenAI Prod/gpt-5.4-mini). - For AWS Bedrock, Google Vertex AI, and Microsoft Foundry, pick the provider’s API family — Bedrock API Family, Vertex API Family, or Model API Family. It decides which models this provider can serve. To use more than one family from the same account, create one provider per family, all using the same credentials.
- Pick the Credentials — a saved set from Step 1, or + Create new credentials to enter them here. New credentials are given a Credential name and saved to the Credentials section, where other providers can reuse them.
-
Review the provider settings:
- Click Create (Create and add route for AWS Bedrock). If Auto-Sync is Off, an Enable Models dialog opens next — continue with Step 3 there, or click Skip.
Provider health
Barndoor tracks whether each provider is reachable and serving, and shows it as a status pill on the provider’s row:
Step 3: Enable Models
A provider serves only the models enabled on it. If you skipped the Enable Models dialog, or want to change what’s enabled later, open the Models section: each provider is listed with its models, and you toggle on every upstream model your organization should be able to call (for examplegpt-5.4-mini, claude-sonnet-5, text-embedding-3-large). To add a model that isn’t in Barndoor’s catalog, type its exact upstream name as a custom model.
These are the upstream model identifiers — the names sent to the provider. An enabled model is immediately callable by its provider-prefixed name, <provider name>/<model> (for example OpenAI Prod/gpt-5.4-mini). To give it a plain name, add it to a route in Step 5.

Step 4: Configure Model Pricing (optional)
Barndoor already prices every request against its managed default catalog of market-rate prices, so the cost-aware features work without any setup:- Spending budgets in LLM Controls
- The estimated cost recorded for every request
- Per-team, per-user, and per-model cost on the Reporting → LLM Usage Dashboard
Step 5: Define Model Routes
This is the step that gives callers a stable model name. A Model Route maps a client-facing model name to one or more enabled provider models, tried in priority order.- Open Model Routes and click Create Route.
- Enter the Route Name callers will use, for example
gpt-5.4-miniorteam-coding-model. This is the value callers put in themodelfield. - Pick a provider in Browse provider and check one or more of its Provider Models. Switch Browse provider to add targets from other providers to the same route.
- Optionally open Advanced settings to set per-target Rate limit retries and Timeouts.
- Click Create Route.

Step 6: Create an API Key
To send a test request you need abd-… key. Either:
- Create your own under Settings → My Models → API Keys → Create Key, or
- Create one in LLM Management → API Keys → Create Key. Give it a Name, then optionally Assign to User or Assign to Group. Leave both unset for an organization-wide key — the usual choice for services and CI. Group members share group-scoped budgets, rate limits, and model access.
Step 7: Send a Test Request
List the models your key can call, then send a request to one of them:gpt-5.4-mini with a route name from Step 5 (or a provider/model name from Step 3). A 200 with a normal chat completion means the gateway is working end to end. The request shows up on Reporting → LLM Usage Dashboard. If it fails, see Troubleshooting.
Step 8: Add Governance (optional)
Once routes are live, layer on usage policies. They live under the Controls group of LLM Management and are enforced inside the gateway on every request, so they apply to every client and SDK alike.- Budgets — token and spending caps per period, with alert thresholds.
- Rate Limits — request and token throughput caps.
- Model Access — allow or deny specific models and routes for the organization, a group, a role, a user, or an API key.
Sending Requests
The gateway speaks two API dialects on the same base URL,https://app.barndoor.ai/api/llm-gateway/v1:
Authorization: Bearer bd-… or x-api-key: bd-…. When both headers are present the gateway reads the key from x-api-key, so Anthropic-compatible clients can pass a provider-side OAuth token in Authorization.
Request bodies can be up to 32 MB by default, enough for a full-context Claude Code conversation.
List Available Models
Enumerate what a key can call instead of hardcoding model names — the set changes as admins add providers, enable models, or adjust access policies./v1 form, the Anthropic client the bare one — it appends /v1 itself. Both are shown on the LLM Gateway Endpoint card under Settings → My Models → Gateway Endpoint for your own tenant.
The listing is filtered by the policies that apply to your key, so it reflects what that key can actually invoke rather than the organization’s full inventory.
The response shape follows the client. The request above returns the OpenAI envelope ({"object": "list", "data": [...]}), which is the default. Send an anthropic-version header — as the Anthropic SDKs and Claude Code do — or authenticate with x-api-key and no Authorization: Bearer header, and you get Anthropic’s envelope instead ({"data": [{"type": "model", "id": …, "display_name": …}], "has_more": false}), so client.models.list() parses against either SDK:
barndoor object — the serving provider and upstream model (when every target agrees on them), whether the name is a multi-target fallback group, and how many targets it has. It is extra metadata on top of the standard fields, so strict OpenAI and Anthropic clients ignore it safely.
Non-Streaming Chat Completion
Streaming Chat Completion
Set"stream": true and the gateway streams the response back as server-sent events in the format of the endpoint you called, whichever provider serves it.
Embeddings
Anthropic Messages (Claude Code)
The gateway also accepts native Anthropic-style requests:Connect Your Tools
Cursor, Claude Code, Codex, LangChain, the OpenAI and Anthropic SDKs, and plaincurl each need your API key, a model route name, and the gateway endpoint. Step-by-step configuration for each lives on its own page:
Connecting Your Tools to the LLM Gateway
Model Naming
The string in themodel field decides how the gateway routes the request. There are three forms:
openai/gpt-5.4-mini works only if a provider is named openai; a provider named Azure OpenAI Prod is addressed as Azure OpenAI Prod/gpt-5.4-mini.
The part after the prefix is always an upstream model name, never a route name. To pin one target of a route, address that target’s upstream model directly on its provider; <provider>/<route name> returns 404.
GET /v1/models lists only routing policies. See Require requests to use a routing policy.GET /v1/models returns every identifier the calling key can use, already filtered by your model access policies. Call it once on startup rather than on every request.
Observability Headers
Successful responses onPOST /v1/chat/completions and POST /v1/messages include headers you can log to understand routing — useful for client-side monitoring, comparing providers, and post-incident analysis.
/v1/completions, /v1/embeddings, or /v1/responses.
Every response, including errors, also carries x-bd-request-id. Send your own x-bd-request-id (or x-request-id) on the request and the gateway echoes it back; otherwise it generates one. Include it when you contact support.
For per-request usage and cost, use Reporting → LLM Usage Dashboard in the Barndoor portal (guide), where you can break traffic down by model, provider, user, group, API key, status code, and more.
Failover, Retries, and Streaming
- If a target returns a 5xx, a network error, a timeout, or a 429 that outlasts its retry budget, the gateway tries the next target in the route’s priority order. The response headers above show which target served the request.
- Same-target 429 retries are configured per target (Rate limit retries in the route’s advanced settings). The gateway retries with backoff, then either succeeds or fails over.
- Targets that keep failing are put in a short cooldown and skipped until they recover, and providers failing their health check are skipped too (see Provider health) — so failover prefers targets that are actually up. A provider with Block traffic on failed health check turned off stays in the rotation regardless.
- A streaming request fails over if the upstream sends no response within 60 seconds.
- Streaming responses (
stream: true) preserve the provider’s SSE framing and pass through token usage where the provider reports it.
Troubleshooting
Gateway errors use the error shape of the endpoint you called:{"error": {"message", "type", "code"}} on OpenAI endpoints, and {"type": "error", "error": {"type", "message"}} on /v1/messages. The message says what went wrong; the type is the stable value to branch on.
404 — model '…' not found or not available
404 — model '…' not found or not available
- Call
GET /v1/modelsto see exactly which names your key can use. - If you expected a name to be there, check with an admin that the route exists in Model Routes with at least one enabled target, and that the model is enabled on its provider.
model '…' not found for provider '…'means a provider-prefixed name didn’t match. The part after/must be an upstream model enabled on that provider — not a route name. Call a route by its plain name.
403 — model access denied
403 — model access denied
- Model access denials read
Model '…' is not allowed by access policy. Check LLM Management → Model Access for the policy that applies to the key’s user, group, or role. See Configuring LLM Controls.
429 — rate limit or budget exhausted
429 — rate limit or budget exhausted
- Barndoor’s rate limits (
type: rate_limit_error, with aRetry-Afterheader) and budgets (type: budget_exhausted) can return429before the request reaches any provider. The message says which limit fired. - Upstream 429s are retried per the route’s retry settings and may then fail over. Check the
x-bd-provider-retry-countandx-bd-provider-failover-countheaders to see what happened.
502 — every target failed
502 — every target failed
- When every target on a route fails, the message lists the providers tried and the last failure, and
error.metadata.attemptshas the detail for each attempt. The status matches the upstream failure where they all agree (for example401if every provider rejected its credentials),429if every attempt was rate limited, and502otherwise. - An attempt that timed out has a
codestarting withupstream_timeout_(for exampleupstream_timeout_first_bytewhen a streaming request got no response within 60 seconds). - Check the providers’ status pills in Providers — see Provider health.
400 — streaming or tools rejected on Vertex Gemini
400 — streaming or tools rejected on Vertex Gemini
- Gemini on Google Vertex AI doesn’t support streaming, tool calls, or structured
response_formatthrough the gateway yet. Send a non-streaming request, or route to a Google AI (Gemini) provider or a Claude model instead.
Streaming connection closes early
Streaming connection closes early
- Make sure your HTTP client supports SSE and doesn’t buffer (
curl -N,requests.post(..., stream=True),fetchwith a manual reader, and so on). - A premature close usually means the upstream provider closed first. Check the failover headers and the LLM Usage Dashboard for that request.
Anthropic SDK / Claude Code can't reach the gateway
Anthropic SDK / Claude Code can't reach the gateway
- The Anthropic SDK appends
/v1/messagesitself: set its base URL tohttps://app.barndoor.ai/api/llm-gateway(without/v1). Both forms are on the Gateway Endpoint card. - Send the Barndoor key in
x-api-key. If your client only knowsANTHROPIC_API_KEY, set that to yourbd-…key — it’s sent in the same header.
Frequently Asked Questions
Do I have to use OpenAI's SDK?
Do I have to use OpenAI's SDK?
/v1/messages — works. SDKs are a convenience, not a requirement.Where do upstream API keys live?
Where do upstream API keys live?
Can I see how many tokens / how much money my agents are using?
Can I see how many tokens / how much money my agents are using?
What's the difference between user keys and org keys?
What's the difference between user keys and org keys?
- User keys (Settings → My Models → API Keys, or an admin key assigned to a user) are tied to one user. Usage and policies attribute to that user.
- Group keys (assigned to a group in LLM Management → API Keys) share that group’s budgets, rate limits, and model access.
- Org keys (no user or group) are typically used for services and CI. They have an organization scope but no individual user.
What happens when an upstream provider is down?
What happens when an upstream provider is down?
502 entry in Troubleshooting.Need Help?
Reach out to [email protected] with:- The endpoint you called, the HTTP status code, and the
error.message. - The
x-bd-request-idresponse header, or the approximate time of the request and the value you sent in themodelfield. - A redacted request body if the issue reproduces consistently.