# Migrate from OpenRouter (/docs/migrate-from-openrouter)

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 [#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](https://www.ohmygpt.com/keys) |

```python tab="Python"
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)
```

```ts tab="TypeScript"
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://api.ohmygpt.com/v1',
  apiKey: process.env.OHMYGPT_API_KEY,
});

const completion = await client.chat.completions.create({
  model: 'ohmygpt/mock',
  messages: [{ role: 'user', content: 'Hello' }],
});
console.log(completion.choices[0].message.content);
```

```bash tab="cURL"
curl https://api.ohmygpt.com/v1/chat/completions \
  -H "Authorization: Bearer $OHMYGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "ohmygpt/mock", "messages": [{"role": "user", "content": "Hello"}]}'
```

```text
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 [#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:

```bash
curl -s https://api.ohmygpt.com/v1/models | jq -r '.data[] | select(.available) | .id'
```

Prices are on the [Models](https://www.ohmygpt.com/models) page. If an ID is off, the response is a `404` that names it:

```json
{
  "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 [#what-keeps-working]

- **The `provider` object** on Chat Completions and Responses, with `order`, `only`, `ignore`, `allow_fallbacks` and `sort` (`price`, `latency` or `throughput`, as a string or as `{"by": "price"}`). OpenRouter's provider slugs such as `amazon-bedrock` and `google-vertex` work as they are; each model lists its own under `providers[].provider` in `GET /v1/models`. See [Provider Routing](/docs/provider-routing).
- **`openrouter/auto`** and its `auto-router` plugin (`allowed_models`, `excluded_models`, `cost_tier`). See [Auto Router](/docs/auto-router).
- **App attribution headers**: `HTTP-Referer`, `X-OpenRouter-Title` (or `X-Title`) and `X-OpenRouter-Categories` are read as they are. See [App Attribution](/docs/app-attribution).
- **Streaming, tool calls and structured output** (`response_format` with 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 [#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](/docs/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](/docs/api/thinking) |
| `provider` fields such as `data_collection`, `zdr`, `quantizations` or `max_price` | Use `provider.only` to pick the exact providers you want |

## Check the cost of each request [#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](https://www.ohmygpt.com/usage) lists every request with its cost, and [Costs](/docs/costs) explains Credits.

## Use the Anthropic and Gemini SDKs too [#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](/docs#base-url-and-protocols) lists each SDK's base URL.
