Jan with a Custom OpenAI-Compatible Endpoint

In short: Jan asks for the API format before the URL, and the format describes the protocol the endpoint speaks rather than who made the model — an OpenAI-speaking gateway needs OpenAI-compatible even for Claude models. The base URL must carry /v1 and the key field is mandatory even for a local server. Capabilities are not inferred, so tools stay off until enabled per model.

Jan is a local-first desktop assistant: it runs models on your machine, and it also connects to remote providers that speak the OpenAI or Anthropic wire format. Adding a gateway is a four-field dialog, and the order of those fields matters more than it looks.

The API format is chosen before the URL, and picking the wrong one fails every request even when the base URL and key are both correct. The format tells Jan how to build requests and parse responses — it describes the protocol your endpoint speaks, not who made the model. The base URL has to include /v1 for OpenAI-compatible servers, and the API key is mandatory even when nothing on the other end checks it.

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

This page covers the dialog, why a wrong format cannot be debugged from the URL, and what a month of Jan sessions costs once a remote provider is in the mix.

The four fields

Open Settings, go to Model Providers, and click Add Provider. The dialog asks for:

FieldWhat goes in it
Provider nameAny unique name — this is what shows in the model selector
API formatOpenAI-compatible (default) or Anthropic-compatible
Base URLThe root of the API, including the version path
API keyRequired

For an OpenAI-compatible gateway:

Provider name:  My Gateway
API format:     OpenAI-compatible
Base URL:       https://gw.example.com/v1
API key:        sk-your-gateway-key

Jan strips trailing slashes automatically, so a URL ending in /v1/ is fine. What it does not do is add the version path for you: entering https://gw.example.com for a server that expects /v1 produces a 404 on every request, because Jan appends the operation path — /chat/completions — onto whatever you supplied and ends up at /chat/completions instead of /v1/chat/completions.

Do not append /chat/completions yourself either. Jan builds that part.

The format field describes the endpoint, not the model

This is the field people get wrong, and it is wrong in a specific direction.

The choice is between OpenAI-compatible and Anthropic-compatible, and it tells Jan which request shape to send and which response shape to parse. It has nothing to do with which company made the model. If your gateway exposes the OpenAI Chat Completions API — most do, including ones that go on to serve Claude models — you pick OpenAI-compatible, even for an Anthropic-created model.

Pick Anthropic-compatible against an OpenAI-speaking endpoint and every request fails, with the base URL and key both correct and both irrelevant. The error does not mention the format, so the natural next move is to re-check the URL, which is already fine.

The key is required even when nothing checks it

Jan requires a non-empty API key for custom providers. For a local server that does not authenticate — vLLM, Ollama, llama.cpp server on your own machine — put any placeholder there. The documented example is sk-no-key. Leave it blank and the provider will not save.

Models: discovered once, then by hand

When you save the provider, Jan requests {base_url}/models and populates the list from what comes back. If your endpoint does not expose that route, or returns an empty list, nothing appears — and the fix is not to change the base URL. Open the provider's Models section, click +, and enter the model id exactly as your server expects it.

There is a second, quieter consequence. Jan does not infer capabilities for custom providers. It cannot tell whether a model supports tools, vision or audio, so those switches stay off until you enable them per model. A model that supports tool calling will simply never call a tool. Enable only what the model actually declares — a UI toggle cannot add an API capability the endpoint does not have.

Key rotation covers three status codes

Jan accepts several keys per provider. Under the provider's API keys section, click Advanced and add them; #1 is primary and the rest are fallbacks. There is a Test keys action that calls {base_url}/models per key and reports the result for each.

Rotation is narrower than it sounds: Jan only tries the next key on HTTP 401, 403 or 429. Every other error — a 404 from a wrong path, a 500 from the upstream, a model id that does not exist — returns immediately without trying another key. Treat the fallback list as resilience against auth and rate limits, not as a general retry.

A 429 across every configured key means you are being rate limited at the account level, and no amount of rotation helps.

Across 219 catalogue models that publish both rates, the median output rate is 4.0× the input rate, and 68% of them (150 models) charge at least 4× more for output than input. The other 624 raw catalogue entries are dropped by cleaning — test entries, dated snapshots and non-chat variants — not for a missing rate. This is why an agent workload is decided on the output column, not the input one everyone quotes.

What remote sessions cost

Jan's default posture is local, where the bill is electricity. Adding a remote gateway changes that, and the shape of a chat session is predictable: each turn re-sends the conversation so far, so input grows with the length of the thread while output stays roughly one message per turn.

A day of work on this page's workload is 140k input and 30k output tokens — 2.8M input and 0.6M output across 20 working days. That is smaller than a coding agent's footprint, because Jan is a chat interface rather than a loop that reads files it did not ask for. The local models stay available alongside the remote one, so the cheapest configuration is usually a cheap remote model for long threads and a local one for quick questions. See output vs input pricing for the general rule.

Per 1M input / output tokens and a 20-day month
ModelGateway rate
in / out per 1M tokens
One day20 days
gpt-5.6-luna$0.10 / $0.60$0.03$0.64
gemini-3.7-flash$0.375 / $1.875$0.11$2.17
llama-4-maverick$0.07 / $0.35$0.02$0.41
gpt-5-mini$0.125 / $1.00$0.05$0.95
o3$1.00 / $4.00$0.26$5.20

One day = 140k input + 30k output on this page's workload. 20 days = 2.8M input and 0.6M output. Rates checked 2026-10-11 — gateway rates move with upstream promotions, so verify the current number in your dashboard before committing to a budget.

Verifying the route

  1. Choose OpenAI-compatible unless your gateway documents the Anthropic Messages API. The format is about the protocol, not the model's maker.
  2. Include /v1 in the base URL and do not append /chat/completions. Jan adds the operation path.
  3. Put something in the key field even for a local server — sk-no-key is the documented placeholder.
  4. Run Test keys. It reports per-key status against {base_url}/models, which separates a bad key from a wrong URL.
  5. Add models by hand if the list is empty, then enable the capabilities that model actually has.

FAQ

FAQ

Why does every request fail when the URL and key are right?

The API format is wrong. It must match the protocol your endpoint speaks — an OpenAI-speaking gateway needs OpenAI-compatible even when it serves Anthropic-created models.

Do I need /v1 in the base URL?

Yes, for OpenAI-compatible servers. Without it the request lands on /chat/completions instead of /v1/chat/completions and returns 404.

Can I leave the API key blank for a local server?

No. The field is required; use any non-empty placeholder such as sk-no-key when the server does not check.

No models appear in the selector

Jan queried {base_url}/models when you saved and got nothing usable. Add the model id manually in the provider's Models section — do not change the base URL to chase it.

Why does my model never call tools?

Capabilities are not detected for custom providers. Enable tools for that specific model in the provider settings, and only if the model actually supports them.

Will Jan try my backup key on any error?

Only on 401, 403 and 429. Other errors return immediately.

Related

Get API access