Add an OpenAI-compatible endpoint to LibreChat

LibreChat is the one tool here where the bill lands on whoever owns the key. One endpoint, many people, and a handful of settings — fetch, titleConvo, titleModel — decide whether that arrangement is cheap or surprising.

In short: LibreChat defines custom endpoints under endpoints.custom in librechat.yaml, with keys referenced from .env and the file bind-mounted into the container. titleConvo adds one extra request per new conversation, so titleModel is worth pointing at a cheap model; fetch: true exposes the full catalogue unless you curate it.
Before you start: you need an endpoint root ending in /v1 and a key from that endpoint. The setting below is the only thing that changes — request and response handling stay identical. Rates checked 2026-09-26.

The setting

Custom endpoints live in librechat.yaml. One entry is enough:

version: 1.3.13
cache: true
endpoints:
  custom:
    - name: "MyGateway"
      apiKey: "${MY_GATEWAY_KEY}"
      baseURL: "https://aicomp.ai/v1"
      models:
        default: ["claude-sonnet-5", "deepseek-v4-pro", "gpt-5.6-luna"]
        fetch: false          # set true only if the endpoint serves /v1/models
      titleConvo: true
      titleModel: "gpt-5.6-luna"   # cheap model: titles are a whole extra call
      dropParams: ["stop"]
      modelDisplayLabel: "MyGateway"

The key should never sit in that file. Reference a variable, and put the value in .env:

MY_GATEWAY_KEY=sk-...

Under Docker the YAML also has to be mounted into the container, or the file is invisible to the application and the endpoint will not appear no matter how correct it is:

# docker-compose.override.yml — without this the container cannot see librechat.yaml
services:
  api:
    volumes:
      - type: bind
        source: ./librechat.yaml
        target: /app/librechat.yaml

Restart after any change — configuration is read at startup, not watched.

What a shared deployment costs

Take ten people on a working day: forty messages each, each carrying roughly 6k tokens of conversation history and producing about 500 back. That is 2.4M input and 200k output per day, before titles. With titleConvo on and around thirty new conversations a day, add another 15k input and 600 output — small, but recurring and easy to forget.

Ten people, 40 messages each per working day, 30 new conversations, 20 working days. Rates checked 2026-09-26.
ModelVendorRate
in / out per 1M
Per monthInput share
of the bill
Per year
gpt-5.6-lunaOpenAI$0.1 / $0.6$7.2467%$7
MiniMax-M3MiniMax$0.15 / $0.6$9.6575%$10
deepseek-v4-flashDeepSeek$0.22 / $0.66$13.2780%$13
gemini-3.7-flashGoogle$0.375 / $1.875$25.6371%$26
claude-haiku-4-5-20251001Anthropic$0.5 / $2.5$34.1871%$34
deepseek-v4-proDeepSeek$0.66 / $1.98$39.8280%$40
glm-5.3Zhipu$0.7 / $2.2$42.6479%$43
qwen3.8-maxAlibaba$1 / $3$60.3480%$60
claude-sonnet-5Anthropic$1 / $5$68.3671%$68
gpt-5.6-terraOpenAI$1 / $6$72.3767%$72
kimi-k3Moonshot$1.5 / $7.5$102.5471%$103
claude-opus-5Anthropic$2.5 / $12.5$170.9071%$171

Input is between 67% and 80% of that monthly figure — noticeably less dominant than the agent workload on the OpenHands page, because a chat window carries far less history per turn than an agent loop resends. It also makes titleConvo worth quantifying: six hundred new conversations a month at 500 input and 20 output tokens each comes to 0.5%–0.6% of the monthly bill. Small, but it is a cost that exists only because a setting is on, and pointing titleModel at the cheapest model in the table removes most of it without turning the feature off.

Cost note. The ratio here is about 12:1, not the 150:1 an agent loop produces. Output is now a visible line in the bill rather than rounding error, so a model that looks cheap on input alone is not automatically the cheap one — but input still decides the ranking.

The lever with the best ratio of effort to effect is titleModel. Titles are generated for every new conversation and the job does not need a flagship model; pointing it at an inexpensive one keeps the feature and removes most of its cost.

How this fails in practice

The failures that account for most setup problems, and what each one actually means.
What you seeWhat it usually isFix
Endpoint never appears in the dropdownlibrechat.yaml not mounted into the containerAdd the bind mount in docker-compose.override.yml, then restart
Changes have no effectConfiguration is read at startup onlyRestart the stack after every edit
fetch: true throws an errorEndpoint does not serve /v1/modelsSet fetch: false and list the models yourself
Requests land on the wrong providerEnvironment variable named differently from what the integration expectsUse the exact variable name from the docs; confirm in the usage log
Bill higher than expected with no obvious causetitleConvo generating titles on an expensive modelSet titleModel to an inexpensive model
Users pick up a model nobody budgeted forfetch: true exposes the full catalogueSet fetch: false and curate the list
You need a key before the code below runs. Create an account, generate a key, and copy the base URL (https://aicomp.ai/v1). Create one free →
Check current rates → Free to sign up · $1 minimum top-up · No prepayment

Confirming it took effect

Send one message on the new endpoint and then read the usage log. A request recorded there is the only real confirmation — an answer in the browser can come from the built-in provider just as easily, and nothing on screen distinguishes the two. With a shared key it is also worth reading that log per model, because a total figure hides which model is driving the spend until the invoice arrives.

FAQ

Where does LibreChat store a custom endpoint?

In librechat.yaml, under endpoints.custom. Each entry takes a name, an apiKey, a baseURL and a models block. Keys belong in .env and are referenced from the YAML with variable syntax, so the config file itself stays safe to commit. Docker users also need a bind mount in docker-compose.override.yml — without it the container cannot see the file at all, which is the single most common reason an endpoint silently never appears.

Should I use fetch: true or list models manually?

fetch: true asks the endpoint's /v1/models for its catalogue and keeps the list current as models are added. It fails on endpoints that do not serve that route, and it cannot be combined with a curated list. If you want the dropdown to show only the models you actually intend to pay for, set fetch: false and list them — which also stops someone in a shared deployment discovering an expensive model you never budgeted for.

What is titleConvo costing me?

One extra request per new conversation, to generate the conversation title. It is small per conversation and invisible per user, but on a team deployment it is a steady stream of calls whose only job is naming a chat. Setting titleModel to an inexpensive model keeps the feature and removes nearly all of the cost, which is a better outcome than switching the feature off.

Can each user supply their own key?

Yes — set the endpoint's apiKey to user_provided and LibreChat shows a key field when that endpoint is selected. This is the right choice when the deployment is shared but the spending should not be: each person's usage lands on their own account, and you stop being the one who explains the bill. It does mean users have to obtain a key before they can use the endpoint.

Why does my endpoint not show up after I edited the file?

Configuration is read at startup, so an edit alone changes nothing — restart the stack. If it still does not appear, the container most likely cannot see the file: check the bind mount in docker-compose.override.yml and confirm the source path is relative to where Compose is run. A YAML indentation error produces the same symptom, so validate the file before assuming the mount is wrong.

Is there a naming trap with the environment variables?

Yes, and it is specific. Some integrations expect a particular variable name, and using the wrong one does not merely fail — it can redirect the built-in provider as well, so requests you thought went to one place go to another. Use the variable name the documentation for your endpoint specifies exactly, and check the usage log after changing it.

How do I keep a shared deployment from getting expensive?

Three things, in order of effect. Curate the model list with fetch: false so only the models you intend to pay for are reachable. Point title generation at a cheap model. And read the usage log per model rather than in total, because a shared key hides which model — and sometimes which person — is driving the spend until the invoice arrives.

Related

Get API access