curl --request POST \
--url https://{host}/api/llm-gateway/admin/model-mappings \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model_alias": "<string>",
"provider_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"upstream_model": "<string>",
"bare_alias": true,
"change_note": "<string>",
"cooldown_429_default_secs": 123,
"cooldown_base_secs": 123,
"cooldown_failure_threshold": 123,
"cooldown_max_secs": 123,
"cooldown_overloaded_secs": 123,
"cooldown_window_secs": 123,
"enabled": true,
"priority": 123,
"request_timeout_secs": 123,
"retry_on_429_count": 123,
"retry_on_429_max_wait_secs": 123,
"stream_idle_timeout_secs": 123
}
'import requests
url = "https://{host}/api/llm-gateway/admin/model-mappings"
payload = {
"model_alias": "<string>",
"provider_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"upstream_model": "<string>",
"bare_alias": True,
"change_note": "<string>",
"cooldown_429_default_secs": 123,
"cooldown_base_secs": 123,
"cooldown_failure_threshold": 123,
"cooldown_max_secs": 123,
"cooldown_overloaded_secs": 123,
"cooldown_window_secs": 123,
"enabled": True,
"priority": 123,
"request_timeout_secs": 123,
"retry_on_429_count": 123,
"retry_on_429_max_wait_secs": 123,
"stream_idle_timeout_secs": 123
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model_alias: '<string>',
provider_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
upstream_model: '<string>',
bare_alias: true,
change_note: '<string>',
cooldown_429_default_secs: 123,
cooldown_base_secs: 123,
cooldown_failure_threshold: 123,
cooldown_max_secs: 123,
cooldown_overloaded_secs: 123,
cooldown_window_secs: 123,
enabled: true,
priority: 123,
request_timeout_secs: 123,
retry_on_429_count: 123,
retry_on_429_max_wait_secs: 123,
stream_idle_timeout_secs: 123
})
};
fetch('https://{host}/api/llm-gateway/admin/model-mappings', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{host}/api/llm-gateway/admin/model-mappings",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model_alias' => '<string>',
'provider_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'upstream_model' => '<string>',
'bare_alias' => true,
'change_note' => '<string>',
'cooldown_429_default_secs' => 123,
'cooldown_base_secs' => 123,
'cooldown_failure_threshold' => 123,
'cooldown_max_secs' => 123,
'cooldown_overloaded_secs' => 123,
'cooldown_window_secs' => 123,
'enabled' => true,
'priority' => 123,
'request_timeout_secs' => 123,
'retry_on_429_count' => 123,
'retry_on_429_max_wait_secs' => 123,
'stream_idle_timeout_secs' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{host}/api/llm-gateway/admin/model-mappings"
payload := strings.NewReader("{\n \"model_alias\": \"<string>\",\n \"provider_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"upstream_model\": \"<string>\",\n \"bare_alias\": true,\n \"change_note\": \"<string>\",\n \"cooldown_429_default_secs\": 123,\n \"cooldown_base_secs\": 123,\n \"cooldown_failure_threshold\": 123,\n \"cooldown_max_secs\": 123,\n \"cooldown_overloaded_secs\": 123,\n \"cooldown_window_secs\": 123,\n \"enabled\": true,\n \"priority\": 123,\n \"request_timeout_secs\": 123,\n \"retry_on_429_count\": 123,\n \"retry_on_429_max_wait_secs\": 123,\n \"stream_idle_timeout_secs\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{host}/api/llm-gateway/admin/model-mappings")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model_alias\": \"<string>\",\n \"provider_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"upstream_model\": \"<string>\",\n \"bare_alias\": true,\n \"change_note\": \"<string>\",\n \"cooldown_429_default_secs\": 123,\n \"cooldown_base_secs\": 123,\n \"cooldown_failure_threshold\": 123,\n \"cooldown_max_secs\": 123,\n \"cooldown_overloaded_secs\": 123,\n \"cooldown_window_secs\": 123,\n \"enabled\": true,\n \"priority\": 123,\n \"request_timeout_secs\": 123,\n \"retry_on_429_count\": 123,\n \"retry_on_429_max_wait_secs\": 123,\n \"stream_idle_timeout_secs\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{host}/api/llm-gateway/admin/model-mappings")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model_alias\": \"<string>\",\n \"provider_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"upstream_model\": \"<string>\",\n \"bare_alias\": true,\n \"change_note\": \"<string>\",\n \"cooldown_429_default_secs\": 123,\n \"cooldown_base_secs\": 123,\n \"cooldown_failure_threshold\": 123,\n \"cooldown_max_secs\": 123,\n \"cooldown_overloaded_secs\": 123,\n \"cooldown_window_secs\": 123,\n \"enabled\": true,\n \"priority\": 123,\n \"request_timeout_secs\": 123,\n \"retry_on_429_count\": 123,\n \"retry_on_429_max_wait_secs\": 123,\n \"stream_idle_timeout_secs\": 123\n}"
response = http.request(request)
puts response.read_body{
"cooldown_429_default_secs": 123,
"cooldown_base_secs": 123,
"cooldown_failure_threshold": 123,
"cooldown_max_secs": 123,
"cooldown_overloaded_secs": 123,
"cooldown_window_secs": 123,
"bare_alias": true,
"enabled": true,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"model_alias": "<string>",
"priority": 123,
"provider_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"retry_on_429_count": 123,
"retry_on_429_max_wait_secs": 123,
"source": "catalog",
"upstream_model": "<string>",
"created_by_email": "<string>",
"created_by_name": "<string>",
"created_by_user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"last_change_note": "<string>",
"last_modified_at": "2023-11-07T05:31:56Z",
"last_modified_by_email": "<string>",
"last_modified_by_name": "<string>",
"last_modified_by_user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"auto_disabled_reason": "catalog_retired",
"request_timeout_secs": 123,
"stream_idle_timeout_secs": 123
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}Create a Model Route
Creates a model route from a caller-facing model_alias to an upstream_model on a provider.
- A 1:1 enablement (
model_aliasequalsupstream_model) makes the model servable on the provider. Creating one that already exists updates the existing row instead of failing, so automation can re-issue the call safely. - A custom alias (
model_aliasdiffers fromupstream_model) requires the 1:1 enablement for the same provider and upstream model to exist first, or the request fails with400.
When your organization requires pricing for model routes, an enabled route must match a pricing rule.
curl --request POST \
--url https://{host}/api/llm-gateway/admin/model-mappings \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model_alias": "<string>",
"provider_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"upstream_model": "<string>",
"bare_alias": true,
"change_note": "<string>",
"cooldown_429_default_secs": 123,
"cooldown_base_secs": 123,
"cooldown_failure_threshold": 123,
"cooldown_max_secs": 123,
"cooldown_overloaded_secs": 123,
"cooldown_window_secs": 123,
"enabled": true,
"priority": 123,
"request_timeout_secs": 123,
"retry_on_429_count": 123,
"retry_on_429_max_wait_secs": 123,
"stream_idle_timeout_secs": 123
}
'import requests
url = "https://{host}/api/llm-gateway/admin/model-mappings"
payload = {
"model_alias": "<string>",
"provider_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"upstream_model": "<string>",
"bare_alias": True,
"change_note": "<string>",
"cooldown_429_default_secs": 123,
"cooldown_base_secs": 123,
"cooldown_failure_threshold": 123,
"cooldown_max_secs": 123,
"cooldown_overloaded_secs": 123,
"cooldown_window_secs": 123,
"enabled": True,
"priority": 123,
"request_timeout_secs": 123,
"retry_on_429_count": 123,
"retry_on_429_max_wait_secs": 123,
"stream_idle_timeout_secs": 123
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model_alias: '<string>',
provider_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
upstream_model: '<string>',
bare_alias: true,
change_note: '<string>',
cooldown_429_default_secs: 123,
cooldown_base_secs: 123,
cooldown_failure_threshold: 123,
cooldown_max_secs: 123,
cooldown_overloaded_secs: 123,
cooldown_window_secs: 123,
enabled: true,
priority: 123,
request_timeout_secs: 123,
retry_on_429_count: 123,
retry_on_429_max_wait_secs: 123,
stream_idle_timeout_secs: 123
})
};
fetch('https://{host}/api/llm-gateway/admin/model-mappings', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{host}/api/llm-gateway/admin/model-mappings",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model_alias' => '<string>',
'provider_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'upstream_model' => '<string>',
'bare_alias' => true,
'change_note' => '<string>',
'cooldown_429_default_secs' => 123,
'cooldown_base_secs' => 123,
'cooldown_failure_threshold' => 123,
'cooldown_max_secs' => 123,
'cooldown_overloaded_secs' => 123,
'cooldown_window_secs' => 123,
'enabled' => true,
'priority' => 123,
'request_timeout_secs' => 123,
'retry_on_429_count' => 123,
'retry_on_429_max_wait_secs' => 123,
'stream_idle_timeout_secs' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{host}/api/llm-gateway/admin/model-mappings"
payload := strings.NewReader("{\n \"model_alias\": \"<string>\",\n \"provider_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"upstream_model\": \"<string>\",\n \"bare_alias\": true,\n \"change_note\": \"<string>\",\n \"cooldown_429_default_secs\": 123,\n \"cooldown_base_secs\": 123,\n \"cooldown_failure_threshold\": 123,\n \"cooldown_max_secs\": 123,\n \"cooldown_overloaded_secs\": 123,\n \"cooldown_window_secs\": 123,\n \"enabled\": true,\n \"priority\": 123,\n \"request_timeout_secs\": 123,\n \"retry_on_429_count\": 123,\n \"retry_on_429_max_wait_secs\": 123,\n \"stream_idle_timeout_secs\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{host}/api/llm-gateway/admin/model-mappings")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model_alias\": \"<string>\",\n \"provider_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"upstream_model\": \"<string>\",\n \"bare_alias\": true,\n \"change_note\": \"<string>\",\n \"cooldown_429_default_secs\": 123,\n \"cooldown_base_secs\": 123,\n \"cooldown_failure_threshold\": 123,\n \"cooldown_max_secs\": 123,\n \"cooldown_overloaded_secs\": 123,\n \"cooldown_window_secs\": 123,\n \"enabled\": true,\n \"priority\": 123,\n \"request_timeout_secs\": 123,\n \"retry_on_429_count\": 123,\n \"retry_on_429_max_wait_secs\": 123,\n \"stream_idle_timeout_secs\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{host}/api/llm-gateway/admin/model-mappings")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model_alias\": \"<string>\",\n \"provider_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"upstream_model\": \"<string>\",\n \"bare_alias\": true,\n \"change_note\": \"<string>\",\n \"cooldown_429_default_secs\": 123,\n \"cooldown_base_secs\": 123,\n \"cooldown_failure_threshold\": 123,\n \"cooldown_max_secs\": 123,\n \"cooldown_overloaded_secs\": 123,\n \"cooldown_window_secs\": 123,\n \"enabled\": true,\n \"priority\": 123,\n \"request_timeout_secs\": 123,\n \"retry_on_429_count\": 123,\n \"retry_on_429_max_wait_secs\": 123,\n \"stream_idle_timeout_secs\": 123\n}"
response = http.request(request)
puts response.read_body{
"cooldown_429_default_secs": 123,
"cooldown_base_secs": 123,
"cooldown_failure_threshold": 123,
"cooldown_max_secs": 123,
"cooldown_overloaded_secs": 123,
"cooldown_window_secs": 123,
"bare_alias": true,
"enabled": true,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"model_alias": "<string>",
"priority": 123,
"provider_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"retry_on_429_count": 123,
"retry_on_429_max_wait_secs": 123,
"source": "catalog",
"upstream_model": "<string>",
"created_by_email": "<string>",
"created_by_name": "<string>",
"created_by_user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"last_change_note": "<string>",
"last_modified_at": "2023-11-07T05:31:56Z",
"last_modified_by_email": "<string>",
"last_modified_by_name": "<string>",
"last_modified_by_user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"auto_disabled_reason": "catalog_retired",
"request_timeout_secs": 123,
"stream_idle_timeout_secs": 123
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}{
"error": {
"message": "retry_on_429_count must be between 0 and 10",
"type": "invalid_request_error"
}
}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.
retry_on_429_*), timeouts, and
passive-health cooldown settings (cooldown_*); omitted fields take the platform
defaults. Change them later with Update a model route.
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 is a 1:1 enablement opted into bare-name resolution, so callers can sendclaude-opus-5-5 without a provider prefix. Route 2 is a custom alias with the
same name on Bedrock, so the 1:1 enablement of anthropic.claude-opus-5-5 on
that provider must exist first.
# Route 1: primary (priority 0)
curl -X POST https://app.barndoor.ai/api/llm-gateway/admin/model-mappings \
-H "Authorization: Bearer $BARNDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider_id": "<anthropic-provider-id>",
"model_alias": "claude-opus-5-5",
"upstream_model": "claude-opus-5-5",
"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_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider_id": "<bedrock-provider-id>",
"model_alias": "claude-opus-5-5",
"upstream_model": "anthropic.claude-opus-5-5",
"priority": 1,
"bare_alias": true
}'
Authorizations
An access token from Barndoor's identity provider, sent as Authorization: Bearer <token>. Use a service-account token from the OAuth 2.0 client-credentials grant for scripts and CI, or a signed-in user's token. The caller needs the admin role in the organization. Gateway API keys (bd-...) are not accepted here.
Body
Caller-facing model name: what API callers send in model.
The provider's name for the model.
Whether the route answers requests that name the alias alone, without a <provider>/ prefix. Defaults to true for custom aliases and false for 1:1 enablements.
Optional note explaining why this was created. Shown with the record and in the audit log.
Cooldown after an upstream 429 with no usable Retry-After, in seconds (1–3600, and at most cooldown_max_secs). Defaults to 30.
First cooldown window, in seconds, doubled after each failed recovery probe up to cooldown_max_secs (1–3600, and at most cooldown_max_secs). Defaults to 30.
Gateway failures (5xx responses, timeouts, connection errors, and 401/403 from a stored key) within cooldown_window_secs that put the route in cooldown (0–100). 0 disables cooldowns for the route. Defaults to 10.
Longest cooldown window, in seconds (1–86400). Defaults to 300.
Cooldown after an upstream 529 (overloaded) with no usable Retry-After, in seconds (0–3600, and at most cooldown_max_secs unless 0). 0 treats a 529 as an ordinary failure. Defaults to 10.
Length of the rolling failure window, in seconds (1–3600). Defaults to 60.
Whether the route serves traffic. Defaults to true.
Failover order among routes serving the same alias; lower is tried first. Defaults to 0.
Total-request timeout for non-streaming requests, in seconds (1–600). Defaults to 120 when unset. On a 1:1 enablement row this sets the timeout for every alias of the model.
Retries on the same route after an upstream 429 before failing over (0–10). 0 fails over immediately.
Longest upstream Retry-After to honor, in seconds (0–180). 0 uses a short built-in wait and ignores the header.
Whether the model was chosen from the catalog (catalog) or typed in (custom). Defaults to the 1:1 enablement's value when one exists, otherwise catalog.
catalog, custom Idle timeout between chunks of a streaming response, in seconds (1–300). Defaults to 180 when unset.
Response
Created
A model route.
Cooldown after an upstream 429 with no usable Retry-After, in seconds.
First cooldown window, in seconds. Doubles after each failed recovery probe, up to cooldown_max_secs.
Gateway failures within cooldown_window_secs that put the route in cooldown. 0 disables cooldowns for the route.
Longest cooldown window, in seconds.
Cooldown after an upstream 529 (overloaded) with no usable Retry-After, in seconds. 0 treats a 529 as an ordinary failure.
Length of the rolling failure window, in seconds.
Whether the route answers requests that name the alias alone. When false, the model is reachable only as <provider>/<upstream_model>. Custom aliases are always true.
Failover order among routes serving the same alias; lower is tried first.
Same-route retries on upstream 429. 0 means immediate failover.
Longest upstream Retry-After to honor, in seconds. 0 uses a short built-in wait and ignores the header.
Whether the model was chosen from the catalog or typed in when the route was created.
catalog, custom Note explaining the last change.
When the last attributed change was made.
Set when the gateway disabled this route because the model left the provider's catalog. Any admin change to enabled clears it.
catalog_retired Total-request timeout for non-streaming requests, in seconds (1–600).
Idle timeout between chunks of a streaming response, in seconds (1–300).