The oMLX API key, port and endpoints
Table of contents
- Key takeaways
- The eight endpoints the server exposes
- The API key and sub-keys
- Resetting or rotating the key
- When you do not want a key
- How the key is sent
- The default port and how to change it
- The precedence order
- Frequently asked questions
- Do I need an API key to use oMLX locally?
- What is the difference between the main key and a sub-key?
- Why will my Anthropic client not authenticate against oMLX?
- Conclusion
- Sources
oMLX listens on 127.0.0.1:8000 by default and exposes eight endpoints compatible with OpenAI and Anthropic. The API key travels in the Authorization header or in x-api-key, supports sub-keys that only call the API, and can be skipped for local connections. Everything is configurable through settings.json, environment variables or flags.
oMLX does not invent its own API: it imitates two that already exist, OpenAI’s and Anthropic’s, so any client written against either points at your Mac by changing one address. This guide covers the eight endpoints it exposes, how the API key works along with its sub-keys, what the default port is and how to change it without breaking the service.
Key takeaways
- The server listens on
127.0.0.1port8000. It only accepts local connections while you leavehostalone. - The key travels in
Authorization: Beareror inx-api-key; the second exists for Anthropic SDK compatibility. - There are three separate credentials: the main key, API-only sub-keys and admin session tokens.
- Settings resolve in a cascade: command flags, then
OMLX_*environment variables, then~/.omlx/settings.json, then the built-in defaults. - Changes made from the panel apply without restarting the server. Ones you hand-edit into the file do not.
The eight endpoints the server exposes
oMLX speaks three dialects at once over the same port. Most routes are OpenAI’s API verbatim, one is Anthropic’s, and a third exists for Codex.
| Method | Route | What it is for |
|---|---|---|
| POST | /v1/chat/completions |
Streaming chat, OpenAI’s format |
| POST | /v1/completions |
Plain text completion |
| POST | /v1/messages |
Anthropic Messages API |
| POST | /v1/responses |
Codex compatibility |
| POST | /v1/embeddings |
Embeddings |
| POST | /v1/rerank |
Document reranking |
| POST | /v1/mcp/tools |
Model Context Protocol tools |
| GET | /v1/models |
Catalogue of available models |
Having both /v1/chat/completions and /v1/messages on the same server is what lets Claude Code and an OpenAI library work against the same loaded model without duplicating memory. Both endpoints reach the same engine pool.
/v1/rerank and /v1/embeddings are the ones that make this usable for semantic search. With an embedding model and a reranker loaded, you have both halves of a retrieval pipeline without leaving the Mac. If you have built this with other tools, the comparison with llama.cpp optimisations is instructive.
The API key and sub-keys
oMLX distinguishes three credentials, and the difference matters more than it looks:
- Main key. Grants access to the inference endpoints and to the admin dashboard as well. It is the one you set at startup.
- Sub-keys. They only call the API. They cannot log into the panel or change settings. These are what you hand out to applications consuming the server.
- Session tokens. Generated by the panel after logging in with the main key. They live in the
omlx_admin_sessioncookie, signed withitsdangerous.URLSafeTimedSerializer. They last 24 hours, or 30 days if you tick remember me.
The most direct way to set the main key is at server startup:
omlx serve --model-dir ~/models --api-key your-secret-key
Validation is deliberately loose: at least four characters, no whitespace, printable characters only. That means the server will accept 1234 without complaint. The check runs through secrets.compare_digest, in constant time, so the key cannot be deduced by measuring how long a rejection takes.
One detail anyone who has ever chased a leaked credential will appreciate: in the logs the key appears as a truncated SHA-256 fingerprint, never in the clear.
Resetting or rotating the key
There is no dedicated command. The key lives in the configuration, so it changes through the same three paths as any other setting: the panel’s global settings, editing ~/.omlx/settings.json, or restarting with a different --api-key. Rotating the main key invalidates open panel sessions; rotating a sub-key only affects the application that used it.
If you have lost the key and cannot get into the panel, the way out is to stop the service, edit the configuration file by hand and start again.
When you do not want a key
On a desktop machine where the server only listens on 127.0.0.1, demanding a key adds friction without buying real security. The panel’s global settings let you skip verification for local connections. That is reasonable as long as host stays 127.0.0.1.
The moment you change host to 0.0.0.0 to reach it from another machine, that decision inverts: the server becomes reachable from the network and a key stops being optional. And since CORS origins default to ["*"], any web page open in a browser on that network could talk to it. Adjust both together or adjust neither.
How the key is sent
Both headers are equivalent as far as the server is concerned:
curl http://127.0.0.1:8000/v1/models \
-H "Authorization: Bearer your-secret-key"
curl http://127.0.0.1:8000/v1/models \
-H "x-api-key: your-secret-key"
The second exists because the Anthropic SDK sends x-api-key rather than Authorization. If you are talking to it with an OpenAI library, use the first and you will not have to touch anything.
A full chat call, to confirm the model answers:
curl http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-secret-key" \
-d '{
"model": "qwen3-8b",
"messages": [{"role": "user", "content": "Answer in one sentence: what is MLX?"}],
"max_tokens": 128,
"stream": false
}'
The model field accepts either the model’s directory name or the alias you gave it in the panel. /v1/models returns the alias, so if the catalogue shows you one name and requests fail with another, you are mixing the two.
The default port and how to change it
The port is 8000 and there are three ways to change it, which override each other in a specific order:
omlx serve --model-dir ~/models --port 8080
OMLX_PORT=8080 omlx serve --model-dir ~/models
Or permanently, in ~/.omlx/settings.json:
{
"host": "127.0.0.1",
"port": 8080,
"log_level": "info",
"cors_origins": ["*"],
"max_concurrent_requests": 8
}
The file is what matters if you run oMLX as a Homebrew service, because that service executes omlx serve with no arguments: flags never reach it. I go through this in the Homebrew installation guide.
The precedence order
Four layers, strongest first:
- Command arguments (
--port,--api-key,--model-dir). - The
OMLX_*environment variables (OMLX_PORT,OMLX_MODEL_DIR,OMLX_BASE_PATH,OMLX_SECRET_KEY). - The
~/.omlx/settings.jsonfile. - The code’s built-in defaults.
This explains the commonest failure when changing port: you edit the file, restart, and the server is still on 8000 because a flag or an environment variable sits above it. Check what arguments it actually started with using brew services info omlx.
OMLX_SECRET_KEY deserves its own note. If you do not define it, the server generates a random value at every startup, which invalidates every panel session each time you restart. Pinning it in the service environment is what stops you having to log in again after every upgrade.
Frequently asked questions
Do I need an API key to use oMLX locally?
No. If the server listens only on 127.0.0.1, the panel’s global settings let you skip key verification for local connections. Set a key as soon as you expose the server to the network by changing host, because CORS origins are open by default.
What is the difference between the main key and a sub-key?
The main key opens the inference endpoints and also lets you into the admin panel and change settings. A sub-key only calls the API. Hand out sub-keys to applications and keep the main one for yourself.
Why will my Anthropic client not authenticate against oMLX?
Almost always because it sends the key in x-api-key while you expect Authorization, or the other way round. oMLX accepts both, so if it fails check the base address first: Claude Code needs ANTHROPIC_BASE_URL pointing at your server and ANTHROPIC_AUTH_TOKEN holding the key.
Conclusion
The oMLX API is deliberately boring, and that is the best thing you can say about it. There is no bespoke format to learn: if your code already talks to OpenAI or Anthropic, changing the base address and the key is enough. The decisions that do need making are two, and they travel together: whether the server listens beyond 127.0.0.1 and whether you require a key. Changing the first without changing the second is the one configuration mistake that can hurt.
The natural next step is the admin dashboard, where models are loaded and tuned one by one: I cover it in the oMLX dashboard and command line. The Spanish version of this article is at Clave de API, puerto y endpoints de oMLX.
Sources
Source code
Access all the source code for this post on GitHub.
View on GitHub