Anthropic SDK base_url https://northerninference.ca/v1 Set in code as base_url. The SDK appends /messages, so the full path becomes /v1/messages. Not the same as Claude Code's ANTHROPIC_BASE_URL (that one uses the host root).

Anthropic SDK

Use the official Anthropic SDK with Northern Inference

Get going in 30 seconds

import os
from anthropic import Anthropic

client = Anthropic(
    base_url="https://northerninference.ca/v1",
    api_key=os.environ["NI_API_KEY"],          # ni_live_... key from the portal
)

resp = client.messages.create(
    model="bedrock/global.anthropic.claude-sonnet-4-5-20250929-v1:0-global",
    max_tokens=80,
    messages=[{"role": "user", "content": "Which jurisdiction am I in?"}],
)
print(resp.content[0].text)

Set NI_API_KEY to your ni_live_... key from the portal. That is the only change from a standard Anthropic SDK setup. Your usage appears under Usage within seconds.

Why this works

NI's gateway accepts both wire formats. OpenAI clients POST to /v1/chat/completions; Anthropic SDK clients POST to /v1/messages with the native Anthropic request shape (no shim, no translation layer). Use whichever your existing code already uses; setting base_url="https://northerninference.ca/v1" and your NI key is the only change.

Note: the Claude Code CLI uses ANTHROPIC_BASE_URL=https://northerninference.ca (host root, no /v1). That is an environment variable convention specific to the Claude Code binary. When using the Anthropic Python or TypeScript SDK directly in code, use https://northerninference.ca/v1 as shown below.

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="bedrock/global.anthropic.claude-sonnet-4-5-20250929-v1:0-global",  # exact NI route (copy from /v1/models)
    max_tokens=80,
    messages=[{"role": "user", "content": "Which jurisdiction am I in?"}],
)
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: "bedrock/global.anthropic.claude-sonnet-4-5-20250929-v1:0-global",
    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": "bedrock/global.anthropic.claude-haiku-4-5-20251001-v1:0-global",
    "max_tokens": 30,
    "messages": [{"role": "user", "content": "hi"}]
  }'

Model IDs

The examples above use the exact NI route ID, copied from /v1/models or /api/billing/models, so you control the privacy tier and jurisdiction explicitly. As a convenience, NI's gateway also aliases Anthropic's native model IDs (claude-sonnet-4-5-20250929, claude-haiku-4-5-20251001, etc.) to a matching deployment, but the exact route is recommended so you always know which tier you are on.

Route selection

The model name you pass selects the NI route and therefore the provider, region, and residency that serve the request. Your API key's allowed tiers authorize which routes it can call. Copy the exact route id from /models when you need a specific provider or region.

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).

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.

Using ni-* commands

Send an ni-* command as the message content when you need to inspect or change your route mapping without rebuilding your client. The gateway intercepts the command and responds directly (no model call, no billing).

Useful commands:

Mappings are saved to the account (all keys on the account share them). The command must be the start of the message content.


Anything not working as expected? Open a ticket. The full request log is in your portal under Usage.