← back to blog

Migrating from the Anthropic API to MonoRouter in 5 Minutes

Already using the Anthropic API? Switch to MonoRouter without changing your code. Just update two environment variables.

If you're already using the Anthropic API, migrating to MonoRouter takes less time than reading this post. Your code doesn't change — only your configuration does.

Before and After

Python

Your code stays exactly the same. Only the environment changes:

import anthropic

# This code works with BOTH the Anthropic API and MonoRouter.
# The SDK reads ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL
# from the environment automatically.
client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Explain dependency injection in Python"}],
)
print(response.content[0].text)

Before (direct API — billed per token):

export ANTHROPIC_API_KEY="sk-ant-api03-..."
# Requests go to api.anthropic.com
# Cost: $3/MTok input, $15/MTok output (Sonnet)

After (through MonoRouter — uses your subscription):

export ANTHROPIC_API_KEY="mr_live_abc123"
export ANTHROPIC_BASE_URL="https://api.monorouter.dev/v1"
# Requests go to api.monorouter.dev
# Cost: $0 incremental (covered by your Claude subscription)

TypeScript

Same story — zero code changes:

import Anthropic from "@anthropic-ai/sdk";

// Reads ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL from env
const client = new Anthropic();

const message = await client.messages.create({
  model: "claude-sonnet-4-20250514",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Write a React hook for debounced input" }],
});

console.log(message.content[0].text);

Shell Setup by Platform

Bash (~/.bashrc):

export ANTHROPIC_API_KEY="mr_live_abc123"
export ANTHROPIC_BASE_URL="https://api.monorouter.dev/v1"

Zsh (~/.zshrc):

export ANTHROPIC_API_KEY="mr_live_abc123"
export ANTHROPIC_BASE_URL="https://api.monorouter.dev/v1"

Fish (~/.config/fish/config.fish):

set -gx ANTHROPIC_API_KEY "mr_live_abc123"
set -gx ANTHROPIC_BASE_URL "https://api.monorouter.dev/v1"

PowerShell ($PROFILE):

$env:ANTHROPIC_API_KEY = "mr_live_abc123"
$env:ANTHROPIC_BASE_URL = "https://api.monorouter.dev/v1"

direnv (.envrc in your project root — auto-loaded when you cd in):

export ANTHROPIC_API_KEY="mr_live_abc123"
export ANTHROPIC_BASE_URL="https://api.monorouter.dev/v1"

After editing, reload your shell: source ~/.zshrc (or restart your terminal).

Verification Script

Save this as verify_monorouter.py and run it to confirm everything is working:

#!/usr/bin/env python3
"""Verify MonoRouter routing is active."""

import anthropic
import sys

client = anthropic.Anthropic()

# Check that we're pointing at MonoRouter
base_url = client.base_url
print(f"Base URL: {base_url}")

if "monorouter" not in str(base_url):
    print("⚠  WARNING: Not pointing at MonoRouter.")
    print("   Set ANTHROPIC_BASE_URL=https://api.monorouter.dev/v1")
    sys.exit(1)

# Send a test request
try:
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=50,
        messages=[{"role": "user", "content": "Respond with exactly: MONOROUTER_OK"}],
    )
    text = response.content[0].text
    print(f"Response: {text}")
    print(f"Model: {response.model}")
    print(f"Tokens: {response.usage.input_tokens} in, {response.usage.output_tokens} out")
    print("\n✓ MonoRouter is working correctly.")
except anthropic.AuthenticationError:
    print("✗ Authentication failed. Check your ANTHROPIC_API_KEY.")
    sys.exit(1)
except anthropic.APIConnectionError as e:
    print(f"✗ Connection failed: {e}")
    sys.exit(1)
$ python verify_monorouter.py
Base URL: https://api.monorouter.dev/v1
Response: MONOROUTER_OK
Model: claude-sonnet-4-20250514
Tokens: 16 in, 5 out

✓ MonoRouter is working correctly.

Keeping the API as Fallback

Some teams run a dual setup during the transition period. Here's a simple wrapper that tries MonoRouter first and falls back to the direct API:

import anthropic

def get_client() -> anthropic.Anthropic:
    """Try MonoRouter first, fall back to direct API."""
    try:
        mr_client = anthropic.Anthropic(
            api_key="mr_live_abc123",
            base_url="https://api.monorouter.dev/v1",
            timeout=10.0,
        )
        # Quick health check
        mr_client.messages.create(
            model="claude-haiku-3-5-20241022",
            max_tokens=10,
            messages=[{"role": "user", "content": "hi"}],
        )
        return mr_client
    except Exception:
        # MonoRouter unavailable — fall back to API
        return anthropic.Anthropic(api_key="sk-ant-api03-...")

In practice, most teams find MonoRouter reliable enough to use as their sole endpoint within the first week.

What About Existing Conversations?

MonoRouter is stateless — it doesn't maintain conversation history. Each request is independent. This means there's nothing to migrate on the conversation side. Your application manages its own conversation state (as it does with the direct API), and MonoRouter just proxies each message.

Rolling Back

If you decide MonoRouter isn't for you, remove the ANTHROPIC_BASE_URL variable and restore your original API key:

# Remove from your shell profile
unset ANTHROPIC_BASE_URL
export ANTHROPIC_API_KEY="sk-ant-api03-..."

Your code goes back to hitting the Anthropic API directly. No cleanup needed — MonoRouter doesn't modify your application state.