# Migrate in one prompt

> Point an existing OpenAI, Anthropic, or Gemini project at MirAPI with a single coding-agent prompt — swap the base URL, key, and model, then verify with a checklist.

Moving an existing project to MirAPI is a provider swap, not a rewrite. MirAPI exposes OpenAI-compatible, Anthropic, and Gemini endpoints behind a single API base, so one prompt can have your coding agent find every client, retarget the base URL, swap the key and model, and leave streaming, tool calling, and response handling untouched.

## What changes

Most migrations come down to three edits: the **base URL**, the **API key**, and the **model ID**. Everything else — streaming, tool calling, structured outputs, and response shapes — stays as the framework already implements it.

### Base URLs and auth

Each protocol has its own base URL and auth header, and all three draw from the same prepaid balance.

| Protocol | Base URL | Auth |
|---|---|---|
| OpenAI-compatible | `https://api.mirapi.ai/v1` | `Authorization: Bearer <key>` |
| Anthropic | `https://api.mirapi.ai` (bare, no `/v1`) | `x-api-key: <key>` (or `Authorization: Bearer <key>`) |
| Gemini | `https://api.mirapi.ai/v1beta` | `x-goog-api-key: <key>` (or `?key=`) |

Rule of thumb: if a tool appends the path itself (for example `/chat/completions`), give it `https://api.mirapi.ai/v1`; if it expects a bare origin, give it `https://api.mirapi.ai`.

### Pick a model

Use the exact catalogue name in requests. `deepseek-chat` is a safe default. Confirm any name against `GET /v1/models`, which returns `id`, `name`, `context_length`, `pricing`, `supported_parameters`, and `output_modalities` per model. The `vendor/` prefix is only for browsing in the console — never send it in an API request.

## The prompt

Open Claude Code or Cursor at the project root and paste:

```text
Migrate this project to use MirAPI.

1. Find every place that configures an OpenAI, Anthropic, or Gemini client:
SDK constructors, environment variable examples, .env templates, and config files.
2. Set the base URL per protocol:
   - OpenAI-compatible: https://api.mirapi.ai/v1
   - Anthropic: https://api.mirapi.ai (bare, no /v1)
   - Gemini: https://api.mirapi.ai/v1beta
3. Store the key in a single variable, MIRAPI_API_KEY, and set the header each
   protocol expects: Authorization: Bearer for OpenAI, x-api-key for Anthropic,
   x-goog-api-key for Gemini.
4. Replace the default model with deepseek-chat (exact catalogue name).
5. Keep request logic — streaming, tools, structured outputs, retries — unchanged;
   do not rewrite auth beyond pointing it at the key above.
6. Show a diff summary of every file you changed, and flag anything you could not
   map cleanly instead of guessing.
```

Let the agent finish, then review the diff — do not accept silent edits to unrelated files.

## Before you run

- **A coding agent with file access** — Claude Code or Cursor, already configured for MirAPI (see [Claude Code](/docs/integrations/claude-code) or [Cursor](/docs/integrations/cursor)).
- **A MirAPI key with balance** — create the key in the console (https://console.mirapi.ai) and top up if needed; the project references it as `MIRAPI_API_KEY`.
- **A clean git working tree** — so you can review every change before committing.

:::caution
This prompt edits your codebase and may run the project's lint, typecheck, or test commands. Run it on a branch and review the diff before merging.
:::

## Verification checklist

Run these in order:

1. List models with the new key and confirm `deepseek-chat` is present:

   ```bash
   curl https://api.mirapi.ai/v1/models -H "Authorization: Bearer $MIRAPI_API_KEY"
   ```

2. Make one chat call from the project's own SDK (not from curl) and confirm it returns a normal completion.
3. Search for stale keys and base URLs — no hardcoded `sk-...` values should remain in tracked files:

   ```bash
   grep -rn "sk-" --include="*.py" --include="*.ts" --include="*.toml" .
   ```

4. If the project streams, confirm streaming still works. MirAPI streams standard SSE: `data:` lines ending in `data: [DONE]`.
5. Confirm the test requests appear in the console billing log and in `GET /api/log/token`.

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| `401` | Missing, invalid, or unknown key | Check `MIRAPI_API_KEY` and the auth header |
| `403` | Key is valid but rejected — model not on the key's whitelist, quota, IP allowlist, or empty balance | Top up, or add the model to the whitelist |
| `413` | Request body too large | Reduce the payload and retry |
| `429` | Rate limited | Retry with jittered exponential backoff (there is no `Retry-After` header; the gateway does not retry for you) |
| `5xx` | All channels for the model are unhealthy | Retry — idempotent requests are safe to repeat; the gateway never silently swaps to another model |

When the balance is exhausted, requests return `403`; topping up restores the same key immediately. Include the request ID from the end of any error message when you open a support ticket.

## Billing

MirAPI is prepaid: you top up a USD balance at https://console.mirapi.ai, with no subscription, monthly fee, or minimum, and the balance never expires. Text and multimodal chat bill by token — input, output, and cache read, each priced per 1M tokens — with reasoning tokens billed as output and cache reads cheaper than fresh input. The migration itself costs a few cents at most (one or two short agent turns); every request after that bills at the model's catalogue rate. Non-streaming `usage` reports token counts only — dollar amounts live in the console billing log and `GET /api/log/token`. See [Billing & top-ups](/docs/billing).

## Related links

- [First integration](/docs/tutorials/first-integration) — a smaller, hand-run setup walkthrough
- [Claude Code](/docs/integrations/claude-code)
- [Cursor](/docs/integrations/cursor)
- [Models & pricing](/docs/models)
- [Errors](/docs/api-reference/errors)