curl --request POST \
--url https://{host}/api/llm-gateway/admin/providers \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"base_url": "<string>",
"model_provider": "<string>",
"name": "<string>",
"api_key": "<string>",
"auth_type": "<string>",
"billing_note": "<string>",
"catalog_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"change_note": "<string>",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"credentials": "<unknown>",
"enforce_health_check": true,
"models": [
"<string>"
],
"request_timeout_secs": 123,
"settings": "<unknown>",
"stream_idle_timeout_secs": 123
}
'import requests
url = "https://{host}/api/llm-gateway/admin/providers"
payload = {
"base_url": "<string>",
"model_provider": "<string>",
"name": "<string>",
"api_key": "<string>",
"auth_type": "<string>",
"billing_note": "<string>",
"catalog_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"change_note": "<string>",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"credentials": "<unknown>",
"enforce_health_check": True,
"models": ["<string>"],
"request_timeout_secs": 123,
"settings": "<unknown>",
"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({
base_url: '<string>',
model_provider: '<string>',
name: '<string>',
api_key: '<string>',
auth_type: '<string>',
billing_note: '<string>',
catalog_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
change_note: '<string>',
connection_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
credentials: '<unknown>',
enforce_health_check: true,
models: ['<string>'],
request_timeout_secs: 123,
settings: '<unknown>',
stream_idle_timeout_secs: 123
})
};
fetch('https://{host}/api/llm-gateway/admin/providers', 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/providers",
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([
'base_url' => '<string>',
'model_provider' => '<string>',
'name' => '<string>',
'api_key' => '<string>',
'auth_type' => '<string>',
'billing_note' => '<string>',
'catalog_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'change_note' => '<string>',
'connection_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'credentials' => '<unknown>',
'enforce_health_check' => true,
'models' => [
'<string>'
],
'request_timeout_secs' => 123,
'settings' => '<unknown>',
'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/providers"
payload := strings.NewReader("{\n \"base_url\": \"<string>\",\n \"model_provider\": \"<string>\",\n \"name\": \"<string>\",\n \"api_key\": \"<string>\",\n \"auth_type\": \"<string>\",\n \"billing_note\": \"<string>\",\n \"catalog_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"change_note\": \"<string>\",\n \"connection_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"credentials\": \"<unknown>\",\n \"enforce_health_check\": true,\n \"models\": [\n \"<string>\"\n ],\n \"request_timeout_secs\": 123,\n \"settings\": \"<unknown>\",\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/providers")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"base_url\": \"<string>\",\n \"model_provider\": \"<string>\",\n \"name\": \"<string>\",\n \"api_key\": \"<string>\",\n \"auth_type\": \"<string>\",\n \"billing_note\": \"<string>\",\n \"catalog_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"change_note\": \"<string>\",\n \"connection_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"credentials\": \"<unknown>\",\n \"enforce_health_check\": true,\n \"models\": [\n \"<string>\"\n ],\n \"request_timeout_secs\": 123,\n \"settings\": \"<unknown>\",\n \"stream_idle_timeout_secs\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{host}/api/llm-gateway/admin/providers")
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 \"base_url\": \"<string>\",\n \"model_provider\": \"<string>\",\n \"name\": \"<string>\",\n \"api_key\": \"<string>\",\n \"auth_type\": \"<string>\",\n \"billing_note\": \"<string>\",\n \"catalog_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"change_note\": \"<string>\",\n \"connection_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"credentials\": \"<unknown>\",\n \"enforce_health_check\": true,\n \"models\": [\n \"<string>\"\n ],\n \"request_timeout_secs\": 123,\n \"settings\": \"<unknown>\",\n \"stream_idle_timeout_secs\": 123\n}"
response = http.request(request)
puts response.read_body{
"auth_type": "<string>",
"base_url": "<string>",
"billing_mode": "per_token",
"created_at": "2023-11-07T05:31:56Z",
"enabled": true,
"enforce_health_check": true,
"health_status": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"model_provider": "<string>",
"model_sync_mode": "off",
"name": "<string>",
"org_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"secret_path": "<string>",
"settings": "<unknown>",
"updated_at": "2023-11-07T05:31:56Z",
"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",
"billing_note": "<string>",
"billing_reason": "subscription",
"catalog_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"catalog_slug": "<string>",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"health_checked_at": "2023-11-07T05:31:56Z",
"health_detail": "<string>",
"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"
}
}Create a Provider
Creates a named upstream provider. Providers whose auth type needs a secret must reference an existing credential with connection_id; sending api_key or credentials here is rejected with 400.
Pass models to enable a list of upstream model names as 1:1 model routes in the same call.
curl --request POST \
--url https://{host}/api/llm-gateway/admin/providers \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"base_url": "<string>",
"model_provider": "<string>",
"name": "<string>",
"api_key": "<string>",
"auth_type": "<string>",
"billing_note": "<string>",
"catalog_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"change_note": "<string>",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"credentials": "<unknown>",
"enforce_health_check": true,
"models": [
"<string>"
],
"request_timeout_secs": 123,
"settings": "<unknown>",
"stream_idle_timeout_secs": 123
}
'import requests
url = "https://{host}/api/llm-gateway/admin/providers"
payload = {
"base_url": "<string>",
"model_provider": "<string>",
"name": "<string>",
"api_key": "<string>",
"auth_type": "<string>",
"billing_note": "<string>",
"catalog_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"change_note": "<string>",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"credentials": "<unknown>",
"enforce_health_check": True,
"models": ["<string>"],
"request_timeout_secs": 123,
"settings": "<unknown>",
"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({
base_url: '<string>',
model_provider: '<string>',
name: '<string>',
api_key: '<string>',
auth_type: '<string>',
billing_note: '<string>',
catalog_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
change_note: '<string>',
connection_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
credentials: '<unknown>',
enforce_health_check: true,
models: ['<string>'],
request_timeout_secs: 123,
settings: '<unknown>',
stream_idle_timeout_secs: 123
})
};
fetch('https://{host}/api/llm-gateway/admin/providers', 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/providers",
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([
'base_url' => '<string>',
'model_provider' => '<string>',
'name' => '<string>',
'api_key' => '<string>',
'auth_type' => '<string>',
'billing_note' => '<string>',
'catalog_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'change_note' => '<string>',
'connection_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'credentials' => '<unknown>',
'enforce_health_check' => true,
'models' => [
'<string>'
],
'request_timeout_secs' => 123,
'settings' => '<unknown>',
'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/providers"
payload := strings.NewReader("{\n \"base_url\": \"<string>\",\n \"model_provider\": \"<string>\",\n \"name\": \"<string>\",\n \"api_key\": \"<string>\",\n \"auth_type\": \"<string>\",\n \"billing_note\": \"<string>\",\n \"catalog_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"change_note\": \"<string>\",\n \"connection_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"credentials\": \"<unknown>\",\n \"enforce_health_check\": true,\n \"models\": [\n \"<string>\"\n ],\n \"request_timeout_secs\": 123,\n \"settings\": \"<unknown>\",\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/providers")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"base_url\": \"<string>\",\n \"model_provider\": \"<string>\",\n \"name\": \"<string>\",\n \"api_key\": \"<string>\",\n \"auth_type\": \"<string>\",\n \"billing_note\": \"<string>\",\n \"catalog_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"change_note\": \"<string>\",\n \"connection_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"credentials\": \"<unknown>\",\n \"enforce_health_check\": true,\n \"models\": [\n \"<string>\"\n ],\n \"request_timeout_secs\": 123,\n \"settings\": \"<unknown>\",\n \"stream_idle_timeout_secs\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{host}/api/llm-gateway/admin/providers")
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 \"base_url\": \"<string>\",\n \"model_provider\": \"<string>\",\n \"name\": \"<string>\",\n \"api_key\": \"<string>\",\n \"auth_type\": \"<string>\",\n \"billing_note\": \"<string>\",\n \"catalog_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"change_note\": \"<string>\",\n \"connection_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"credentials\": \"<unknown>\",\n \"enforce_health_check\": true,\n \"models\": [\n \"<string>\"\n ],\n \"request_timeout_secs\": 123,\n \"settings\": \"<unknown>\",\n \"stream_idle_timeout_secs\": 123\n}"
response = http.request(request)
puts response.read_body{
"auth_type": "<string>",
"base_url": "<string>",
"billing_mode": "per_token",
"created_at": "2023-11-07T05:31:56Z",
"enabled": true,
"enforce_health_check": true,
"health_status": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"model_provider": "<string>",
"model_sync_mode": "off",
"name": "<string>",
"org_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"secret_path": "<string>",
"settings": "<unknown>",
"updated_at": "2023-11-07T05:31:56Z",
"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",
"billing_note": "<string>",
"billing_reason": "subscription",
"catalog_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"catalog_slug": "<string>",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"health_checked_at": "2023-11-07T05:31:56Z",
"health_detail": "<string>",
"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"
}
}connection_id referencing an existing
Credential; the
provider takes its auth_type and settings from it.
api_key or credentials here is
rejected with 400, and so is a provider with no connection_id unless its auth
type stores no secret (claude_oauth or codex_oauth). To rotate a key, update
the credential.Auto-enabling models in one call
Pass a list of upstream model names inmodels and Barndoor will create a 1:1
Model Route for each
one in the same call. The route’s alias matches the upstream model name so
callers can address it as <provider>/<model>. Add bare-name aliases or
failover routes afterwards via the Model Routes endpoints.
Example
curl -X POST https://app.barndoor.ai/api/llm-gateway/admin/providers \
-H "Authorization: Bearer $BARNDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "OpenAI Production (US)",
"model_provider": "openai",
"base_url": "https://api.openai.com/v1",
"connection_id": "4f8b2a3c-12ee-4d92-9c7b-e7d2f8b0a111",
"models": ["gpt-5.5", "gpt-5.4-mini", "text-embedding-3-large"]
}'
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
Provider family, which decides the protocol the gateway speaks upstream, for example openai, anthropic, azure_openai, bedrock, vertex, or custom.
Not accepted for auth types that need a stored secret: create a credential and pass connection_id instead.
How the gateway authenticates upstream. Defaults by provider family.
Whether the gateway records a per-token cost. Defaults to per_token.
per_token, not_metered Optional note about the billing arrangement, up to 200 characters.
How the vendor bills. Required when billing_mode is not_metered.
subscription, local, external, other Optional provider catalog entry this provider was created from.
Optional note explaining why this was created. Shown with the record and in the audit log.
ID of the credential this provider uses. Required for every auth type that needs a stored secret.
Not accepted for auth types that need a stored secret: create a credential and pass connection_id instead.
Whether routing waits on the connectivity check. Defaults to true; set false to serve the provider even while its check fails.
Whether the provider follows Barndoor's model catalog. Defaults to off.
off, additive, full Upstream model names to enable as 1:1 model routes in the same call.
Provider-wide fallback for the non-streaming request timeout, in seconds (1–600). Rarely needed: routes carry their own timeout.
Provider-specific settings as a JSON object, such as region for Bedrock or api_version for Azure OpenAI.
Provider-wide fallback for the streaming idle timeout, in seconds (1–300). Rarely needed: routes carry their own timeout.
Response
Created
An upstream provider.
Whether the gateway records a per-token cost for this provider's traffic.
per_token, not_metered Whether the provider may serve traffic.
Whether routing waits on the connectivity check. When false the provider serves even while its check fails; health is still recorded.
Upstream reachability from the connectivity check: unverified, healthy, or unhealthy. Separate from enabled. An enabled provider that turns unhealthy stops receiving traffic until a check records it healthy again, unless enforce_health_check is false. Some provider families are not checked and stay unverified.
Whether this provider follows Barndoor's model catalog.
off, additive, full Internal reference to the stored secret. This is not the secret.
Note explaining the last change.
When the last attributed change was made.
Note about the billing arrangement.
How the vendor bills this provider. Descriptive only.
subscription, local, external, other ID of the credential this provider uses.
When the last connectivity check ran; null before the first check.
Reason for the last unhealthy result; null otherwise.
Provider-wide fallback for the non-streaming request timeout, in seconds.
Provider-wide fallback for the streaming idle timeout, in seconds.