anoman
Sign InGet API Key
Documentation home

Migrate from OpenAI

Anoman is a drop-in replacement for OpenAI's API. Change base_url + api_key. Keep all your code. Get guardrails, observability, and multi-provider routing for free.

Before vs after

Python — before & after

# BEFORE: raw OpenAI
from openai import OpenAI
 
client = OpenAI(api_key="sk-...")
 
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hi"}],
)
 
# AFTER: through Anoman — only base_url + api_key change
from openai import OpenAI
 
client = OpenAI(
    base_url="https://api.anoman.io/v1",  # ← 1
    api_key="anm-sk-...",                  # ← 2
)
 
response = client.chat.completions.create(
    model="gpt-4o",  # same slug — works unchanged
    messages=[{"role": "user", "content": "Hi"}],
)

TypeScript — before & after

// BEFORE: raw OpenAI
import OpenAI from "openai";
 
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
 
const response = await client.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: "Hi" }],
});
 
// AFTER: through Anoman
import OpenAI from "openai";
 
const client = new OpenAI({
  baseURL: "https://api.anoman.io/v1",     // ← 1
  apiKey: process.env.ANOMAN_API_KEY,       // ← 2
});
 
const response = await client.chat.completions.create({
  model: "gpt-4o",  // same slug — works unchanged
  messages: [{ role: "user", content: "Hi" }],
});

Env var — fastest path

# If you're using the OpenAI SDK with env vars (and not passing
# baseURL in code), you can migrate without touching any code at all:
 
# Before:
OPENAI_API_KEY=sk-...
 
# After:
OPENAI_API_KEY=anm-sk-...
OPENAI_BASE_URL=https://api.anoman.io/v1

That's it. The OpenAI SDK doesn't care which server it's talking to — it just wants base_url + api_key. Streaming, tools, vision, batching, function calling — all unchanged.

What stays the same

  • Every OpenAI SDK method works unchanged — chat.completions.create, embeddings.create, models.list, etc.
  • Streaming via stream=True — identical SSE shape.
  • Tool / function calling — identical request shape, identical response.
  • Vision (image inputs) — identical multimodal message format.
  • JSON mode — response_format={"type": "json_object"} works as-is.
  • Async clients (AsyncOpenAI) — fully supported.
  • Error handling — same exception classes (openai.RateLimitError, APIStatusError, etc.).

No code changes required

  • Guardrails on every request — prompt injection detection, PII masking, content moderation. See the pipeline.
  • Full observability — every request shows up in the dashboard Traces view with timing, cost, region.
  • Cost capture per request — _anoman.cost_usd on every response.
  • Caching for free — Anthropic / OpenAI / Google prompt caching is auto-injected for long system prompts. See caching.
  • Multi-provider failover — when OpenAI is down, your model: gpt-4o call doesn't break (configurable per key).
  • Rate-limit headers — see your usage in real time per request.
// Every response from Anoman now carries the _anoman extension.
// Your OpenAI SDK code doesn't break — it ignores unknown fields.
 
{
  "choices": [...],          // same as before
  "usage": {...},            // same as before
  "_anoman": {               // NEW — Anoman additions
    "guardrails": {          // prompt injection / PII / content all ran
      "injection": { "status": "pass", "score": 0.02 },
      "pii":       { "status": "pass" },
      "content":   { "status": "pass" }
    },
    "routing": { "region": "id" },   // where data was processed
    "cache":   { "hit": false },     // cache status
    "cost_usd": "0.000041",          // exact cost of this request
    "weighted_tokens": 1240          // quota consumed
  }
}

Hundreds of models, one client

Once your code is pointed at Anoman, you can call any model in our catalog by changing the model parameter. No new client, no new key.

# Same client, different model slug.
response = client.chat.completions.create(
    model="claude-sonnet-4-6",   # ← was an Anthropic call before
    messages=[{"role": "user", "content": "Hi"}],
)
 
response = client.chat.completions.create(
    model="deepseek-v3",         # ← OSS at 75% lower cost
    messages=[{"role": "user", "content": "Hi"}],
)
 
response = client.chat.completions.create(
    model="gemini-1.5-pro",      # ← 2M-token context window
    messages=[{"role": "user", "content": "Hi"}],
)
# Browse the full catalog at https://anoman.io/models

Production rollout

  1. Create an Anoman API key in the dashboard. Add an env var for it.
  2. Point a small slice of traffic at Anoman first (e.g. a feature flag for 5% of users). Verify guardrails don't block legitimate prompts in your domain.
  3. Tune the policy group in Guardrails settings — PII mode, injection threshold — to match your acceptable false-positive rate.
  4. Cut over the rest of your traffic.
  5. Set a per-key monthly USD budget so a runaway script hits 402 instead of draining your account.
  6. Decommission your direct OpenAI key (or keep it for emergency fallback).

Try it now — free API key.

Two lines to change. Five minutes to integrate.

On this page