nrouter-sdk

module
v3.0.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 5, 2026 License: MIT

README

nRouter SDK & Examples

npm PyPI R-universe Go Reference Socket npm publish PyPI publish

SDK and code examples for the nRouter LLM gateway.

Supported today: JavaScript/TypeScript, Python, and Java

Three SDKs are supported. npm, PyPI and Maven Central carry those three. The rest are distributed but not supported: Kotlin and Android on Maven Central, Rust on crates.io, Dart / Flutter on pub.dev and R on R-universe are registry-distributed public previews, and Swift and Go resolve immutable git tags. Every SDK here is held to the same conformance and security gates. Distribution does not broaden the support commitment.

⚠️ Repository source is 3.0.0 for all ten, but four registry artifacts lag that train — Kotlin, Android and Rust serve 2.1.0, Dart serves 2.1.1. The install snippets below pin the version each registry actually serves, because asking for 3.0.0 there fails to resolve. Every version on this page was read from the registry on 2026-09-02; re-verify with the commands under SDK Ecosystem & Status rather than trusting the number.

SDK Registry Registry URL Package Version
JavaScript / TypeScript npm npmjs.com/package/@nrouter_ai/sdk @nrouter_ai/sdk 3.0.0
Python PyPI pypi.org/project/nrouter-sdk nrouter-sdk 3.0.0
Java Maven Central central.sonatype.com ai.nrouter:nrouter-sdk 3.0.0

All ten SDKs are held to the same public wire contract. The conformance gate accounts for all 150 route-ownership cells (15 routes × 10 SDKs): seven first-party transports expose native helpers with the exact path and HTTP verb, Android delegates the exact surface to Kotlin, and the JS/Python hybrid clients explicitly partition native helpers from their bounded vendor-client inheritance seam. Python's native route cells require both sync and async implementations. For inherited routes, the source gate proves ownership and a compiled resource—not the vendor package's internal HTTP implementation. The complete local gate compiles and runs the package suites against their locked dependencies.

The conformance gate derives and compares every manifest to the canonical version in spec/nrouter-sdk-spec.json; release metadata cannot drift silently.

One API key for models across six provider clouds — Alibaba US, OpenAI, AWS Bedrock, Azure Foundry, Google Vertex AI and Anthropic. nRouter serves the OpenAI wire format and Anthropic's Messages API natively, plus embeddings, audio, images and video.

One key. One bill. The live multi-provider catalog. Guardrails, prompt templates, and cost tracking built in. Browse the exact models available now at nrouter.ai/api/public/models.

The model decides the route — a Claude id is not callable on every endpoint

The gateway resolves a provider endpoint per wire, and a provider that serves no endpoint for a wire answers 404 model_unavailable_on_route: the model exists, just not on the route it was asked for. Anthropic serves /v1/messages only — it has neither chat-completions nor Responses — so a claude-* id posted to /v1/chat/completions fails for a customer holding a valid key and a real model id.

You are calling Use a model from
/v1/chat/completions, /v1/completions, /v1/responses OpenAI, Azure Foundry, Vertex AI or Alibaba (for example gpt-5.4-mini)
/v1/messages, /v1/messages/count_tokens Anthropic (claude-sonnet-4-5-20250929) or any provider serving that wire

The JS/TS SDK is the one exception: client.nr.chat() selects /v1/messages itself for claude-* ids and translates the response back, so the examples below pass a Claude id to it deliberately.

Every example here uses a model measured in the live catalogue on 2026-08-31. Confirm against your own key before spending — the catalogue is per-org:

curl -s https://api.nrouter.ai/v1/models -H "Authorization: Bearer $NROUTER_API_KEY"

gpt-5.4-mini is a reasoning model: give it a real token budget (~1024), or a small max_tokens is spent on hidden reasoning and the reply comes back empty.

conformance/doc_wires.py gates every snippet in this repository against that table.

Why Use the nRouter SDK?

Rather than juggling separate provider SDKs (OpenAI, Anthropic, Bedrock, Vertex AI, Azure Foundry), nRouter provides:

  1. One API Key Across 6 Provider Clouds: Call OpenAI, Claude, Vertex, Bedrock, and Azure models with a single client and unified billing.
  2. Built-in Spend & Observability: Every response captures exact latency, model ID, and request cost (x-nr-request-cost) with no extra telemetry instrumentation needed.
  3. Automated Guardrails & Compliance: PII redaction, prompt injection protection, and keyword scanning configured once in the dashboard apply automatically.
  4. Smart Routing & Automatic Failover: Route across provider clouds by real-time latency, price, or availability using router aliases.
  5. Universal Enterprise Features: Unified conversation memory, Jinja2 prompt variable injection, and RFC 9110 retry-after exponential backoff across all 10 SDKs.

Authentication, Environment & .env Setup

All nRouter SDKs automatically read your API key from the NROUTER_API_KEY environment variable.

1. Where to Get Your API Key
  1. Sign in to your dashboard: nrouter.ai/dashboard.
  2. Go to API Keys / Virtual Keys: nrouter.ai/dashboard/keys.
  3. Click Create Key. Virtual keys start with sk-nrouter-. Assign key budgets, rate limits, and guardrails directly in the dashboard.
2. Configure Local .env

Copy .env.example to .env:

cp .env.example .env

Edit .env and set your key:

NROUTER_API_KEY="sk-nrouter-your-api-key-here"
NROUTER_BASE_URL="https://api.nrouter.ai/v1"
3. How to Source .env
  • Shell (Bash / Zsh):
    export $(grep -v '^#' .env | xargs)
    
  • Node.js / TypeScript:
    npm install dotenv
    
    import "dotenv/config";
    import { nRouter } from "@nrouter_ai/sdk";
    const client = new nRouter(); // reads process.env.NROUTER_API_KEY
    
  • Python:
    pip install python-dotenv
    
    from dotenv import load_dotenv
    load_dotenv()
    from nroutersdk import nRouter
    client = nRouter() # reads os.environ["NROUTER_API_KEY"]
    
  • Go:
    import "github.com/joho/godotenv"
    _ = godotenv.Load()
    client, err := nrouter.NewFromEnv()
    

All API keys must start with the sk-nrouter- prefix. You can also pass the key explicitly in code via apiKey / api_key in any SDK constructor.


Quick Start

TypeScript / JavaScript
npm install @nrouter_ai/sdk
import { nRouter } from "@nrouter_ai/sdk";

const client = new nRouter(); // reads NROUTER_API_KEY from environment
const res = await client.nr.chat({
  model: "claude-sonnet-4-5-20250929",
  prompt: "Hello from TypeScript!",
});
console.log(client.nr.text(res));
console.log(`Cost: $${res.meta.cost ?? "unpriced"}`);
Python
pip install nrouter-sdk
from nroutersdk import nRouter

client = nRouter()  # reads NROUTER_API_KEY from env
response = client.chat.completions.create(
    model="gpt-5.4-mini",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)
print(f"Cost: ${client.last_response.cost}" if client.last_response.cost else "Cost: unpriced")
Java
<dependency>
    <groupId>ai.nrouter</groupId>
    <artifactId>nrouter-sdk</artifactId>
    <version>3.0.0</version>
</dependency>
import ai.nrouter.sdk.NRouter;
import com.openai.client.OpenAIClient;
import com.openai.models.chat.completions.*;

OpenAIClient client = NRouter.create(); // reads NROUTER_API_KEY
ChatCompletion res = client.chat().completions().create(
    ChatCompletionCreateParams.builder()
        .model("gpt-5.4-mini")
        .addMessage(ChatCompletionMessageParam.ofUser(
            ChatCompletionUserMessageParam.builder().content("Hello!").build()
        ))
        .build()
);
System.out.println(res.choices().get(0).message().content());
Swift
// Swift Package Manager
.package(url: "https://github.com/nRouterAI/nrouter-sdk.git", from: "3.0.0")
import NRouter

let client = try NRouter() // reads NROUTER_API_KEY
let res = try await client.chatCompletions([
    "model": "gpt-5.4-mini",
    "messages": [["role": "user", "content": "Hello!"]]
])
print(res.meta.isPriced ? "Cost: $\(res.meta.cost!)" : "Cost: unpriced")
Rust
# Cargo.toml
[dependencies]
nrouter = "2.1.0" # crates.io; 3.0.0 is not yet published there
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
use nrouter::http::Client;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::from_env()?; // reads NROUTER_API_KEY
    let out = client.chat_completions(&json!({
        "model": "gpt-5.4-mini",
        "messages": [{"role": "user", "content": "Hello from Rust!"}]
    })).await?;
    println!("Response: {:?}", out.body);
    Ok(())
}
Dart / Flutter
# pubspec.yaml
dependencies:
  nrouter: ^2.1.1 # pub.dev; 3.0.0 is not yet published there
import 'package:nrouter/nrouter.dart';

final client = NRouter(apiKey: 'sk-nrouter-...');
final result = await client.chatCompletions({
  'model': 'gpt-5.4-mini',
  'messages': [{'role': 'user', 'content': 'Hello from Dart!'}],
});
print(result.body['choices']);
client.close();
Kotlin
// build.gradle.kts
repositories { mavenCentral() }
dependencies {
    implementation("ai.nrouter:nrouter-sdk-kotlin:2.1.0") // latest on Central
}
import ai.nrouter.sdk.NRouter
import org.json.JSONObject

val client = NRouter() // reads NROUTER_API_KEY
val res = client.chatCompletions(
    JSONObject()
        .put("model", "gpt-5.4-mini")
        .put("messages", listOf(mapOf("role" to "user", "content" to "Hello from Kotlin!")))
)
println("Cost: ${res.meta.cost?.let { "$$it" } ?: "unpriced"}")
Android
// app/build.gradle.kts
repositories { mavenCentral() }
dependencies {
    implementation("ai.nrouter:nrouter-sdk-android:2.1.0") // latest on Central
}
SDK Ecosystem & Status

Ten branded packages, each pre-configured for nRouter. Every one validates the sk-nrouter- prefix before any request and points at https://api.nrouter.ai/v1; all but Dart also resolve NROUTER_API_KEY (Dart requires an explicit key — dart:io does not exist in a Flutter web build, so an environment fallback would silently resolve to nothing):

Distribution status is a fact, not an intention. Every row below was read from the registry itself on 2026-09-02, not from an intent to publish. Where a registry serves an older version than this repository's 3.0.0 source, the row says which version it actually serves — that is the version that resolves.

Language Install Registry URL Registry status Package Typed errors x-nr-* metadata
Python pip install nrouter-sdk pypi.org/project/nrouter-sdk ✅ PUBLISHED sdks/python/ ✅ typed wrappers ✅ client.last_response
TypeScript / JS npm install @nrouter_ai/sdk npmjs.com/package/@nrouter_ai/sdk ✅ PUBLISHED sdks/js/ ✅ 9 codes ✅ 14 headers
Java Maven ai.nrouter:nrouter-sdk central.sonatype.com ✅ PUBLISHED sdks/java/ ✅ 9 codes (native HTTP surface) ✅ 14 headers (native HTTP surface)
Kotlin Maven ai.nrouter:nrouter-sdk-kotlin:2.1.0 central.sonatype.com 🧪 PUBLIC PREVIEW — serves 2.1.0 sdks/kotlin/ ✅ 9 codes ✅ 14 headers
Android Maven ai.nrouter:nrouter-sdk-android:2.1.0 central.sonatype.com 🧪 PUBLIC PREVIEW — serves 2.1.0 sdks/android/ ✅ 9 codes ✅ 14 headers
Rust cargo add nrouter@2.1.0 crates.io/crates/nrouter 🧪 PUBLIC PREVIEW — serves 2.1.0 sdks/rust/ ✅ 9 codes ✅ 14 headers
Dart / Flutter dart pub add nrouter pub.dev/packages/nrouter 🧪 PUBLIC PREVIEW — serves 2.1.1 sdks/dart/ ✅ 9 codes ✅ 14 headers
Swift SwiftPM, this repo's URL github.com/nRouterAI/nrouter-sdk ✅ git tag 3.0.0 sdks/swift/ ✅ 9 codes ✅ 14 headers
R install.packages("nrouter", repos = c(nrouterai = "https://nrouterai.r-universe.dev", CRAN = "https://cloud.r-project.org")) nrouterai.r-universe.dev/nrouter 🧪 PUBLIC PREVIEW sdks/r/ ✅ 9 classed conditions ✅ 14 headers
Go go get github.com/nRouterAI/nrouter-sdk/sdks/go/v3@v3.0.0 pkg.go.dev/github.com/nRouterAI/nrouter-sdk/sdks/go/v3 ✅ git tag sdks/go/v3.0.0 sdks/go/ ✅ 9 codes ✅ 14 headers

Verify any row rather than trusting it:

# Ask each registry what it SERVES, not whether a page exists.
curl -s https://pypi.org/pypi/nrouter-sdk/json | python3 -c 'import sys,json;print("pypi",json.load(sys.stdin)["info"]["version"])'
curl -s https://registry.npmjs.org/@nrouter_ai%2Fsdk | python3 -c 'import sys,json;print("npm",json.load(sys.stdin)["dist-tags"]["latest"])'

# Maven Central. Use repo1 metadata, NOT search.maven.org — its solr index
# returns zero hits for ai.nrouter while the artifacts are demonstrably there,
# so an "empty" search page is an index gap, never proof of an absent release.
for a in nrouter-sdk nrouter-sdk-kotlin nrouter-sdk-android; do
  echo -n "maven $a "
  curl -s "https://repo1.maven.org/maven2/ai/nrouter/$a/maven-metadata.xml" | grep -o '<release>[^<]*'
done

curl -s -H 'User-Agent: nrouter-check' https://crates.io/api/v1/crates/nrouter | python3 -c 'import sys,json;print("crates.io",json.load(sys.stdin)["crate"]["max_version"])'
curl -s https://pub.dev/api/packages/nrouter | python3 -c 'import sys,json;print("pub.dev",json.load(sys.stdin)["latest"]["version"])'

# Go has no registry: proxy.golang.org serves whatever a git tag points at, and
# it case-encodes the path (each uppercase letter becomes '!' + lowercase).
curl -s https://proxy.golang.org/github.com/n!router!a!i/nrouter-sdk/sdks/go/v3/@v/list
curl -s https://nrouterai.r-universe.dev/src/contrib/PACKAGES | grep -A4 '^Package: nrouter$'

Java keeps its vendor-compatible OpenAI factory and adds a Java 11 native HTTP surface for all 15 gateway operations, four incremental SSE wires, every x-nr-* header and nine typed gateway errors. JavaScript/TypeScript and the seven first-party native transports expose the same contract. Android delegates those guarantees to Kotlin; Python adds the same nRouter typing and metadata capture around its vendor client.

Every SDK is held to one contract. conformance/check_conformance.py reads spec/nrouter-sdk-spec.json and fails if any SDK drifts on the base URL, the environment variable, the key prefix, a response header, an error code, one of the 150 route-ownership cells, or one of the four native streaming helpers per first-party transport. It needs no toolchains, and its --self-test proves it goes red rather than merely printing green. See conformance/.

Run the complete local release gate—including all ten language suites, Android lint/AAR assembly, race/clippy/analyzer checks, and conformance mutation proof—with:

scripts/test-all.sh

The same command runs scripts/security-audit.sh and fails on known advisories across npm, PyPI, Maven/Gradle, Cargo and Dart dependency graphs. Install osv-scanner and pip-audit.

It also runs scripts/sast.sh, which is a different check and not a substitute for either direction: security-audit.sh looks for known vulnerabilities in third-party dependencies, sast.sh runs static analysis over the code in this repository. It uses semgrep's p/default ruleset:

brew install semgrep                   # macOS
python3 -m pip install --user semgrep  # any platform

Without it the lane is reported SKIPPED and named, never passed, and scripts/sast.sh run directly exits 78 with that install command rather than a bare command not found. The three exit states are deliberately distinct — 0 scanned and clean, 1 scanned and found something, 78 never ran — because semgrep itself uses 0/1, so absence must be neither or "not installed" reads as "clean". Prove it bites before trusting a green run:

scripts/sast.sh --self-test

That plants a git-tracked file containing a command injection and fails unless the scan reports it. Tracked is deliberate: semgrep scans git-tracked files only, so an untracked probe is skipped and the scan still exits 0.

This is a mirror, not parity. It stands in for the GitHub CodeQL default setup, which is dormant while Actions is unavailable. Measured over this tree, p/default is comparable to CodeQL on Python, TypeScript, JavaScript, Java and Go; it is thin on Kotlin (18 rules) and Swift (2 rules), which nothing local now replaces; Rust is thin in semgrep but genuinely covered by cargo clippy -D warnings in the Rust lane. Dart and R are scanned by nothing — CodeQL never covered them either, so that hole is pre-existing. CodeQL's actions workflow analysis is not mirrored. scripts/sast.sh carries the per-language rule counts and how to re-derive them.

Each language is an independent lane, so one absent toolchain no longer blocks the rest. A lane whose prerequisites are missing is reported SKIPPED, named, and counted separately — it is never a pass, and the summary says so in as many words. A lane that FAILS exits the script non-zero. For a release, set NROUTER_REQUIRE_ALL=1: a lane that did not run is then not evidence, and the run reports INCOMPLETE and exits non-zero. scripts/test-all.sh --self-test proves those three exit postures against the same engine the real run uses.

The opt-in live tests are intentionally excluded unless NROUTER_LIVE=1 is set, because they make billed inference calls.

Publishing is PUBLISHING.md: bump the canonical version and all manifests together, merge to main, publish the three supported registry packages, verify every source preview, and create the source tags.

Swift and Go resolve git tags rather than registry uploads. SwiftPM reads Package.swift from the repository ROOT. That is what Package.swift here is for — this directory is the root of the public nrouter-sdk repo, and the manifest uses path: to reach sdks/swift/, so the Swift sources stay beside the other eight. Consumers use:

.package(url: "https://github.com/nRouterAI/nrouter-sdk.git", from: "3.0.0")
Any Other Language (OpenAI SDK)
base_url  →  https://api.nrouter.ai/v1
api_key   →  NROUTER_API_KEY
// Node.js — npm install openai
import OpenAI from "openai";
const client = new OpenAI({
  apiKey: process.env.NROUTER_API_KEY,
  baseURL: "https://api.nrouter.ai/v1",
});

Supported Endpoints

All endpoints are served by the nRouter gateway at https://api.nrouter.ai/v1, which routes to the upstream providers. You never call a provider directly and you never need a provider key. This table is derived from spec/nrouter-sdk-spec.json › supported_endpoints (Rule #14) — edit the spec first, this table second.

Endpoint SDK Method nRouter Features
/v1/chat/completions chat.completions.create() Guardrails + Prompts + A/B Testing + Credits
/v1/completions completions.create() Credits
/v1/embeddings embeddings.create() Credits
/v1/images/generations images.generate() Credits
/v1/audio/speech audio.speech.create() Credits (TTS)
/v1/audio/transcriptions audio.transcriptions.create() Credits (Whisper STT)
/v1/audio/translations audio.translations.create() Credits
/v1/messages client.messages.create() Anthropic-compatible buffered call; Credits
/v1/messages/count_tokens POST /v1/messages/count_tokens Count before spending
/v1/responses responses.create() OpenAI Responses API
/v1/videos POST /v1/videos Start a video job (billed)
/v1/videos/{id} GET /v1/videos/{id} Poll job status (free)
/v1/videos/{id}/content GET /v1/videos/{id}/content Download the video (free)
/v1/models models.list() Tenant-filtered model list
/v1/models/{model_id} models.retrieve() Retrieve one model
Routing strategies are selected by the model value

Routing strategy is a gateway concern, so there is no separate per-language strategy API to drift. Put a Smart Router alias in model to activate its configured strategy and fallback chain; put a concrete model id there to pin the call to that model. Every runnable hello-world example accepts NROUTER_MODEL so the same example demonstrates both modes without inventing client-only routing behavior.

NROUTER_MODEL=my-production-router ./run-your-example   # alias: strategy + fallback
NROUTER_MODEL=gpt-5.4-mini ./run-your-example  # concrete: pinned
Not Served By The Gateway

spec/nrouter-sdk-spec.json › unsupported_endpoints marks these as never called: files, fine-tuning, batches, beta/assistants-threads, vector stores, uploads, containers, conversations, webhooks, image edits, moderations, rerank, OCR. Do not add a client method or example for any of these without first adding the route to the gateway and the spec.


Examples by Language

SDKs (direct)
Language Install Example
Python (branded) pip install nrouter-sdk sdks/python/ · examples/python/, notebooks/quickstart.ipynb
TypeScript / JS (branded) npm install @nrouter_ai/sdk sdks/js/ · examples/typescript/quickstart.ts, examples/javascript/quickstart.js
Java (branded) ai.nrouter:nrouter-sdk sdks/java/ · examples/java/quickstart.java
Kotlin (branded) Maven ai.nrouter:nrouter-sdk-kotlin:2.1.0 sdks/kotlin/ · examples/kotlin/quickstart.kt
Android (branded) Maven ai.nrouter:nrouter-sdk-android:2.1.0 sdks/android/
Rust (branded) cargo add nrouter@2.1.0 sdks/rust/ · examples/rust/quickstart.rs
Dart / Flutter (branded) dart pub add nrouter sdks/dart/ · examples/dart/quickstart.dart
R (branded) install.packages("nrouter", repos = c(nrouterai = "https://nrouterai.r-universe.dev", CRAN = "https://cloud.r-project.org")) sdks/r/ · examples/r/quickstart.R
Node.js / TypeScript (plain openai) npm install openai examples/typescript/node.ts
Go go get github.com/nRouterAI/nrouter-sdk/sdks/go/v3@v3.0.0, or plain openai-go examples/go/quickstart.go
Java (plain openai-java) com.openai:openai-java examples/java/quickstart.java
Ruby gem install ruby-openai examples/ruby/quickstart.rb
PHP composer require openai-php/client examples/php/quickstart.php
C# / .NET dotnet add package OpenAI examples/dotnet/quickstart.cs
cURL Built-in examples/curl/quickstart.sh

Every language under examples/ holds standalone, runnable starter scripts and framework integrations.

AI Frameworks
Framework Install Example What Changes
LangChain pip install langchain-openai examples/python/frameworks/langchain.py base_url + api_key on ChatOpenAI
LlamaIndex pip install llama-index-llms-openai examples/python/frameworks/llamaindex.py api_base + api_key on OpenAI
Vercel AI SDK npm install ai @ai-sdk/openai examples/typescript/vercel_ai.ts baseURL on createOpenAI()
CrewAI pip install crewai examples/python/frameworks/crewai.py OPENAI_API_BASE env var
AutoGen pip install autogen-agentchat examples/python/frameworks/autogen.py base_url in config_list

Every framework that supports OpenAI-compatible endpoints works with nRouter. Set base_url to https://api.nrouter.ai/v1 and api_key to your NROUTER_API_KEY. That's it.


Response Headers

The gateway's public x-nr-* response headers, and what each one means. Most are conditional; x-nr-request-id is the one present on every response. The authoritative set is spec/gateway-response-headers.json, derived from the gateway and held against all ten SDKs by conformance/check_conformance.py — this table describes the headers, and is not itself the register of which ones exist.

Header Type Description
x-nr-request-id string Unique request ID (always present)
x-nr-request-cost float Exact cost in USD; absent when the model is unpriced
x-nr-cost-status string exact or unpriced when cost metadata is available
x-nr-model string Model that served the request
x-nr-input-tokens integer Input token count
x-nr-output-tokens integer Output token count
x-nr-total-tokens integer Total token count, including cache tokens
x-nr-cache-read-tokens integer Cache-read tokens; emitted only when nonzero
x-nr-cache-write-tokens integer Cache-write tokens; emitted only when nonzero
x-nr-limit-source string key, plan, team, user, or budget on 429 responses
x-nr-budget-warning string A soft budget you configured was crossed by this request, which still served; <scope> soft_budget <spend>/<ceiling>, e.g. org soft_budget 80.00/100.00
x-nr-guardrails string Pre-call guardrail posture; absent means the response makes no guardrail claim, never none, which is an explicit token
x-nr-auth-reason string On a 401, the gateway's stable reason for refusing the key
x-nr-response-cache string hit or miss; absent when the response cache did not participate
x-nr-response-cache-age integer Age of a cache hit in seconds

Python SDK captures these automatically in client.last_response. Other languages read them from HTTP response headers.


Structure

This is the standalone public nRouterAI/nrouter-sdk repository:

nrouter-sdk/
├── README.md                        ← You are here (single reference for all)
├── LANGUAGES.md                     ← every-language guide (any OpenAI-format client)
├── spec/nrouter-sdk-spec.json       ← Source of truth (headers, errors, endpoints, Rule #14)
├── sdks/
│   ├── python/                      ← Branded SDK → pip install nrouter-sdk
│   ├── js/                          ← Branded SDK → npm install @nrouter_ai/sdk
│   ├── java/                        ← Branded SDK → Maven ai.nrouter:nrouter-sdk
│   ├── kotlin/                      ← Branded SDK → Maven ai.nrouter:nrouter-sdk-kotlin
│   ├── android/                     ← Branded SDK → Maven ai.nrouter:nrouter-sdk-android
│   ├── swift/                       ← SwiftPM package from the root git tag
│   ├── rust/                        ← Branded SDK → crates.io nrouter
│   ├── dart/                        ← Branded SDK → pub.dev nrouter
│   ├── go/                          ← Branded SDK → tagged Go module
│   └── r/                           ← Branded SDK → R-universe public preview
└── examples/
    ├── curl.sh                      ← cURL
    ├── node.ts                      ← Node.js / TypeScript (plain openai)
    ├── go.go                        ← Go (plain openai-go; sdks/go/ is branded)
    ├── java.java                    ← Java (plain openai-java)
    ├── ruby.rb                      ← Ruby
    ├── php.php                      ← PHP
    ├── dotnet.cs                    ← C# / .NET
    ├── langchain.py                 ← LangChain
    ├── llamaindex.py                ← LlamaIndex
    ├── vercel_ai.ts                 ← Vercel AI SDK
    ├── crewai.py                    ← CrewAI
    ├── autogen.py                   ← AutoGen
    └── hello-world/                 ← one minimal script per non-Python branded SDK
        ├── typescript.ts
        ├── javascript.js
        ├── java.java
        ├── rust.rs
        └── r.R

This is the single reference for all SDK/examples. The playground code generation and docs site pull from these examples.

Documentation

Every link below was checked live before it was written here; none is derived from the sitemap alone, because a URL can sit in a sitemap and still 404.

How each capability works, and where it is enforced — all of these are gateway-side, so they behave identically from every SDK in this repository:

Capability Guide Product page
Guardrails — PII redaction, injection protection, pre- and post-call docs/guides/guardrails product/guardrails
Budgets and spend limits, per key / team / org docs/guides/budget-controls product/budgets
Routing, fallback chains, failover docs/guides/router-settings product/routing
Observability and cost tracking docs/guides/observability product/observability
Prompt templates and versioning docs/guides/prompts —
API keys — creation, rotation, scope docs/guides/api-key-management —

None of this lives in the SDK. It is configured in the dashboard and enforced at the gateway on the request path, so whatever you have enabled applies to a raw curl exactly as it does to a branded SDK, and no client can bypass it. That is the reason a thin client is the right shape here.

⚠️ Two things are conditional, and assuming otherwise is how you rely on protection you do not have:

  • Which guardrails run is resolved per request. The organization's guardrail switch gates everything; below it the narrowest applicable assignment wins across key > team > org > default, and a winner disabled at that scope does not run. A guardrail you configured is not necessarily a guardrail this request gets — check the assignment, not just the switch.
  • Routing is opt-in by what you put in model, and applies to text wires only. An alias gets its strategy and fallback chain; a concrete model is never re-routed and inherits no hidden platform fallback. Audio, image and video take a single-provider route and are not cross-provider Smart Router wires.

Cost accounting covers every BILLABLE call. Some routes these SDKs expose are deliberately free and emit no x-nr-request-cost at all — /v1/messages/count_tokens, and video polling and content retrieval — because they generate no completion. Absent is not zero (Rule #28): a missing cost header means unpriced or free, never a $0 inference.

Per-language quickstarts: Python · Node.js / TypeScript · Go · Java · PHP · Ruby · curl · OpenAI SDK against nRouter

Reference: Quick start · API reference · Live model catalogue · Pricing · Changelog

Contributing, security, and support

CONTRIBUTING.md How to build and test each SDK, and the PR checklist. Read the version-field warning before you open a PR — merging main publishes immutably.
SECURITY.md Report a vulnerability privately to security@nrouter.ai, never as an issue. Supported version lines per registry.
SUPPORT.md SDK bugs go to issues; account, billing, and API-key questions go to support@nrouter.ai.
CODE_OF_CONDUCT.md Adapted from the Contributor Covenant 2.1.
CHANGELOG.md Coordinated release history for the shared SDK version train.
PUBLISHING.md How a release actually ships, and which credential each registry needs.

npm builds 1.1.1 and later carry provenance attestations tying the tarball to the exact commit and workflow that produced it — verify with npm audit signatures. 1.0.0 and 1.1.0 were published by hand and have none; provenance cannot be added to a version after the fact. See SECURITY.md.

Directories

Path Synopsis
examples
go command
sdks
go module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL