Integration
AtmoRouter speaks both the OpenAI Chat Completions API and the Anthropic Messages API. Point your existing client at us and keep your code exactly as it is.
OpenAI-compatible
https://atmorouter.dev/v1Include the /v1 suffix. Used by the OpenAI SDKs, LangChain, LiteLLM and most coding agents.
Anthropic-compatible
https://atmorouter.devNo /v1 suffix — the Anthropic SDK and Claude Code append it themselves.
Most agents and CLIs read these, so nothing in your code has to change.
Environment variables
Works with most coding agents and CLIs without touching code
export OPENAI_BASE_URL="https://atmorouter.dev/v1" export OPENAI_API_KEY="ar-xxxxxxxxxxxx" # Verify the key and list every model you can call: curl $OPENAI_BASE_URL/models -H "Authorization: Bearer $OPENAI_API_KEY"
Same request shape, same streaming, same response fields.
Python
openai — chat, streaming, tool calls
from openai import OpenAI
client = OpenAI(
base_url="https://atmorouter.dev/v1",
api_key="ar-xxxxxxxxxxxx",
)
res = client.chat.completions.create(
model="atmo/deepseek-v4.1-flash",
messages=[{"role": "user", "content": "Explain PKCE."}],
)
print(res.choices[0].message.content)Node.js
openai — drop-in client replacement
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://atmorouter.dev/v1",
apiKey: process.env.ATMOROUTER_API_KEY,
});
const res = await client.chat.completions.create({
model: "atmo/deepseek-v4.1-flash",
messages: [{ role: "user", content: "Explain PKCE." }],
});Native /v1/messages support, including the Anthropic streaming event protocol. Any model in the catalogue can be called this way, not only Claude.
Anthropic SDK
Messages API, native Claude
from anthropic import Anthropic
client = Anthropic(
base_url="https://atmorouter.dev",
api_key="ar-xxxxxxxxxxxx",
)
msg = client.messages.create(
model="ag/claude-opus-4-6-thinking",
max_tokens=1024,
messages=[{"role": "user", "content": "Write a haiku."}],
)
print(msg.content[0].text)cURL
x-api-key header, as Anthropic expects
curl https://atmorouter.dev/v1/messages \
-H "x-api-key: ar-xxxxxxxxxxxx" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "ag/claude-opus-4-6-thinking",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello"}]
}'Errors on this surface use the Anthropic error envelope, so Anthropic SDKs parse them correctly.
Server-sent events pass through byte-for-byte. Exact token usage arrives on the final frame, and that is what you are billed on.
Streaming with usage
SSE passthrough — usage on the final frame, never a character estimate
stream = client.chat.completions.create(
model="atmo/deepseek-v4.1-flash",
messages=[{"role": "user", "content": "Count to five"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content if chunk.choices else None
if delta:
print(delta, end="", flush=True)
# The frame before [DONE] carries:
# {"usage": {"prompt_tokens": 9, "completion_tokens": 25}}
# Billing uses those exact counts.OpenAI base URL
https://atmorouter.dev/v1Include the /v1 suffix.
Anthropic base URL
https://atmorouter.devSDK appends /v1 itself.
Auth header
Authorization: Bearer ar-…x-api-key is accepted too.
Cost header
X-Atmorouter-CostExact amount deducted, every response.
Create an account, grab a key, and make your first call in minutes.