DEV Community

Dylan Brown
Dylan Brown

Posted on • Originally published at apisrouter.com

How to migrate from the OpenAI API to an OpenAI-compatible gateway in 5 minutes

I maintain a couple of side projects that all talk to LLMs through the OpenAI SDK. Last month I moved them from api.openai.com to an OpenAI-compatible gateway (APIsRouter) so I could hit Claude, Gemini, DeepSeek and a few Chinese models (GLM, Kimi, Qwen) from the same client. The whole migration took less time than writing this post, so here is the exact diff.

What actually changes

One thing: the base URL. If your code uses the official OpenAI SDK, you are already done after this:

# Python
from openai import OpenAI

client = OpenAI(
    api_key="sk-...",                      # key from the gateway console
    base_url="https://api.apisrouter.com/v1",
)

resp = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "hello"}],
)
Enter fullscreen mode Exit fullscreen mode
// Node / TypeScript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.APISROUTER_API_KEY,
  baseURL: "https://api.apisrouter.com/v1",
});
Enter fullscreen mode Exit fullscreen mode

No SDK swap, no request shape changes. Streaming, tool calling and JSON mode go through unchanged because the gateway speaks the same wire protocol.

If you cannot touch the code

Most frameworks read the standard env vars, so this also works:

export OPENAI_API_KEY="sk-..."
export OPENAI_BASE_URL="https://api.apisrouter.com/v1"
Enter fullscreen mode Exit fullscreen mode

That covers LangChain, LiteLLM, aider, Open WebUI, Cline and most agent frameworks without editing a line.

The part that surprised me: cross-vendor models in the same client

The model id is the router. Same client object, different vendors:

client.chat.completions.create(model="claude-sonnet-4-6", messages=msgs)
client.chat.completions.create(model="gemini-3.1-pro-preview", messages=msgs)
client.chat.completions.create(model="deepseek-v4-pro", messages=msgs)
client.chat.completions.create(model="glm-5.2", messages=msgs)
Enter fullscreen mode Exit fullscreen mode

If you have ever wanted to A/B two vendors inside one eval script without juggling three SDKs and three billing dashboards, this is the appeal. GET /v1/models lists everything your key can use.

Gotchas I hit

  1. Model ids are not always identical to the vendor's. Check the gateway's model list first instead of assuming. My eval script had gpt-5.5-turbo hardcoded from an old run and got a clean 404 with a readable error body, which made it easy to catch.
  2. Anthropic-native clients are a separate path. Claude Code and other tools that speak the Anthropic Messages API use the same base URL but the /v1/messages route. Worth knowing it exists; nothing to configure if you stay on the OpenAI protocol.
  3. Billing is prepaid. You top up first and usage draws down the balance. I prefer that failure mode over a surprise invoice, but if you expect postpaid invoicing, plan around it.

When this is not the right move

If you only ever call one vendor and you need that vendor's newest beta endpoints on day zero, staying direct is simpler. A gateway earns its place when you are comparing models, need a fallback vendor, or want Chinese models (GLM, Kimi, Qwen) that are annoying to buy access to from outside China.

Full endpoint reference and the current model catalog are on the docs page.

Happy to answer questions about the setup in the comments.

Top comments (0)