API reference¶
This task-oriented reference covers the routes implemented by Nexus. All examples use a placeholder key and a model returned for the authenticated key.
Common contract¶
- Authentication:
Authorization: Bearer <key>,x-api-keyandapi-key. Gemini routes also acceptx-goog-api-keyor?key=. - Model placement: JSON body for OpenAI/Anthropic routes;
{model}and an action suffix in a Gemini path; querymodelfor Realtime. - Request ID: send
x-request-idfor correlation; Nexus returns it in the response header and local error envelope. - Limits: ordinary JSON routes accept up to 32 MiB; Gemini JSON up to 20 MiB; image/audio JSON up to 1 MiB; multipart image/audio up to 25 MiB.
- Billing: successful measured usage or a compatible fixed-price response can be charged once. Missing or contradictory usage is left uncharged and is not charged later automatically.
- Idempotency: to prevent duplicate charges on POST generation routes, send
the
Idempotency-Key(orX-Idempotency-Key) header. The key length must be 1 to 256 printable ASCII characters, scoped to the profile, API key, and endpoint family. Replays with identical payload return the cached response withIdempotency-Replayed: true(cache retained for 24 hours, followed by a 7-day tombstone window returningresult_expired) and zero additional balance charges. See Retries and idempotency.
export NEXUS_API_KEY='replace-with-your-key'
curl https://api.nexus-hub.tech/v1/models \
-H "Authorization: Bearer $NEXUS_API_KEY" \
-H "x-request-id: docs-models-001"
A successful discovery response has this shape:
{"object":"list","data":[{"id":"MODEL","object":"model","created":0,"owned_by":"..."}]}
Local failures use one safe envelope across route families:
{"error":{"message":"model is not enabled for this API key","type":"nexus_error","code":"model_not_allowed","request_id":"docs-001"}}
Discovery and account¶
| Method and path | Model placement | Successful response |
|---|---|---|
GET /api.json |
none | public OpenCode-compatible metadata catalog of active public models |
GET /v1/models |
none | key-visible OpenAI-style list |
GET /v1/catalog |
none | public models and verified endpoint capabilities |
GET /v1/models/catalog |
none | same public catalog as GET /v1/catalog |
GET /v1/models/{model} |
path | one visible model or model_not_found |
GET /v1/balance |
none | balance object for the key's profile |
GET /v1beta/models |
none | Gemini aliases, methods and optional token limits |
GET /v1beta/openai/models |
none | OpenAI-style Gemini model list for bridge clients |
GET /v1/catalog?currency=RUB\|USD\|EUR\|CNY |
none | public retail catalogue and price snapshot |
Authenticated discovery routes are filtered by key, endpoint policy and active model access.
OpenCode metadata catalog¶
GET /api.json needs no API key. The public URL is
https://api.nexus-hub.tech/api.json. It returns the current list of active
public Nexus Hub models plus the metadata OpenCode, Delta and compatible
clients use to choose a transport (@ai-sdk/anthropic, @ai-sdk/openai, or
@ai-sdk/openai-compatible).
It is not a per-key access guarantee. Presence in /api.json only means the
model is currently active and public in the shared Nexus Hub catalogue. Check
key-specific access with authenticated GET /v1/models. Public
GET /v1/catalog remains the capability and retail-price catalogue.
Known text models include context and output hints plus text modalities for
client discovery. Unknown limits appear as 0; this does not impose a zero
request limit on Nexus.
curl https://api.nexus-hub.tech/api.json
{"opencode":{"id":"opencode","name":"Nexus Hub","npm":"@ai-sdk/openai-compatible","api":"https://api.nexus-hub.tech/v1","models":{"grok-4.6":{"id":"grok-4.6","name":"Grok 4.6","family":"grok","attachment":false,"reasoning":true,"reasoning_options":[{"type":"effort","values":["low","medium","high","xhigh"]}],"tool_call":true,"temperature":true,"modalities":{"input":["text"],"output":["text"]},"limit":{"context":500000,"output":500000},"provider":{"npm":"@ai-sdk/openai-compatible"}}}}}
Public catalog¶
GET /v1/catalog needs no API key and defaults to RUB. It accepts USD,
EUR, and CNY with the currency query parameter. An unsupported value
returns 400 with invalid_catalog_currency.
GET /v1/models/catalog is the same public catalog as GET /v1/catalog,
including the optional currency query.
The response keeps the order of the active public catalogue, families, public
model IDs and display names, endpoint families, billing mode, and final retail
price components. It is not a per-key availability response; use authenticated
GET /v1/models for that. Each money value is a decimal string with an
explicit unit such as
USD_per_1M_tokens or EUR_per_request. snapshot.fx_status is current,
stale, or unavailable; when it is unavailable, the affected components are
null rather than values incorrectly labelled as the selected currency.
{"snapshot":{"fetched_at":"2026-08-14T10:00:00Z","effective_date":"2026-08-14","fx_status":"current"},"currency":"EUR","families":[{"id":"example","models":[{"id":"MODEL","display_name":"MODEL","endpoint_families":["responses"],"prices":[{"endpoint_families":["responses"],"billing_mode":"per_token","components":{"input":{"amount":"1.250000","unit":"EUR_per_1M_tokens"},"cached_input":null,"cache_write":null,"output":{"amount":"5.000000","unit":"EUR_per_1M_tokens"},"request":null}}]}]}]}
This route is intended for the documentation table. It supports browser cache
revalidation with ETag and has a short public cache lifetime.
GET /v1/catalog is a no-auth capability discovery endpoint. It includes only
public model metadata and verified optional parameters; missing endpoint
entries remain unknown and do not become unsupported.
Text generation¶
All rows below accept JSON up to 32 MiB. Use a model returned for the key.
| Method and path | Minimal JSON body | Successful response | Streaming/output control |
|---|---|---|---|
POST /v1/chat/completions |
{"model":"MODEL","messages":[{"role":"user","content":"Reply OK"}],"max_completion_tokens":16} |
OpenAI Chat object | stream: true; max_completion_tokens or max_tokens |
POST /v1/completions |
{"model":"MODEL","prompt":"Reply OK","max_tokens":16} |
OpenAI completion object | no stream; max_tokens |
POST /v1/responses |
{"model":"MODEL","input":"Reply OK","max_output_tokens":16} |
Responses object | stream: true; max_output_tokens |
POST /v1/responses/compact |
{"model":"MODEL","input":"Reply OK","max_output_tokens":16} |
compact Responses object | stream: true; max_output_tokens |
POST /v1/messages |
{"model":"MODEL","max_tokens":16,"messages":[{"role":"user","content":"Reply OK"}]} |
Anthropic Messages object | stream: true; positive max_tokens required |
POST /v1/messages/count_tokens |
{"model":"MODEL","messages":[{"role":"user","content":"Reply OK"}]} |
{"input_tokens":...} |
no charge and no stream |
Send anthropic-version: 2023-06-01 on both Messages routes. JSON streaming
uses protocol-native SSE terminal events; a non-streaming request returns one
JSON object. /v1/completions accepts only a string prompt: batch and token-ID
prompts return unsupported_prompt_shape.
Minimal Responses request:
curl https://api.nexus-hub.tech/v1/responses \
-H "Authorization: Bearer $NEXUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_FROM_V1_MODELS","input":"Reply exactly OK.","max_output_tokens":16}'
Minimal Messages request:
curl https://api.nexus-hub.tech/v1/messages \
-H "x-api-key: $NEXUS_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_FROM_V1_MODELS","max_tokens":16,"messages":[{"role":"user","content":"Reply exactly OK."}]}'
Embeddings, ranking and moderation¶
These JSON routes accept up to 32 MiB and do not stream.
| Method and path | Minimal JSON body | Successful response |
|---|---|---|
POST /v1/embeddings |
{"model":"MODEL","input":"Reply OK"} |
embedding list |
POST /v1/rerank |
{"model":"MODEL","query":"OK","documents":["OK"],"top_n":1} |
ranked results |
POST /v1/moderations |
{"model":"MODEL","input":"Reply OK"} |
moderation results |
The key must have access to the endpoint family and model.
Images and audio¶
| Method and path | Minimal request fields | Limit and successful response |
|---|---|---|
POST /v1/images/generations |
JSON: model, prompt |
1 MiB; JSON image result |
POST /v1/images/edits |
multipart: model, image, prompt |
25 MiB; JSON image result |
POST /v1/images/variations |
multipart: model, image |
25 MiB; JSON image result |
POST /v1/audio/speech |
JSON: model, input, voice |
1 MiB; binary audio |
POST /v1/audio/transcriptions |
multipart: model, file |
25 MiB; JSON transcript |
POST /v1/audio/translations |
multipart: model, file |
25 MiB; JSON translation |
Media routes do not stream. A wrong content type returns
unsupported_content_type; an oversized body returns payload_too_large.
Gemini-compatible actions¶
The path is POST /v1beta/models/{model}:{action}. All action bodies accept up
to 20 MiB. The model is in the path; if a body also contains model, it must
match.
| Action | Minimal request shape | Response/stream and output control |
|---|---|---|
generateContent |
contents; optional generationConfig |
JSON; generationConfig.maxOutputTokens |
streamGenerateContent |
same | SSE chunks, terminal [DONE]; same output field |
countTokens |
contents |
{"totalTokens":...}; no charge and no stream |
embedContent |
content |
one JSON embedding; no stream |
batchEmbedContents |
requests[] |
JSON embeddings; no stream |
curl "https://api.nexus-hub.tech/v1beta/models/MODEL:generateContent" \
-H "x-goog-api-key: $NEXUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contents":[{"role":"user","parts":[{"text":"Reply exactly OK."}]}],"generationConfig":{"maxOutputTokens":16}}'
countTokens is a preflight operation and does not change the balance.
embedContent accepts one content; batchEmbedContents accepts a
requests array.
Body-size limits and output-token limits are separate. When Nexus has an
explicit output limit for a model, a larger max_tokens,
max_completion_tokens, max_output_tokens or Gemini
generationConfig.maxOutputTokens is rejected with invalid_request_error.
Gemini discovery exposes outputTokenLimit when that metadata is configured;
an omitted value does not create a hidden default.
Realtime WebSocket¶
Connect to wss://api.nexus-hub.tech/v1/realtime?model=MODEL_FROM_V1_MODELS and
send the key as Authorization: Bearer or x-api-key during the handshake.
The query model is fixed for the session; a message attempting to switch it is
rejected. Text, binary, ping, pong and close frames are proxied. Output limits
inside protocol messages are forwarded unchanged.
Errors and retries¶
Common codes are invalid_key, model_not_found, model_not_allowed,
endpoint_not_allowed, insufficient_balance, streaming_not_supported,
unsupported_content_type, payload_too_large, upstream_error,
upstream_timeout, pricing_unavailable, duplicate_request_id,
invalid_idempotency_key, idempotency_conflict, idempotency_in_progress,
result_expired, as well as 429 rate/concurrency limit codes and 503 capacity
codes (provider_capacity_exceeded, etc.). Both 429 and 503 include a Retry-After
header. On network timeouts and disconnections, safely retry using the
Idempotency-Key header. See Errors and support and
Retries and idempotency.