Back to skills
SKILL.md
Openrouter Upgrade Migration
ASecurity'Migrate to OpenRouter from direct provider APIs or upgrade between SDK/model
- 2 stars
- 0 votes
- 0 copies
- 0 views
- Added November 11, 2026
Works with
Security analysis
100/100Pro scans all 8 files and shows the line behind each finding
npx -y skills add pauldx/claudifying --skill openrouter-upgrade-migration --agent claude-codeAre you the author of Openrouter Upgrade Migration?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/pauldx-openrouter-upgrade-migration)---
name: openrouter-upgrade-migration
description: 'Migrate to OpenRouter from direct provider APIs or upgrade between SDK/model
versions. Triggers: ''openrouter migrate'', ''openrouter upgrade'', ''switch to
openrouter'', ''migrate from openai to openrouter''.
'
allowed-tools: Read, Write, Edit, Bash, Grep
version: 2.0.0
license: MIT
tags:
- saas
- openrouter
- migration
- upgrade
compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
---
# OpenRouter Upgrade & Migration
## Current State
!`npm list openai 2>/dev/null | head -5`
!`pip show openai 2>/dev/null | head -5`
## Overview
Migrating to OpenRouter from a direct provider API (OpenAI, Anthropic) is minimal: change `base_url` and `api_key`, add two headers. The OpenAI SDK works natively with OpenRouter. This skill covers migrating from direct APIs, switching between models, upgrading SDK versions, and running comparison tests.
## Migration from Direct OpenAI
```python
# BEFORE: Direct OpenAI
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=200,
)
# AFTER: Via OpenRouter (3 lines changed)
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1", # ← Changed
api_key=os.environ["OPENROUTER_API_KEY"], # ← Changed
default_headers={ # ← Added
"HTTP-Referer": "https://my-app.com",
"X-Title": "my-app",
},
)
response = client.chat.completions.create(
model="openai/gpt-4o", # ← Add provider prefix
messages=[{"role": "user", "content": "Hello"}],
max_tokens=200,
)
```
## Migration from Direct Anthropic
```python
# BEFORE: Direct Anthropic SDK
import anthropic
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=200,
messages=[{"role": "user", "content": "Hello"}],
)
content = response.content[0].text
# AFTER: Via OpenRouter (using OpenAI SDK instead of Anthropic SDK)
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://my-app.com",
"X-Title": "my-app",
},
)
response = client.chat.completions.create(
model="anthropic/claude-3.5-sonnet", # OpenRouter model ID
messages=[{"role": "user", "content": "Hello"}],
max_tokens=200,
)
content = response.choices[0].message.content # OpenAI response format
```
## TypeScript Migration
```typescript
// BEFORE: Direct OpenAI
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// AFTER: Via OpenRouter
const client = new OpenAI({
baseURL: "https://openrouter.ai/api/v1",
apiKey: process.env.OPENROUTER_API_KEY,
defaultHeaders: {
"HTTP-Referer": "https://my-app.com",
"X-Title": "my-app",
},
});
// Change model from "gpt-4o" to "openai/gpt-4o"
```
## Migration Checklist
```python
MIGRATION_CHECKLIST = {
"config": [
"base_url changed to https://openrouter.ai/api/v1",
"API key changed to OPENROUTER_API_KEY (sk-or-v1-...)",
"HTTP-Referer and X-Title headers added",
"Model IDs prefixed with provider/ (e.g., openai/gpt-4o)",
],
"code": [
"All client initialization updated",
"Model IDs updated in all routes/configs",
"Error handling covers OpenRouter-specific codes (402, 408)",
"Streaming still works with new endpoint",
"Tool/function calling still works",
],
"testing": [
"Same prompts produce comparable quality output",
"Latency within acceptable range (expect +50-100ms)",
"Token counts match expectations",
"Cost tracking updated for OpenRouter pricing",
"Fallback chain tested",
],
"operations": [
"Credit balance sufficient for expected usage",
"Per-key credit limits configured",
"Monitoring updated to track OpenRouter metrics",
"Alerting on new error codes (402, 408)",
"Rollback plan documented",
],
}
```
## Model ID Migration Map
| Direct Provider | OpenRouter ID |
|----------------|---------------|
| `gpt-4o` | `openai/gpt-4o` |
| `gpt-4o-mini` | `openai/gpt-4o-mini` |
| `o1` | `openai/o1` |
| `claude-3-5-sonnet-20241022` | `anthropic/claude-3.5-sonnet` |
| `claude-3-haiku-20240307` | `anthropic/claude-3-haiku` |
| `gemini-2.0-flash` | `google/gemini-2.0-flash-001` |
| `llama-3.1-8b-instruct` | `meta-llama/llama-3.1-8b-instruct` |
## Comparison Test Script
```python
def compare_migration(prompt: str, old_model: str, new_model: str):
"""Run same prompt through old and new configurations to compare."""
import time
# New: OpenRouter
or_client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={"HTTP-Referer": "https://my-app.com", "X-Title": "migration-test"},
)
start = time.monotonic()
or_response = or_client.chat.completions.create(
model=new_model,
messages=[{"role": "user", "content": prompt}],
max_tokens=200, temperature=0,
)
or_latency = (time.monotonic() - start) * 1000
return {
"openrouter": {
"model": or_response.model,
"content": or_response.choices[0].message.content[:100],
"tokens": or_response.usage.prompt_tokens + or_response.usage.completion_tokens,
"latency_ms": round(or_latency),
},
}
# Test
result = compare_migration(
"What is 2+2?",
old_model="gpt-4o",
new_model="openai/gpt-4o",
)
print(json.dumps(result, indent=2))
```
## Feature Flag Migration
```python
import os
USE_OPENROUTER = os.environ.get("USE_OPENROUTER", "false").lower() == "true"
def get_llm_client():
"""Feature flag for gradual migration."""
if USE_OPENROUTER:
return OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={"HTTP-Referer": "https://my-app.com", "X-Title": "my-app"},
)
else:
return OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def get_model_id(model: str) -> str:
"""Map model IDs based on current backend."""
if USE_OPENROUTER and "/" not in model:
MODEL_MAP = {"gpt-4o": "openai/gpt-4o", "gpt-4o-mini": "openai/gpt-4o-mini"}
return MODEL_MAP.get(model, f"openai/{model}")
return model
```
## Error Handling
| Error | Cause | Fix |
|-------|-------|-----|
| 401 after migration | Using old API key with new base_url | Update to OpenRouter API key (sk-or-v1-...) |
| `model_not_found` | Missing provider prefix | Add `openai/` or `anthropic/` prefix to model ID |
| Different response format | Switched from Anthropic SDK to OpenAI SDK | Update response parsing: `.choices[0].message.content` |
| Higher latency | OpenRouter proxy overhead | Expected: +50-100ms; use streaming to mask it |
## Enterprise Considerations
- Migration from direct provider to OpenRouter requires only 3 lines of code change
- Use feature flags for gradual migration (10% -> 50% -> 100%)
- Run comparison tests on critical prompts before full migration
- OpenRouter adds ~50-100ms overhead; use streaming to mask perceived latency
- Keep direct provider keys active during migration for quick rollback
- Update monitoring dashboards for OpenRouter-specific metrics (generation_id, provider used)
## References
- [Examples](${CLAUDE_SKILL_DIR}/references/examples.md) | [Errors](${CLAUDE_SKILL_DIR}/references/errors.md)
- [Quickstart](https://openrouter.ai/docs/quickstart) | [OpenAI Compatibility](https://openrouter.ai/docs/frameworks)
Files in this skill
- SKILL.md
- references/code-pattern-updates.md
- references/configuration-migration.md
- references/errors.md
- references/examples.md
- references/migration-from-direct-api-to-sdk.md
- references/model-migration.md
- references/testing-during-migration.md
Attribution
Related skills
View all in ai-agents →Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.