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.
/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.
| Model | Vendor | Rate in / out per 1M | Per month | Input share of the bill | Per year |
|---|---|---|---|---|---|
| gpt-5.6-luna | OpenAI | $0.1 / $0.6 | $7.24 | 67% | $7 |
| MiniMax-M3 | MiniMax | $0.15 / $0.6 | $9.65 | 75% | $10 |
| deepseek-v4-flash | DeepSeek | $0.22 / $0.66 | $13.27 | 80% | $13 |
| gemini-3.7-flash | $0.375 / $1.875 | $25.63 | 71% | $26 | |
| claude-haiku-4-5-20251001 | Anthropic | $0.5 / $2.5 | $34.18 | 71% | $34 |
| deepseek-v4-pro | DeepSeek | $0.66 / $1.98 | $39.82 | 80% | $40 |
| glm-5.3 | Zhipu | $0.7 / $2.2 | $42.64 | 79% | $43 |
| qwen3.8-max | Alibaba | $1 / $3 | $60.34 | 80% | $60 |
| claude-sonnet-5 | Anthropic | $1 / $5 | $68.36 | 71% | $68 |
| gpt-5.6-terra | OpenAI | $1 / $6 | $72.37 | 67% | $72 |
| kimi-k3 | Moonshot | $1.5 / $7.5 | $102.54 | 71% | $103 |
| claude-opus-5 | Anthropic | $2.5 / $12.5 | $170.90 | 71% | $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.
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
| What you see | What it usually is | Fix |
|---|---|---|
| Endpoint never appears in the dropdown | librechat.yaml not mounted into the container | Add the bind mount in docker-compose.override.yml, then restart |
| Changes have no effect | Configuration is read at startup only | Restart the stack after every edit |
| fetch: true throws an error | Endpoint does not serve /v1/models | Set fetch: false and list the models yourself |
| Requests land on the wrong provider | Environment variable named differently from what the integration expects | Use the exact variable name from the docs; confirm in the usage log |
| Bill higher than expected with no obvious cause | titleConvo generating titles on an expensive model | Set titleModel to an inexpensive model |
| Users pick up a model nobody budgeted for | fetch: true exposes the full catalogue | Set fetch: false and curate the list |
https://aicomp.ai/v1).
Create one free →
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.