Why this works
NI's gateway accepts both wire formats at the same base URL. OpenAI clients
POST to /v1/chat/completions; Anthropic clients POST to
/v1/messages with native Anthropic request shape (no shim, no
translation layer). Use whichever your existing code already uses; switching
base URLs to NI is the only change.
Python SDK
import os
from anthropic import Anthropic
client = Anthropic(
base_url="https://northerninference.ca/v1",
api_key=os.environ["NI_API_KEY"], # ni_live_... NI key, not an Anthropic key
)
resp = client.messages.create(
model="claude-sonnet-4-5-20250929", # native Anthropic model ID
max_tokens=80,
messages=[{"role": "user", "content": "Which jurisdiction am I in?"}],
extra_body={"privacy_tier": "managed_canadian_cloud"},
)
print(resp.content[0].text)
TypeScript SDK
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://northerninference.ca/v1",
apiKey: process.env.NI_API_KEY!,
});
const resp = await client.messages.create({
model: "claude-sonnet-4-5-20250929",
max_tokens: 80,
messages: [{ role: "user", content: "Which jurisdiction am I in?" }],
});
console.log(resp.content[0].type === "text" ? resp.content[0].text : "");
curl (native /v1/messages shape)
curl https://northerninference.ca/v1/messages \
-H "x-api-key: $NI_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-4-5-20251015",
"max_tokens": 30,
"messages": [{"role": "user", "content": "hi"}]
}'
Custody chain on responses
Same X-NI-* response headers as the OpenAI-compatible path โ
X-NI-Resolved-Provider, X-NI-Resolved-Region,
X-NI-Resolved-Jurisdiction, X-NI-Custody-Path, etc.
Whether a customer's request lands at /v1/chat/completions or
/v1/messages, NI applies the same residency guard and emits
the same audit trail.
Model IDs
Use Anthropic's native model IDs (claude-sonnet-4-5-20250929,
claude-haiku-4-5-20251015, claude-opus-4-7, etc.).
NI's gateway aliases these to the underlying deployment automatically โ you
don't need to know whether the call lands on Bedrock or direct Anthropic.
Force a specific path with privacy_tier if you want.
What about provider_api tier?
Set extra_body.privacy_tier = "provider_api" (Python) or send
X-Privacy-Tier: provider_api (raw HTTP) to route to direct
Anthropic instead of Bedrock CA. The model ID stays the same; NI picks the
right deployment based on the requested tier.
Tools, vision, streaming
All native Anthropic features pass through unchanged: tool_use,
vision (image content blocks), stream: true,
thinking with extended budgets. NI's billing accounts for
thinking tokens explicitly (zero double-billing).
Anything not working as expected? Open a ticket. The full request log is in your portal under Usage.