Custom Endpoints
Add custom AI providers like OpenRouter, Ollama, and Anthropic-compatible gateways to LibreChat using librechat.yaml
LibreChat supports OpenAI API-compatible services as custom endpoints. It also supports Anthropic-compatible custom endpoints with provider: "anthropic". You configure endpoints in librechat.yaml, store API keys in .env, and mount the config via docker-compose.override.yml for Docker deployments.
Which File Does What?
Custom endpoint setup involves three files, each with a specific role:
librechat.yaml-- Defines your custom endpoints (name, API URL, models, display settings).env-- Stores sensitive values like API keys (referenced from librechat.yaml using${VAR_NAME}syntax)docker-compose.override.yml-- Mountslibrechat.yamlinto the Docker container (Docker users only)
For a full overview of how these files work together, see the Configuration Overview.
Before You Start
This guide assumes you have LibreChat installed and running. If not, complete the Docker setup first.
Step 1. Mount librechat.yaml (Docker Only)
Docker users need to mount librechat.yaml as a volume so the container can read it. Skip this step if you are running LibreChat locally without Docker.
cp docker-compose.override.yml.example docker-compose.override.ymlEdit docker-compose.override.yml and ensure the volume mount is uncommented:
services:
api:
volumes:
- type: bind
source: ./librechat.yaml
target: /app/librechat.yamlLearn more: Docker Override Guide
Step 2. Configure librechat.yaml
Create a librechat.yaml file in the project root (if it does not exist) and add your endpoint configuration. See the librechat.yaml guide for detailed setup instructions.
Here is an example with OpenRouter, Ollama, and an Anthropic-compatible gateway:
version: 1.3.13
cache: true
endpoints:
custom:
- name: 'OpenRouter'
apiKey: '${OPENROUTER_KEY}'
baseURL: 'https://openrouter.ai/api/v1'
models:
default: ['meta-llama/llama-3-70b-instruct']
fetch: true
titleConvo: true
titleModel: 'meta-llama/llama-3-70b-instruct'
dropParams: ['stop']
modelDisplayLabel: 'OpenRouter'
- name: 'Ollama'
apiKey: 'ollama'
baseURL: 'http://host.docker.internal:11434/v1/'
models:
default: ['llama3:latest', 'command-r', 'mixtral', 'phi3']
fetch: true
titleConvo: true
titleModel: 'current_model'
- name: 'Claude-Compatible'
provider: 'anthropic'
apiKey: '${ANTHROPIC_API_KEY}'
baseURL: 'https://api.anthropic.com'
headers:
anthropic-version: '2023-06-01'
models:
default: ['claude-sonnet-4-5']
fetch: false
titleConvo: true
titleModel: 'claude-sonnet-4-5'Browse all compatible providers in the AI Endpoints section. For the full field reference, see Custom Endpoint Object Structure.
Anthropic-Compatible Endpoints
Use provider: "anthropic" only for endpoints that speak the native Anthropic Messages API. For OpenAI-compatible gateways that merely expose Anthropic models, omit provider and use the regular OpenAI-compatible custom endpoint shape.
API Key Configuration
When configuring API keys in custom endpoints, you have three options:
- Environment variable (recommended):
apiKey: '${OPENROUTER_KEY}'reads one shared key from.env, so the key needs a matching entry in Step 3. - User provided:
apiKey: 'user_provided'asks each user for their own key in the LibreChat UI instead of reading one from.env. No.enventry is needed for the key itself. LibreChat stores each user's key encrypted and prompts for it the first time they select the endpoint. - Direct value (not recommended):
apiKey: 'sk-your-actual-key'hardcodes the key inlibrechat.yamlin plain text.
baseURL accepts user_provided in the same way, which lets each user point the endpoint at their own gateway.
The example above deliberately mixes styles: OpenRouter and the Anthropic-compatible gateway use option 1, while Ollama passes the literal string 'ollama' because a local Ollama server ignores the key entirely.
Step 3. Set Environment Variables
This step covers every ${VARIABLE_NAME} reference in your librechat.yaml, whether it sits in apiKey, baseURL, or a headers value. If nothing you added uses that form, skip to Step 4.
Add each variable your librechat.yaml references to .env. The example above references two:
OPENROUTER_KEY=your_openrouter_api_key
ANTHROPIC_API_KEY=your_anthropic_api_keyEvery ${VARIABLE_NAME} in librechat.yaml needs a matching entry. A missing one does not drop the endpoint: it still appears in the selector, and the problem only surfaces once someone sends a message through it. An unresolved apiKey fails with Missing API Key for <endpoint>, and an unresolved baseURL with Missing Base URL for <endpoint>. An unresolved headers value behaves differently: it is sent upstream as the literal text ${VARIABLE_NAME}, so the failure comes back from the provider rather than from LibreChat.
Step 4. Restart and Verify
After editing configuration files, you must restart LibreChat for changes to take effect.
docker compose down && docker compose up -dStop the running process (Ctrl+C) and restart:
npm run backendOpen LibreChat in your browser. Your custom endpoints should appear in the endpoint selector dropdown.
Not Seeing Your Endpoint? An Incomplete Block Is Dropped Silently
Start with the server logs:
docker compose logs apiBut do not stop there. LibreChat keeps a custom endpoint only if all of name, baseURL, apiKey, and models are present, and models has either fetch: true or a non-empty default list. An entry failing that check is removed from the endpoint list with no error and no log line at all: the provider simply never appears, and the logs look clean.
So when an endpoint is missing, check the block itself before hunting through logs:
- Is every one of
name,baseURL,apiKey,modelsspelled correctly? A single typo drops the whole entry. - Does
modelshavefetch: trueor at least one entry underdefault? - Is the block indented inside the
endpoints.customlist, rather than at the top level? - Is the
nameunique? A second endpoint with the same name (case-insensitively) silently replaces the first.
Compare your block against the Custom Endpoint Object Structure reference.
Also note that a schema error anywhere in librechat.yaml stops the server rather than disabling one section, so one bad block elsewhere can take every custom endpoint down with it. Validate syntax with the YAML Validator, which checks YAML syntax only, not LibreChat's schema.
OpenRouter Still Does Not Show Up
For OpenRouter specifically, verify the three-file chain:
.envhasOPENROUTER_KEY=...librechat.yamlhasapiKey: "${OPENROUTER_KEY}"under the OpenRouter custom endpoint- Docker users mounted
librechat.yamlindocker-compose.override.yml
Then restart with:
docker compose down && docker compose up -dIf the endpoint appears but returns 402 Payment Required, the request reached OpenRouter successfully and the issue is usually account credits, billing, or model availability on OpenRouter.
Next Steps
How is this guide?