Custom base URLs
Point a provider at an endpoint you control instead of the provider's own API.
A provider that authenticates with its own API key can carry an optional Base URL that replaces the provider type's own origin. Nothing else changes: the path after the slug, the query string, the credential header, the model rules and the pricing rule are exactly what they would have been.
The Base URL field
In the Add provider dialog, with Authentication set to API key,
fill in Base URL (optional). Leave it empty to use the provider's own API.
The field takes an absolute https:// URL, and the path you append after the
slug is joined onto it:
Base URL: https://my-vllm.example.com/v1/
Your app: POST /v1/apps/my-app/proxy/vllm/chat/completions
Reaches: https://my-vllm.example.com/v1/chat/completionsClick Test provider to run the provider type's test call at the new origin before saving. A custom endpoint that does not implement the provider's list-models call answers 404, which reports as unconfirmed rather than as a refusal.
The API equivalent:
POST /v1/admin/providers
{
"type": "openai",
"name": "Self-hosted Llama",
"slug": "vllm",
"secret": "...",
"baseUrl": "https://my-vllm.example.com/v1/"
}The field is not available with Use gateway. A gateway owns the upstream
origin, and the API refuses baseUrl together with providerGatewayId on
both create and update.
What it enables
Any server that speaks a supported provider's API unchanged becomes usable without a code change in your apps.
- Self-hosted inference. vLLM, SGLang, Ollama behind TLS, llama.cpp's
server. Pick
openaias the type and point it at your/v1/base. - A second region of a supported provider. BytePlus ModelArk's
eu-westhost, for instance, whose keys and catalogs are region-isolated. Pickbytedanceas the type and enter that region's base URL. - A proxy of your own in front of a provider, as long as it speaks that provider's API unchanged.
- Azure OpenAI, with the caveats below.
The console shows the origin under Auth in the Providers list, beside the key's last characters, so it is never a surprise which service a key is being sent to.
What the URL must look like
The URL is checked and rewritten into a canonical form before it is stored. Each rule refuses with a message naming what is wrong.
| Rule | Rejected examples |
|---|---|
https only | http://..., ftp://... |
| No credentials in the URL | https://user:pass@host/ |
| No query string and no fragment | https://host/?api-version=..., https://host/#x |
| Default port only (443, explicit or implicit) | https://host:8443/ |
| A public DNS name, never an IP address in any form | https://127.0.0.1/, https://0x7f000001/, https://[::1]/ |
| At least two labels, valid DNS labels, no trailing dot | https://vllm/, https://host./, https://a..b.example.com/ |
| No reserved local suffix | .local, .localhost, .internal, .home.arpa, .lan, .corp, .test, .example |
| At most 200 characters |
What is stored is the canonical form: lower-cased host (punycoded if you typed
Unicode), no redundant :443, dot segments resolved, and exactly one trailing
slash. https://My-VLLM.Example.com/v1 is stored as
https://my-vllm.example.com/v1/.
Upstream redirects are never followed on any proxied request. A 3xx from
your endpoint is passed back to the client as is, so a redirect cannot move the
destination after the URL was checked.
Changing the origin
To move an existing provider to a different origin, open Update key on its row. The dialog has a Base URL field next to New API key, with the hint "Changing the origin needs the key above, because the stored key is never sent to a new origin. Leave empty to use the provider's own API."
That rule is the point. The stored key is write-only: it is never decrypted to be sent somewhere it has not been sent before, so pointing a provider at a new host cannot become a way to read its key back out. Paste the key again, set the new Base URL, and click Update key. Emptying the field returns the provider to the provider type's own API.
Through the API, a new baseUrl needs secret in the same request, and the
update is refused with 400 invalid_request without it. Clearing needs nothing
else:
PUT /v1/admin/providers/{id}
{ "secret": "sk-...", "baseUrl": "https://eu.example.com/v1/" }PUT /v1/admin/providers/{id}
{ "baseUrl": null }Send the same type, secret and baseUrl to POST /v1/admin/providers/test
first to find out whether the key works at the new origin.
Security note
Pointing a provider at an origin hands that origin the key
The base URL is set only by you, through the console or a management key. No app and no end user can influence it; it is read from the stored provider, never from a request. Treat entering an origin as equivalent to giving that origin the provider's API key, because that is what every request does.
The checks above stop the direct expression of a mistake: a local address, a typo, a copied internal name. They cannot stop a public hostname from resolving to a private address, because the gateway does not resolve names itself and cannot see or pin the address a request connects to. The real control is that only you can write this field.
Custom endpoints still need prices
A model served from your own endpoint is almost certainly not in the shipped
catalog, so it is refused with 400 pricing_not_configured until you enter a
price for it under the provider's Pricing action. Entering the price is
what allows the model. There is no "unmetered because it is mine" path.
For a model you host yourself and pay no per-token price for, $0 is
enterable. Enter it deliberately, because it also removes that traffic from
every spending limit. See
Model pricing.
Azure OpenAI
Use provider type openai with the resource's v1 base URL:
https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/Azure's v1 API accepts the resource key as Authorization: Bearer, which is
exactly what the gateway sends for the openai type. It is the same thing
Microsoft's own documentation does when it runs the stock OpenAI SDK against
that base URL. Two things to know:
- The older, dated Azure surface is not supported. It authenticates with an
api-keyheader and needs an?api-version=query on the base, neither of which the gateway adds. The URL check refuses a base URL carrying a query string for that reason. Use the v1 base URL above. - Microsoft Entra ID tokens are not supported. They are short-lived and need refreshing, and a provider stores one static secret. Use a resource key.
The model field in your requests is your deployment name, not the
upstream model name, and deployment names are not in the shipped catalog. Price
them on that provider as described above.