Key to first token in about a minute
Nyx is one OpenAI-compatible endpoint in front of fourteen open-weight
models. Point your existing SDK at
https://nyxprovider.com/v1, keep every line of request
code you already have, and stream tokens with 71µs median routing
overhead. Everything on this page runs against production.
Overview
Nyx serves open-weight models behind the OpenAI chat completions schema. There is one base URL for every model, every region, and every plan:
https://nyxprovider.com/v1
Every official OpenAI SDK works unchanged. Set base_url
to https://nyxprovider.com/v1, pass a Nyx key, and pick
a model id from the catalog. The router adds
71µs at p50 and 235µs at p99 between your request and the model
server, and prices for all fourteen models are published live at
/v1/models, so a client can read them
programmatically before sending a single prompt.
POST /v1/chat/completions, streaming and non-streaming, on every model.GET /v1/models, the catalog with per-token prices in the response body.- Prompt caching bills repeated prefixes at the cached rate automatically, with no request changes.
- Token usage arrives in the final chunk of every streamed response.
Authentication
Requests authenticate with a bearer token in the
Authorization header. Keys start with
nyx_sk_ and are shown once at creation. A key is scoped
to your account, works on every model, and can be revoked from the
console without affecting other keys.
# any authenticated request, here the model catalog
curl https://nyxprovider.com/v1/models \
-H "Authorization: Bearer nyx_sk_live_8f2ac41d77e09b63"
Keys belong on servers only. Never embed one in a browser bundle, a mobile app, or a public notebook. Anyone holding the key can spend against your account until you revoke it, so route browser and mobile traffic through your own backend and keep the key in an environment variable there.
Chat completions
POST /v1/chat/completions takes the OpenAI request
body: a model id, a messages array, and optional
sampling parameters. The response schema matches OpenAI's field for
field, so response parsing, retry wrappers, and logging middleware
you already run keep working.
curl https://nyxprovider.com/v1/chat/completions \
-H "Authorization: Bearer $NYX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-oss-120b",
"stream": true,
"max_tokens": 400,
"messages": [
{"role": "system", "content": "Answer in two sentences."},
{"role": "user", "content": "Why does KV cache reuse cut latency?"}
]
}'
Parameters
| Parameter | Type | Notes |
|---|---|---|
| model | string, required | A model id from /v1/models, for example gpt-oss-120b or kimi-k3. |
| messages | array, required | Chat turns with role and content, OpenAI schema. |
| stream | boolean | Defaults to false. Set true for server-sent events. |
| max_tokens | integer | Hard cap on generated tokens. Defaults to the model's context limit minus the prompt. |
| temperature | number | 0 to 2, defaults to 1.0. Lower is more deterministic. |
Streaming
With stream: true the response is server-sent events,
relayed byte for byte. The router never buffers, reframes, or
batches chunks: the bytes the model server emits are the bytes your
client reads, which is why time-to-first-token on Nyx tracks the
model itself rather than the proxy in front of it.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://nyxprovider.com/v1",
api_key=os.environ["NYX_API_KEY"],
)
stream = client.chat.completions.create(
model="gpt-oss-120b",
stream=True,
messages=[{"role": "user", "content": "Explain SSE in one paragraph."}],
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
The final data event before the stream closes is the literal
sentinel data: [DONE], exactly as OpenAI sends it. SDKs
handle it for you; if you parse SSE by hand, stop reading when you
see it. Usage counts arrive in the last JSON chunk before the
sentinel.
List models
GET /v1/models returns every model currently routable,
with context length and the live per-million-token price in the
same response. The price in this endpoint is the price you are
billed, and the pricing page renders from
the same data.
{
"object": "list",
"data": [
{
"id": "gpt-oss-120b",
"object": "model",
"context_length": 131072,
"pricing": {
"input_per_mtok": 0.0273,
"output_per_mtok": 0.1547
}
},
{
"id": "kimi-k3",
"object": "model",
"context_length": 1000000,
"pricing": {
"input_per_mtok": 2.548,
"output_per_mtok": 12.74
}
}
// ... 8 more models, trimmed here
]
}
The endpoint needs no authentication for reads, so a deploy pipeline can verify a model id exists before shipping, and a cost dashboard can poll current prices without holding a key.
Errors
Errors use standard HTTP status codes with an OpenAI-shaped JSON
body containing error.message and
error.type.
| Status | Meaning | What to do |
|---|---|---|
| 400 | Invalid request body or parameters. | Fix the request. The message names the offending field. |
| 401 | Missing, malformed, or revoked key. | Check the Authorization header and the key in your console. |
| 404 | Unknown model id. | Pick an id from GET /v1/models. |
| 429 | Over declared capacity. | Wait the number of seconds in the Retry-After header, then retry. |
| 500 | Upstream model server fault. | Retry with backoff. These are rare and counted against our uptime. |
Backpressure is honest. When a model is at its declared capacity,
Nyx returns 429 immediately, in microseconds, with a
Retry-After header. It never accepts the request into
a hidden queue that times out 30 seconds later, so your retry
logic sees the real state of the fleet the moment it exists and a
slow failure never masquerades as a slow success.
SDKs
There is no Nyx SDK to install, on purpose. The official OpenAI libraries for Python and JavaScript are the supported clients, and any OpenAI-compatible client, framework, or gateway works by changing the base URL and key.
# pip install openai
import os
from openai import OpenAI
client = OpenAI(
base_url="https://nyxprovider.com/v1",
api_key=os.environ["NYX_API_KEY"],
)
r = client.chat.completions.create(
model="deepseek-v3.2",
messages=[{"role": "user", "content": "Say hello."}],
)
print(r.choices[0].message.content)
// npm install openai
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://nyxprovider.com/v1",
apiKey: process.env.NYX_API_KEY,
});
const r = await client.chat.completions.create({
model: "qwen3-coder-next",
messages: [{ role: "user", content: "Say hello." }],
});
console.log(r.choices[0].message.content);
LangChain, LlamaIndex, Vercel AI SDK, LiteLLM, and curl all speak this protocol already. If a tool accepts an OpenAI base URL, it runs on Nyx with no adapter.