The fastest way to migrate from OpenRouter to n4n SDK changes is to treat both as OpenAI-compatible APIs and swap a handful of client settings. Most Python and TypeScript code that builds an OpenAI client will keep the same method calls; the differences are base URL, auth token, model naming conventions, and a few headers. This guide walks through the exact edits, with runnable snippets, and ends with a verification checklist.
Step 1: Inventory your OpenRouter-specific code
Before touching anything, find where you configure the client. In a Python service using the openai library (v1+), that’s usually:
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={
"HTTP-Referer": "https://your-app.com",
"X-Title": "My App",
},
)
Grep your repo for openrouter.ai, HTTP-Referer, X-Title, and route=. These are the only strings that typically need to change. If you pass route="fallback" inside extra_body, flag that line.
Step 2: Replace the base URL and credentials
n4n.ai exposes one OpenAI-compatible endpoint. Swap the base_url and read a new key from the environment.
from openai import OpenAI
import os
client = OpenAI(
base_url="https://api.n4n.ai/v1", # single endpoint, 240+ models
api_key=os.environ["N4N_API_KEY"],
)
That’s the core of the migrate from OpenRouter to n4n SDK changes. The OpenAI class from the official SDK works unchanged. If you used a third-party OpenRouter wrapper, drop it—the standard SDK is sufficient.
For shell tests, update your curl scripts:
curl https://api.n4n.ai/v1/chat/completions \
-H "Authorization: Bearer $N4N_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"openai/gpt-4o","messages":[{"role":"user","content":"hi"}]}'
Step 3: Reconcile model identifiers
OpenRouter popularized the provider/model slug format (anthropic/claude-3.5-sonnet, openai/gpt-4o). n4n.ai addresses the same 240+ models using the identical slash notation, so most model strings can stay as-is. Verify by listing models:
models = client.models.list()
for m in models.data[:5]:
print(m.id)
If you hardcoded a provider prefix that OpenRouter required but n4n doesn’t, the list call will show the canonical id. Adjust your config map accordingly. Don’t assume—print the list in staging.
Step 4: Drop or translate OpenRouter-only headers
OpenRouter uses HTTP-Referer and X-Title for app attribution. Those headers are not required by n4n.ai and can be removed. If you set them in default_headers, delete the dictionary:
# Before
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={"HTTP-Referer": "...", "X-Title": "..."},
)
# After
client = OpenAI(
base_url="https://api.n4n.ai/v1",
api_key=os.environ["N4N_API_KEY"],
)
If your code passed extra_body={"route": "fallback"}, remove it. Unlike OpenRouter, where you manually set route:'fallback', n4n.ai performs automatic fallback when a provider is degraded, while still honoring explicit client routing directives. You can drop the parameter and rely on the gateway, or pass a supported routing hint if you need provider pinning.
Step 5: Update TypeScript/Node SDK usage
The same pattern applies in Node. Using openai v4:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.n4n.ai/v1",
apiKey: process.env.N4N_API_KEY,
});
const completion = await client.chat.completions.create({
model: "openai/gpt-4o",
messages: [{ role: "user", content: "Explain fallback routing." }],
});
If you previously set defaultHeaders with HTTP-Referer, remove that property. Streaming code is identical:
const stream = await client.chat.completions.create({
model: "anthropic/claude-3.5-sonnet",
messages: [{ role: "user", content: "Stream a poem." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
Step 6: Handle cache-control hints
Both gateways forward provider-specific extensions. For Anthropic models, you may have used cache_control on a message:
response = client.chat.completions.create(
model="anthropic/claude-3.5-sonnet",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Large context block", "cache_control": {"type": "ephemeral"}}
],
)
n4n.ai forwards provider cache-control hints without modification, so this block works unchanged. If you previously relied on OpenRouter to translate cache hints, you can keep the same shape.
Step 7: Validate per-token usage metering
After migration, confirm that the usage object returns the expected breakdown. n4n.ai returns per-token metering in the standard usage field:
resp = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Count tokens in this sentence."}],
)
print(resp.usage.prompt_tokens, resp.usage.completion_tokens, resp.usage.total_tokens)
If you bill customers by token, pipe resp.usage into your metering pipeline. The field names match the OpenAI spec, so no parser changes are needed.
Step 8: Verify success
Run a staged test that exercises three paths: a standard completion, a streaming call, and a model from a different provider (e.g., switch from openai/gpt-4o to google/gemini-flash-1.5). Success criteria:
- HTTP 200 with valid
choices. usageobject present and non-zero.- No
HTTP-Referer/X-Titleheaders sent (check with a proxy or printclient.default_headers). - Streaming yields incremental deltas.
A minimal verification script:
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.n4n.ai/v1", api_key=os.environ["N4N_API_KEY"])
for model in ["openai/gpt-4o", "anthropic/claude-3.5-sonnet"]:
r = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "Ping"}],
)
assert r.choices[0].message.content
assert r.usage.total_tokens > 0
print(f"{model}: OK, {r.usage.total_tokens} tokens")
If both loops print OK, the migrate from OpenRouter to n4n SDK changes are complete. The only remaining work is rotating the API key in your secret store and deleting the old OpenRouter client instantiation.
Edge cases worth checking
- Timeout settings: OpenRouter and n4n may have different default upstream timeouts. Set
timeout=30explicitly on the client if your prompts are long. - Rate limit headers: OpenRouter returns
X-RateLimit-Remaining. n4n returns standard OpenAI rate-limit headers; update any custom throttling logic that parses header names. - Function calling: Tool schemas are passed through unchanged. Test one function-calling flow per provider you use.
The migration is fundamentally a configuration swap. The SDK method signatures, response shapes, and streaming protocols are unchanged because both platforms implement the OpenAI chat completions contract. Do the inventory, swap the constants, run the verification loop, and you’re done.