createRoute.md
Create a Model Route
Creates a model route. A 1:1 enablement (model_alias == upstream_model) for an existing provider/model pair will fold into the existing row rather than failing — this lets you re-issue the same create call idempotently from automation.
A Model Route maps a client-facing alias to a (provider, upstream model) pair. Multiple routes can share the same model_alias — the gateway tries them in priority order (lowest first) and fails over to the next on upstream errors.
Two kinds of routes
- 1:1 enablement (
model_alias == upstream_model) — exposes the upstream model under its own name, addressable as<provider>/<upstream_model>. Defaults tobare_alias: false. Re-issuing this call for an existing enablement folds into the existing row, making it idempotent. - Custom alias (
model_alias != upstream_model) — exposes the model under a friendly alias (e.g.team-coding-model). Defaults tobare_alias: trueso callers can use the plain name inmodel. Requires an existing 1:1 enablement on the same(provider, upstream_model)pair.
Example: an alias with failover
The simplest production setup is one alias backed by a primary route plus one or more failover routes:
# Route 1: primary (priority 0)
curl -X POST https://app.barndoor.ai/api/llm-gateway/admin/model-mappings \
-H "Authorization: Bearer $BARNDOOR_JWT" \
-H "Content-Type: application/json" \
-d '{
"provider_id": "<openai-provider-id>",
"model_alias": "claude-opus-4-8",
"upstream_model": "claude-opus-4-8",
"priority": 0,
"bare_alias": true
}'
# Route 2: failover on Bedrock (priority 1)
curl -X POST https://app.barndoor.ai/api/llm-gateway/admin/model-mappings \
-H "Authorization: Bearer $BARNDOOR_JWT" \
-H "Content-Type: application/json" \
-d '{
"provider_id": "<bedrock-provider-id>",
"model_alias": "claude-opus-4-8",
"upstream_model": "us.anthropic.claude-opus-4-8",
"priority": 1,
"bare_alias": true
}'
OpenAPI
openapi: 3.1.0
info:
title: Barndoor LLM Gateway API
version: 1.0.0
description: >
REST API for the Barndoor LLM Gateway: configure providers, model routes,
pricing, governance, and operate a multi-provider LLM platform
programmatically.
All endpoints in this document are scoped to your organization. They are the
same APIs powering the Barndoor portal under **LLM Configuration**,
**LLM Controls**, and **Settings - My Models**, exposed for teams that
prefer scripting over the UI.
## Base URL
All requests are issued against your Barndoor instance:
```
https://app.barndoor.ai/api/llm-gateway
```
Replace `app.barndoor.ai` with your tenant host if you run on Enterprise.
## Authentication
Endpoints accept a JWT Bearer token issued by your Barndoor identity
provider. Tokens can be obtained interactively via the Barndoor SDK:
```ts
const sdk = await loginInteractive();
```
The token must be sent in the `Authorization` header on every request:
```
Authorization: Bearer eyJhbGciOi...
```
Note: the `bd-...` API keys you create through these endpoints are for
runtime LLM traffic (`/v1/chat/completions`, `/v1/messages`, etc.), not for
administrative calls. Administrative endpoints require a user/admin JWT.
## Permissions
Most endpoints require an `admin` (or higher) role on the calling user.
Read-only endpoints are typically accessible by all authenticated users.
Read-only listings under `/user/...` are scoped to the authenticated user.
## Errors
Errors are returned as JSON with a stable shape:
```json
{ "error": "BadRequest", "message": "request_timeout_secs must be between 1 and 3600" }
```
contact:
name: Barndoor Support
url: https://barndoor.ai
servers:
- url: https://{host}/api/llm-gateway
description: >-
Production / Trial (Barndoor SaaS). The gateway lives on your Barndoor
control-plane host. For Enterprise or self-hosted deployments, replace the
host with your portal hostname — the authoritative value is shown on
Settings → My Models in the portal.
variables:
host:
description: Your Barndoor control-plane (portal) hostname
default: app.barndoor.ai
- url: https://app.barndooruat.com/api/llm-gateway
description: UAT
- url: https://app.barndoordev.com/api/llm-gateway
description: Dev
security:
- BearerAuth: []
tags:
- name: Credentials
description: >-
Reusable upstream credentials (API keys, AWS roles, Vertex service
accounts)
- name: Providers
description: Named upstream providers backed by credentials and a model family
- name: Provider Catalog
description: Read-only catalog of supported upstream provider templates
- name: Model Routes
description: Map client-facing aliases to one or more upstream provider/model pairs
- name: Model Pricing
description: Per-million-token input/output costs for usage and budget reporting
- name: Rate Limits
description: Requests-per-minute and tokens-per-minute caps
- name: Token Budgets
description: Daily, weekly, or monthly token and cost ceilings
- name: Model Access
description: Allowlist or denylist policies for models, providers, or aliases
- name: Smart Models
description: Routing policies that pick a target model based on the request
- name: Governance Configuration
description: Org-wide behavior toggles for the LLM Gateway
- name: Route Health
description: Operational view of upstream route ejection and recovery
- name: API Keys
description: Org-managed gateway API keys (the `bd-...` keys callers send on `/v1/...`)
- name: User
description: Self-service endpoints for the authenticated user
paths:
/admin/model-mappings:
post:
tags:
- Model Routes
summary: Create a model route
description: >
Creates a model route. A 1:1 enablement (`model_alias == upstream_model`)
for an existing provider/model pair will fold into the existing row
rather than failing — this lets you re-issue the same create call
idempotently from automation.
operationId: createModelRoute
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateModelRouteRequest'
responses:
'200':
description: The newly created or updated route
content:
application/json:
schema:
$ref: '#/components/schemas/ModelRoute'
'400':
$ref: '#/components/responses/BadRequest'
components:
schemas:
CreateModelRouteRequest:
type: object
required:
- provider_id
- model_alias
- upstream_model
properties:
provider_id:
type: string
format: uuid
model_alias:
type: string
upstream_model:
type: string
enabled:
type: boolean
default: true
priority:
type: integer
default: 0
retry_on_429_count:
type: integer
minimum: 0
maximum: 10
default: 0
retry_on_429_max_wait_secs:
type: integer
minimum: 0
maximum: 180
default: 0
bare_alias:
type: boolean
description: |
Whether the route participates in bare-alias resolution. Defaults
to `true` for custom aliases (where `model_alias != upstream_model`)
and `false` for 1:1 enablement rows.
stream_idle_timeout_secs:
type: integer
nullable: true
minimum: 1
maximum: 1800
max_concurrent_requests:
type: integer
nullable: true
minimum: 1
maximum: 10000
request_timeout_secs:
type: integer
nullable: true
minimum: 1
maximum: 3600
ModelRoute:
type: object
description: |
A Model Route maps a client-facing alias to a specific provider and
upstream model. One alias may have multiple routes; the gateway tries
them in `priority` order and fails over on upstream errors.
required:
- id
- provider_id
- model_alias
- upstream_model
- enabled
- priority
- retry_on_429_count
- retry_on_429_max_wait_secs
- bare_alias
properties:
id:
type: string
format: uuid
provider_id:
type: string
format: uuid
provider_name:
type: string
description: Present on cross-provider listings
model_alias:
type: string
example: gpt-4o-mini
upstream_model:
type: string
example: gpt-4o-mini-2024-07-18
enabled:
type: boolean
priority:
type: integer
description: Lower numbers are tried first within the same alias
retry_on_429_count:
type: integer
minimum: 0
maximum: 10
description: Same-route retries on upstream 429 before failing over
retry_on_429_max_wait_secs:
type: integer
minimum: 0
maximum: 180
description: >-
Cap on honoring upstream `Retry-After` (0 = use small built-in
default)
bare_alias:
type: boolean
description: |
When `true` the route participates in plain-alias resolution
(e.g. `model: "gpt-4o-mini"`). When `false` it is only
addressable as `<provider>/<upstream-model>`.
stream_idle_timeout_secs:
type: integer
nullable: true
minimum: 1
maximum: 1800
max_concurrent_requests:
type: integer
nullable: true
minimum: 1
maximum: 10000
description: Cap on in-flight requests per gateway pod against this route
request_timeout_secs:
type: integer
nullable: true
minimum: 1
maximum: 3600
budget_status:
allOf:
- $ref: '#/components/schemas/BudgetTargetStatus'
description: |
Present (and only present) when one of this route's targeted budgets
with `action_on_exhaust = block` is currently exhausted. The
runtime drops this route until the budget rolls over.
BudgetTargetStatus:
type: object
description: |
Snapshot of the first budget that would block this route (if any).
Surfaced on listings so admin UIs can show a "disabled by budget" pill.
properties:
scope:
type: string
example: org
target_kind:
type: string
enum:
- llm_provider
- model
- model_alias
target_id:
type: string
budget_id:
type: string
format: uuid
budget_name:
type: string
period:
type: string
example: monthly
usage:
type: number
limit:
type: number
Error:
type: object
required:
- error
- message
properties:
error:
type: string
description: A short machine-readable error code
example: BadRequest
message:
type: string
description: A human-readable description of what went wrong
example: request_timeout_secs must be between 1 and 3600
responses:
BadRequest:
description: The request body or query parameters were invalid
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT obtained through Barndoor's authentication flow. Pass the token
verbatim in `Authorization: Bearer <token>`. Use the Barndoor SDK's
`loginInteractive()` helper to obtain a token in scripts and notebooks.