API reference

The Nicrron API

OpenAI-compatible, so the official OpenAI SDKs work with only the base URL and key changed. This page lists what the gateway accepts and returns.

Also as an OpenAPI 3.1 file, and the whole docs index for language models at /llms.txt.

Base URL and keys

Send every request to https://api.nicrron.ai/v1 with your key in the Authorization header. Each path also answers under /api/v1. Keys are made in the dashboard; see Authentication for provider keys.

Header
Authorization: Bearer sk-af-…

Endpoints

Chat completions

POST /v1/chat/completions takes the OpenAI request body plus models and provider. Fields not listed here are accepted without checks.

modelstring
A model id such as anthropic/claude-sonnet-5-5, or a routing slug: nicrron/auto, nicrron/reasoning, nicrron/coding, nicrron/fastest, nicrron/cheapest. At most 256 characters.
modelsstring[]
Fallback models, tried in order after model. At most 10.
messagesobject[]
Required, at least one. role is system, user, assistant or tool; content is a string, an array of content parts (text, image_url) or null; name, tool_call_id and tool_calls as in the OpenAI API.
streamboolean
Send the answer as server-sent events. See Streaming.
max_tokensinteger
Upper bound on generated tokens. Greater than 0.
temperaturenumber
0 to 2. A temperature of 0 also turns the response cache on.
top_pnumber
0 to 1.
stopstring | string[]
Stop sequences.
frequency_penaltynumber
Passed to the provider.
presence_penaltynumber
Passed to the provider.
seedinteger
Passed to providers that support it.
tools, tool_choicearray, any
Function calling, in the OpenAI format.
response_formatobject
For example { "type": "json_object" }.
providerobject
Which providers may serve the request, and in what order. See Provider routing.
userstring
Your own end-user id.
cURL — request
curl https://api.nicrron.ai/v1/chat/completions \
  -H "Authorization: Bearer $NICRRON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nicrron/coding",
    "models": ["openai/gpt-6-sol"],
    "messages": [
      { "role": "system", "content": "Answer in one sentence." },
      { "role": "user", "content": "What does a 502 mean?" }
    ],
    "max_tokens": 200,
    "provider": { "sort": "latency" }
  }'

The answer is an OpenAI chat.completion. model is the model that actually answered and provider who served it. The id is also sent as the x-request-id header, and is the id for /v1/generation. When the provider reports prompt caching, usage also carries cache_read_tokens and cache_write_tokens.

Response
{
  "id": "gen-6f1c2a9e-…",
  "object": "chat.completion",
  "created": 1792345678,
  "model": "anthropic/claude-opus-5-5",
  "provider": "anthropic",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "A 502 means …" },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 24,
    "completion_tokens": 31,
    "total_tokens": 55
  }
}

Provider routing and fallback

A request is tried model by model (model, then models, with routing slugs expanded) and, within a model, endpoint by endpoint. It moves on when a provider rate-limits or fails before answering. Limits per request: 8 models after expansion, 6 endpoint attempts, and 90 seconds for something to answer. Without a provider object, traffic is spread over healthy endpoints and unhealthy ones are tried last.

orderstring[]
Try these providers first, in this order; the rest follow.
onlystring[]
Use only these providers.
ignorestring[]
Never use these providers.
sort"price" | "latency" | "throughput"
Order the endpoints by blended price, measured latency or tokens per second. Healthy endpoints always come before unhealthy ones.
allow_fallbacksboolean
false tries one endpoint per model instead of moving on to the next provider.

Response caching

A request with temperature: 0, or with the header x-nicrron-cache: true, is answered from cache when the identical request was answered before for your account. x-nicrron-cache: false turns it off. Every chat response carries x-nicrron-cache: HIT or MISS; a hit costs nothing and shows in your logs as cached. Answers that call tools, and streams that broke, are never cached.

Streaming

With stream: true the answer arrives as server-sent events of chat.completion.chunk. The last chunk has empty choices and the final usage, then data: [DONE]. If the provider stops partway, a chunk with an error (code 502) and finish_reason: "error" comes first; the part already generated is billed. Closing the connection stops generation upstream.

Event stream
data: {"id":"gen-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"A 502"}}]}

data: {"id":"gen-…","object":"chat.completion.chunk","model":"anthropic/claude-opus-5-5","provider":"anthropic","choices":[],"usage":{"prompt_tokens":24,"completion_tokens":31,"total_tokens":55}}

data: [DONE]

Rate limits and credits

Each key has a per-minute request limit: 60 unless the key was given its own. The window is the calendar minute. Every authenticated response carries x-ratelimit-limit and x-ratelimit-remaining; a 429 also carries retry-after in seconds. A key can also have a lifetime spend limit, after which it answers 403.

Prices are each provider's list price. Requests paid from credits add a 5% platform fee; requests that use your own provider key (BYOK) are charged 5% of the list price. Requests need a positive balance. A prompt is refused with 402 if the prompt alone would cost more than your balance plus $1, so one large request can't run an account far below zero. Accounts with auto top-up are charged afterwards instead.

Errors

Errors come back with an HTTP status and a JSON body. Chat and key errors carry error.code; embeddings, audio and media errors carry error.type (for example invalid_request_error, insufficient_quota).

Error body
{
  "error": {
    "message": "Rate limit exceeded (60 requests/min)",
    "code": 429
  }
}
HTTP status codes
400The body is invalid; no model was given; more than 10 fallback models; a model id over 256 characters; or the prompt is longer than the model's context window.
401The Authorization header is missing, or the key is invalid or disabled.
402The balance is used up, or this prompt alone would cost more than the balance allows. Add credits.
403The account is suspended, or the key has reached its spend limit.
404No such model (or media job).
429The key's per-minute rate limit is used up (see retry-after), or a provider rate-limited a request with no fallback left.
502Every provider in the fallback chain failed, or a provider rejected the request. The message says which.
503Media or audio generation is not available right now. You were not charged.

List models

GET /v1/models needs no key. Prices are US dollars per token, as strings. Media and audio models are listed too; the catalog page shows the same list per million tokens. Prices are each provider's list price. Requests paid from credits add a 5% platform fee.

Response (an example entry)
{
  "data": [
    {
      "id": "anthropic/claude-sonnet-5-5",
      "name": "Anthropic: Claude Sonnet 5.5",
      "modality": "chat",
      "context_length": 1000000,
      "pricing": { "prompt": "0.000003", "completion": "0.000015" },
      "providers": ["anthropic"]
    }
  ]
}

Look up a generation

GET /v1/generation?id=gen-… returns what one request cost (including the platform fee) and how long it took, for your own requests only. Right after a request it can answer 404 for a moment while billing settles.

Response
{
  "data": {
    "id": "gen-6f1c2a9e-…",
    "model": "anthropic/claude-opus-5-5",
    "provider_name": "anthropic",
    "tokens_prompt": 24,
    "tokens_completion": 31,
    "total_cost": 0.00089,
    "latency": 1840,
    "time_to_first_token": 420,
    "streamed": false,
    "created_at": "2026-10-18T21:04:05.000Z"
  }
}

The current key

GET /v1/key describes the key that called it: its label, lifetime spend in dollars, its spend limit (or null), its rate limit, and the account balance.

Response
{
  "data": {
    "label": "production",
    "usage": 12.4815,
    "limit": 100,
    "rate_limit": { "requests": 60, "interval": "1m" },
    "balance": 87.52
  }
}
API reference | Nicrron