# Custom Endpoints (https://www.librechat.ai/docs/quick_start/custom_endpoints)

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.

<Callout type="info" title="Which File Does What?">

Custom endpoint setup involves three files, each with a specific role:

1. **`librechat.yaml`** -- Defines your custom endpoints (name, API URL, models, display settings)
2. **`.env`** -- Stores sensitive values like API keys (referenced from librechat.yaml using `${VAR_NAME}` syntax)
3. **`docker-compose.override.yml`** -- Mounts `librechat.yaml` into the Docker container (Docker users only)

For a full overview of how these files work together, see the [Configuration Overview](/docs/configuration).

</Callout>

<Callout type="warning" title="Before You Start">

This guide assumes you have LibreChat installed and running. If not, complete the [Docker setup](/docs/local/docker) first.

</Callout>

## 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.

```bash
cp docker-compose.override.yml.example docker-compose.override.yml
```

Edit `docker-compose.override.yml` and ensure the volume mount is uncommented:

```yaml filename="docker-compose.override.yml"
services:
  api:
    volumes:
      - type: bind
        source: ./librechat.yaml
        target: /app/librechat.yaml
```

Learn more: [Docker Override Guide](/docs/configuration/docker_override)

## 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](/docs/configuration/librechat_yaml) for detailed setup instructions.

Here is an example with **OpenRouter**, **Ollama**, and an Anthropic-compatible gateway:

```yaml filename="librechat.yaml"
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](/docs/configuration/librechat_yaml/ai_endpoints) section. For the full field reference, see [Custom Endpoint Object Structure](/docs/configuration/librechat_yaml/object_structure/custom_endpoint).

<Callout type="note" title="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.

</Callout>

<Callout type="warning" title="API Key Configuration">

When configuring API keys in custom endpoints, you have three options:

1. **Environment variable** (recommended): `apiKey: '${OPENROUTER_KEY}'` reads one shared key from `.env`, so the key needs a matching entry in [Step 3](#step-3-set-environment-variables).
2. **User provided**: `apiKey: 'user_provided'` asks each user for their own key in the LibreChat UI instead of reading one from `.env`. No `.env` entry is needed for the key itself. LibreChat stores each user's key encrypted and prompts for it the first time they select the endpoint.
3. **Direct value** (not recommended): `apiKey: 'sk-your-actual-key'` hardcodes the key in `librechat.yaml` in 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.

</Callout>

## 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](#step-4-restart-and-verify).

Add each variable your `librechat.yaml` references to `.env`. The example above references two:

```bash filename=".env"
OPENROUTER_KEY=your_openrouter_api_key
ANTHROPIC_API_KEY=your_anthropic_api_key
```

Every `${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.

<Tabs items={['Docker', 'Local']}>
  <Tabs.Tab>

```bash
docker compose down && docker compose up -d
```

  </Tabs.Tab>
  <Tabs.Tab>

Stop the running process (Ctrl+C) and restart:

```bash
npm run backend
```

  </Tabs.Tab>
</Tabs>

Open LibreChat in your browser. Your custom endpoints should appear in the endpoint selector dropdown.

<Callout type="warning" title="Not Seeing Your Endpoint? An Incomplete Block Is Dropped Silently">

Start with the server logs:

```bash
docker compose logs api
```

**But 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`, `models` spelled correctly? A single typo drops the whole entry.
- Does `models` have `fetch: true` or at least one entry under `default`?
- Is the block indented **inside** the `endpoints.custom` list, rather than at the top level?
- Is the `name` unique? A second endpoint with the same name (case-insensitively) silently replaces the first.

Compare your block against the [Custom Endpoint Object Structure](/docs/configuration/librechat_yaml/object_structure/custom_endpoint) 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](/docs/toolkit/yaml-validator), which checks YAML syntax only, not LibreChat's schema.

</Callout>

### OpenRouter Still Does Not Show Up

For OpenRouter specifically, verify the three-file chain:

1. `.env` has `OPENROUTER_KEY=...`
2. `librechat.yaml` has `apiKey: "${OPENROUTER_KEY}"` under the OpenRouter custom endpoint
3. Docker users mounted `librechat.yaml` in `docker-compose.override.yml`

Then restart with:

```bash
docker compose down && docker compose up -d
```

If 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

<Cards num={2}>
  <Cards.Card title="AI Endpoints" href="/docs/configuration/librechat_yaml/ai_endpoints" arrow>
    Browse all compatible AI providers with example configurations
  </Cards.Card>
  <Cards.Card title="librechat.yaml Guide" href="/docs/configuration/librechat_yaml" arrow>
    Full setup guide and reference for the config file
  </Cards.Card>
</Cards>
