---
title: "Migrate to MiniRouter"
description: "Change the base URL, the key and the model ID. Your SDK stays."
canonical_url: "https://minirouter.sh/docs/guides/migrate"
markdown_url: "https://minirouter.sh/docs/guides/migrate.md"
last_updated: "2026-09-26"
---

# Migrate to MiniRouter

Change the base URL, the key and the model ID. Your SDK stays.

[Get a key](https://minirouter.sh/key)

MiniRouter speaks the OpenAI [Chat Completions and Responses](https://minirouter.sh/docs/parameters) APIs and the Anthropic Messages API. Existing SDKs work unchanged: point them at MiniRouter, pay from one [balance](https://minirouter.sh/docs/billing) and pick any model in the [catalog](https://minirouter.sh/models).

> **Note:** OpenAI clients take `https://api.minirouter.sh/v1`. Anthropic clients take `https://api.minirouter.sh` and add `/v1/messages` themselves.

## Quick start

### 1. Get a key

[Create a key](https://minirouter.sh/key), then export it where your app runs.

**macOS / Linux**

```sh
export MINIROUTER_KEY=mr-live-YOUR-KEY-HERE
```

**Windows**

```powershell
setx MINIROUTER_KEY mr-live-YOUR-KEY-HERE
```

### 2. Change the base URL

Pass the MiniRouter URL and key to your client.

**Python**

```python
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.minirouter.sh/v1",
    api_key=os.environ["MINIROUTER_KEY"],
)

completion = client.chat.completions.create(
    model="openai/gpt-5.6-luna",
    messages=[{"role": "user", "content": "Hello"}],
)
print(completion.choices[0].message.content)
```

**TypeScript**

```ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.minirouter.sh/v1",
  apiKey: process.env.MINIROUTER_KEY,
});

const completion = await client.chat.completions.create({
  model: "openai/gpt-5.6-luna",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(completion.choices[0].message.content);
```

**cURL**

```sh
curl https://api.minirouter.sh/v1/chat/completions \
  -H "Authorization: Bearer $MINIROUTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "openai/gpt-5.6-luna",
  "messages": [
    {
      "role": "user",
      "content": "Hello"
    }
  ]
}'
```

### 3. Use full model IDs

Prefix the author: `gpt-5.6-luna` becomes `openai/gpt-5.6-luna`. See [Model IDs](https://minirouter.sh/docs/guides/migrate#model-ids).

### 4. Verify

Send one request, then open [Activity](https://minirouter.sh/dashboard/activity). It lists the model, tokens and exact cost.

## Anthropic SDK

Messages accepts the key as `x-api-key` or a bearer token. Only the base URL changes.

**Python**

```python
from anthropic import Anthropic
import os

client = Anthropic(
    base_url="https://api.minirouter.sh",
    api_key=os.environ["MINIROUTER_KEY"],
)

message = client.messages.create(
    model="anthropic/claude-opus-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)
print(message.content[0].text)
```

**TypeScript**

```ts
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  baseURL: "https://api.minirouter.sh",
  apiKey: process.env.MINIROUTER_KEY,
});

const message = await client.messages.create({
  model: "anthropic/claude-opus-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello" }],
});
console.log(message.content);
```

**cURL**

```sh
curl https://api.minirouter.sh/v1/messages \
  -H "Authorization: Bearer $MINIROUTER_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
  "model": "anthropic/claude-opus-5",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "Hello"
    }
  ]
}'
```

## Vercel AI SDK

```ts
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { generateText } from "ai";

const minirouter = createOpenAICompatible({
  name: "minirouter",
  baseURL: "https://api.minirouter.sh/v1",
  apiKey: process.env.MINIROUTER_KEY,
  includeUsage: true,
});

const { text } = await generateText({
  model: minirouter("openai/gpt-5.6-luna"),
  prompt: "Hello",
});
console.log(text);
```

> **Tip:** `includeUsage` asks streams for usage and cost.

Any other OpenAI-compatible client takes the same base URL and key.

## Environment variables

OpenAI and Anthropic SDKs read these when code passes no URL or key.

| Variable | Value |
| --- | --- |
| `OPENAI_BASE_URL` | `https://api.minirouter.sh/v1` |
| `OPENAI_API_KEY` | Your MiniRouter key. |
| `ANTHROPIC_BASE_URL` | `https://api.minirouter.sh` |
| `ANTHROPIC_API_KEY` | Your MiniRouter key. |

**macOS / Linux**

```sh
export OPENAI_BASE_URL=https://api.minirouter.sh/v1
export OPENAI_API_KEY=mr-live-YOUR-KEY-HERE
```

**Windows**

```powershell
setx OPENAI_BASE_URL https://api.minirouter.sh/v1
setx OPENAI_API_KEY mr-live-YOUR-KEY-HERE
```

## Model IDs

| Before | After |
| --- | --- |
| `gpt-5.6-luna` | `openai/gpt-5.6-luna` |
| `claude-opus-5` | `anthropic/claude-opus-5` |
| `gemini-3.8-flash` | `google/gemini-3.8-flash` |

Copy exact IDs from the [catalog](https://minirouter.sh/models) or [list them](https://minirouter.sh/docs/models). Let MiniRouter choose with [`minirouter/auto`](https://minirouter.sh/docs/auto-router).

> **Warning:** A bare provider name returns 404 [`unknown_model`](https://minirouter.sh/docs/errors#unknown_model), often with a suggestion.

## What stays, what changes

- [Request bodies](https://minirouter.sh/docs/parameters): Chat Completions, Responses and Messages shapes.
- [Streaming](https://minirouter.sh/docs/streaming): Server-sent events, as before.
- [Tools](https://minirouter.sh/docs/tools): Function calling and structured output.

| Area | Detail |
| --- | --- |
| Cost | `usage.cost` and `x-minirouter-cost-usd`. See [billing](https://minirouter.sh/docs/billing). Chat Completions streams carry it when `stream_options.include_usage` is set. |
| Balance | `x-minirouter-balance-usd` on every response. |
| Served by | `x-minirouter-model` and `x-minirouter-provider`. |
| Errors | `error.code` and `x-minirouter-error-code` name the cause. See [errors](https://minirouter.sh/docs/errors). Messages keeps the Anthropic error shape. |
| Routing | Optional [`models`](https://minirouter.sh/docs/model-fallbacks) fallbacks and [`provider`](https://minirouter.sh/docs/provider-selection) settings. |
| Paths | Paths under `/api/v1` also work. |

## Roll out

### 1. One key per environment

Create them in [Keys](https://minirouter.sh/dashboard/keys), each with [limits](https://minirouter.sh/docs/rate-limits).

### 2. Add credits

Top up in [billing](https://minirouter.sh/dashboard/billing).

### 3. Switch staging

- Swap base URL, key and model IDs.
- Log `usage.cost`, or watch [Usage](https://minirouter.sh/dashboard/usage).
- Handle 402 and 429 by `error.code`.

### 4. Switch production

Keep the old config until traffic settles.

> **Warning:** A low balance returns 402 [`insufficient_credits`](https://minirouter.sh/docs/errors#insufficient_credits). Fund the account before switching production.

## FAQ

### Do I need a new SDK?

No. OpenAI, Anthropic and OpenAI-compatible clients work with a new base URL and key.

### Does the Responses API work?

Yes. Chat Completions and Responses both work through the OpenAI SDK.

### How do I see what a request cost?

Read `usage.cost` or `x-minirouter-cost-usd`, or open [Activity](https://minirouter.sh/dashboard/activity).

### What if a model fails?

List up to three backups in [`models`](https://minirouter.sh/docs/model-fallbacks), or `fallbacks` on Messages. If one cannot start a response, the next answers.

### Can I share one model setting across apps?

Call a [preset](https://minirouter.sh/docs/presets) as `@preset/your-slug` and change its model from the [dashboard](https://minirouter.sh/dashboard/presets).
