Migrate from OpenRouter
Switch OpenRouter code to OhMyGPT by changing the base URL and key; your SDK code keeps working.
Switching takes two changes: the base URL and the key. Your OpenAI SDK code, streaming, tool calls, structured output, the provider object and your app attribution headers keep working as they are. Every response then tells you its exact cost, and the free ohmygpt/mock model lets you check the switch before you spend anything.
1. Change the base URL and key
| Before | After | |
|---|---|---|
| Base URL | https://openrouter.ai/api/v1 | https://api.ohmygpt.com/v1 |
| Key | OpenRouter key | OhMyGPT key from API keys |
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.ohmygpt.com/v1",
api_key=os.environ["OHMYGPT_API_KEY"],
)
completion = client.chat.completions.create(
model="ohmygpt/mock",
messages=[{"role": "user", "content": "Hello"}],
)
print(completion.choices[0].message.content)This is a mock reply from OhMyGPT. Your integration works; switch to a real model when ready.The mock is free and is available once your account has been topped up. When it answers, your URL and key are right.
2. Set the model IDs
Model IDs use the same creator/model form. Many are identical; others use a different creator name or a hyphen in the version:
| OpenRouter | OhMyGPT |
|---|---|
openai/gpt-5.4-nano | openai/gpt-5.4-nano |
anthropic/claude-sonnet-4.6 | anthropic/claude-sonnet-4-6 |
x-ai/grok-4.7 | xai/grok-4.7 |
z-ai/glm-5.3 | zhipu/glm-5.3 |
moonshotai/kimi-k2.6 | moonshot/kimi-k2.6 |
List every ID with:
curl -s https://api.ohmygpt.com/v1/models | jq -r '.data[] | select(.available) | .id'Prices are on the Models page. If an ID is off, the response is a 404 that names it:
{
"error": {
"message": "The model `anthropic/claude-sonnet-4.6` does not exist. List available models with `GET /v1/models`.",
"type": "not_found_error",
"param": "model",
"code": "model_not_found"
}
}What keeps working
- The
providerobject on Chat Completions and Responses, withorder,only,ignoreandsort(price,latencyorthroughput). Use the provider slugs that each model lists underproviders[].providerinGET /v1/models. See Provider Routing. - App attribution headers:
HTTP-Referer,X-OpenRouter-Title(orX-Title) andX-OpenRouter-Categoriesare read as they are. See App Attribution. - Streaming, tool calls and structured output (
response_formatwith a JSON schema) in the standard OpenAI shapes. - Usage in every non-streaming response. Chat Completions streams report usage when you set
"stream_options": {"include_usage": true}, as on OpenAI.
Update these if your code uses them
| If your code sends | Do this on OhMyGPT |
|---|---|
A :floor model suffix | Use the plain model ID with "provider": {"sort": "price"} |
A :nitro model suffix | Use the plain model ID with "provider": {"sort": "throughput"} |
| Another model suffix | Use the plain model ID |
A models fallback list | Remove it. OhMyGPT already fails over across a model's providers automatically; see Reliability |
transforms or route | Remove them |
usage: {"include": true} | Remove it. Non-streaming responses always carry usage; on Chat Completions streams, set "stream_options": {"include_usage": true} |
A reasoning object on Chat Completions | Use reasoning_effort, for example "reasoning_effort": "low"; see Thinking |
provider fields such as allow_fallbacks: false, data_collection, zdr, quantizations or max_price | Use provider.only to pick the exact providers you want |
Check the cost of each request
Every response carries X-Request-ID. Non-streaming responses also carry X-Cost-Credits, the exact charge in Credits; streams send it as an SSE comment line : x-cost-credits: N before the final event. Usage lists every request with its cost, and Costs explains Credits.
Use the Anthropic and Gemini SDKs too
The same key also works with the Anthropic Messages API at /v1/messages and the Gemini API at /v1/models/{model}:generateContent. Code written for Anthropic's or Google's SDK can call OhMyGPT without changing format. The protocol table lists each SDK's base URL.