Base URLs
Anthropic clients append
/v1/messages to whatever base URL you give them, so
https://api.nemu.cc works as an Anthropic base URL too: both
https://api.nemu.cc/v1/messages and https://api.nemu.cc/anthropic/v1/messages
serve the Messages API.
Authentication
Send the gateway key either way. Anthropic clients tend to usex-api-key,
OpenAI clients use the bearer header, and Nemu accepts both on every endpoint.
sk_xxxxx-xxxxx. followed by a
40 character secret. A key belongs to one workspace and can only reach the
providers and models enabled in that workspace.
Endpoints
Liveness and readiness
GET /health answers whether the gateway process is up. It reads nothing and
depends on nothing, so it stays fast and stays honest about one thing only.
GET /ready additionally checks that the gateway can reach its database and its
cache, within a two second budget. It answers 200 with "status": "ok" when
both respond and 503 with "status": "degraded" when either does not or is
too slow. Use /health to ask whether the process is alive and /ready to ask
whether it can serve a request.
commit is the git commit the running build was made from, and it is also
returned by GET /v1/health and GET /anthropic/health, which both require a
key. version is the release version and moves independently of it.
Choosing a model
GET /v1/models returns exactly the strings you can put in model. Each one is
the model’s gateway name: the provider name, a slash, and the alias you gave
it in the console.
anthropic/fable-5.1 can
point at claude-fable-5-1 upstream. Edit it under Models in the console.
The gateway name is the only model name a client may send. The upstream id is
not accepted, so nothing you run can address a provider model that you have not
deliberately exposed, and renaming a model in the console changes the name your
clients use without touching the provider.
Two other values are accepted in model:
- A mapping. Mappings match a pattern and rewrite it to a gateway name, which
is how you keep a client that hardcodes
gpt-4opointed at whatever you want. auto. When automatic routing is configured, Nemu picks the model.
Variants
A gateway name can carry a variant in square brackets, the way some clients writeclaude-opus-5[1m]. The variant is stripped before the model is resolved, so
anthropic/fable-5.1[1m] addresses anthropic/fable-5.1. [1m] asks for a
one million token context: it raises the accounted context window and, for
Anthropic providers, sends the context-1m-2025-08-07 beta header upstream.
The window is only ever raised, never lowered. On a model that already reaches a
million tokens, as anthropic/fable-5.1 does, the suffix changes nothing and is
accepted anyway. That is the point of it: a client can append [1m] to every
model name it sends without keeping track of which models need asking and which
already have the context. The beta header still goes upstream on an Anthropic
provider even when the model did not need it.
Three spellings address the same variant: [1m], [1m-context] and
[context-1m]. Case and surrounding spaces are ignored, so [1M] and [ 1m ]
both work. Anything else inside the brackets is stripped from the name and then
ignored, so anthropic/fable-5.1[turbo] resolves to anthropic/fable-5.1 and
asks for nothing rather than failing. The exception is a bracketed string longer
than sixteen characters, which is not read as a variant at all: it stays part of
the model name, and the lookup then fails because no model is called that.
Compatibility
Nemu speaks three wire protocols on the way in and translates to whatever the upstream provider speaks. An Anthropic-shaped request can be served by an OpenAI-compatible provider and the other way round: system blocks, tool calls, streaming events, thinking blocks and cache breakpoints are converted in both directions. Reasoning is handled per model. Anthropic-stylethinking budgets, OpenAI-style
reasoning_effort and adaptive modes are mapped to whatever the target model
actually supports, so a request that asks for thinking on a model without it
succeeds instead of failing with a 400.
The full list of what is translated, what comes back and what is dropped is on
Any model through any API.
Errors
Every error says which side failed. Thex-nemu-error-origin response header is
nemu when the gateway stopped the request and provider when the upstream did,
so a 402 from your provider’s billing is never confused with a 402 from your
nemu budget.
{"type":"error","error":{...}} shape
with the matching invalid_request_error, authentication_error,
not_found_error, rate_limit_error or overloaded_error type.
When an upstream provider explains itself, that explanation reaches you in place
of the gateway’s own description of the status, whether the provider sends an
error object or a plain reason. A reason that only repeats the status, such as
Not Found on a 404, is replaced by the fuller description instead.
If the provider fails partway through a streamed reply, the tokens it delivered
before failing are counted against your quotas and budget, and the request shows
under Metrics as failed with that cost. A request that fails before any output
costs nothing.
Errors that the gateway itself raised end with a reference, as in
... (id: 6f1c2a9e-...). That is the id of the request’s row under Metrics,
so a report can be traced to the exact request without guessing.
Limits and accounting
Requests are counted against your plan and against any quota rules and monthly budget set for the workspace. A 429 carriesRetry-After and the limit that was
hit, so a client can pace itself instead of guessing.
When the gateway is overloaded
Separately from your own limits, the gateway watches the load on the machine it runs on. When processor or memory use stays above 90 percent for a full minute, it stops accepting new requests and answers529 with an overloaded_error and
a Retry-After header. Work already in flight is never interrupted, so a
response that has started streaming finishes normally.
529, and so
is one that arrives when the queue is already full.
Retry-After is 10 seconds while requests are being refused and 30 seconds once
they are being queued. Both states clear on their own once the machine has been
below the threshold for 30 seconds. Live state is published at
status.nemu.cc.
Request bodies are capped per plan, which matters for coding agents because the
whole conversation is resent every turn:
Going over returns a 413 naming both the size sent and the limit.
Every request lands in Metrics with its model, provider, latency, token
counts, cost and origin. Requests that came from nemu’s own chat are labelled as
such rather than showing an internal address.