# Quickstart

> Start using MirAPI in five minutes: create a key, pick a base URL, and send your first request over the OpenAI-, Anthropic-, or Gemini-compatible API.

MirAPI gives you many models through a single API. One key, one prepaid balance, and you switch models by changing a single field — no new SDK, no new account.

The whole flow takes about five minutes:

1. Register at https://console.mirapi.ai and confirm your email.
2. Top up a small prepaid balance (no subscription, no minimum spend, and it never expires).
3. Create an API key.
4. Send your first request.

## 1. Create an account and a key

1. Register at https://console.mirapi.ai.
2. Open **Billing** and top up a small amount — every request is deducted from this balance.
3. Open **API Keys**, create a key, and copy it. It is shown only once.
4. Store it in an environment variable:

```bash
export MIRAPI_API_KEY=sk-...
```

## 2. Choose your base URL

MirAPI speaks the three mainstream protocols, and the base URL plus auth header are the only things that change between them:

| Protocol | Base URL | Auth header |
|---|---|---|
| OpenAI-compatible | `https://api.mirapi.ai/v1` | `Authorization: Bearer $MIRAPI_API_KEY` |
| Anthropic | `https://api.mirapi.ai` | `x-api-key` or `Authorization: Bearer` |
| Gemini | `https://api.mirapi.ai` or `https://api.mirapi.ai/v1beta` | `x-goog-api-key` or `?key=` |

Most SDKs and tools already speak one of these three. A useful rule of thumb: **if a tool appends `/chat/completions` (or any other path) to the base URL itself, enter `https://api.mirapi.ai/v1`**. The same key works across all three protocols.

## 3. Find a model

Pass model names exactly as the catalogue returns them — for example `deepseek-chat`. The authoritative list always comes from the API itself:

```bash
curl https://api.mirapi.ai/v1/models \
  -H "Authorization: Bearer $MIRAPI_API_KEY" | jq '.data[].id'
```

Each entry reports its `context_length`, per-token `pricing` (input, output, and cache read), `supported_parameters`, and `output_modalities`. Browse the console catalogue to compare context windows, capabilities (tools, vision, reasoning), and prices before you pick. The `vendor/` prefix you see in the console is only for browsing and filtering — never send it in a request.

## 4. Send your first request

The minimal request needs just two fields, plus an optional `stream` for SSE:

| Parameter | Required | Description |
|---|---|---|
| `model` | Yes | Model id exactly as the catalogue returns it, e.g. `deepseek-chat` |
| `messages` | Yes | Ordered list of `{ "role", "content" }` objects |
| `stream` | No | `true` returns standard SSE deltas instead of one JSON response |

### curl

```bash
curl https://api.mirapi.ai/v1/chat/completions \
  -H "Authorization: Bearer $MIRAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-chat",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```

### Python

```bash
pip install openai
```

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.mirapi.ai/v1",
    api_key=os.environ["MIRAPI_API_KEY"],
)

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "Hello!"}],
)

print(response.choices[0].message.content)
```

### TypeScript

```bash
npm install openai
```

```ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.mirapi.ai/v1",
  apiKey: process.env.MIRAPI_API_KEY!,
});

const response = await client.chat.completions.create({
  model: "deepseek-chat",
  messages: [{ role: "user", content: "Hello!" }],
});

console.log(response.choices[0].message.content);
```

## 5. Anthropic and Gemini requests

The same key and balance also work over the Anthropic and Gemini protocols. Whether a given model is available on a given protocol depends on the model — check its capability flags in the catalogue.

### Anthropic

```bash
curl https://api.mirapi.ai/v1/messages \
  -H "x-api-key: $MIRAPI_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "deepseek-chat",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```

```bash
pip install anthropic
```

```python
import os
from anthropic import Anthropic

client = Anthropic(
    base_url="https://api.mirapi.ai",
    api_key=os.environ["MIRAPI_API_KEY"],
)

message = client.messages.create(
    model="deepseek-chat",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)

print(message.content[0].text)
```

### Gemini

```bash
curl "https://api.mirapi.ai/v1beta/models/deepseek-chat:generateContent" \
  -H "x-goog-api-key: $MIRAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{"parts": [{"text": "Hello!"}]}]
  }'
```

```bash
pip install google-genai
```

```python
import os
from google import genai

client = genai.Client(
    api_key=os.environ["MIRAPI_API_KEY"],
    http_options={"base_url": "https://api.mirapi.ai"},
)

response = client.models.generate_content(
    model="deepseek-chat",
    contents="Hello!",
)

print(response.text)
```

## 6. Read streaming responses

Set `stream: true` and read the deltas as they arrive. The stream is standard SSE (`data:` lines, ending with `data: [DONE]`), so every OpenAI-compatible SDK handles it without extra configuration. For reasoning models, the reasoning content arrives before the answer:

```python
stream = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

## 7. Handle errors

The gateway does not retry for you, so retry policy is your responsibility. Every error message ends with a request ID — include it in support tickets.

| Status | Meaning | What to do |
|---|---|---|
| `401` | Key missing, invalid, or unknown | Check the `Authorization: Bearer` header and the key value |
| `403` | Key valid but rejected: insufficient balance, model not on the whitelist, quota, or IP | Fix the cause (top up, check whitelist/quota/IP), then retry |
| `413` | Request too large | Reduce the payload |
| `429` | Rate limited | Retry with jittered exponential backoff (1s → 2s → 4s, cap ~30s); no `Retry-After` header is sent |
| `500` | Upstream or other server error | Safe to retry idempotent requests |

When your balance runs out, requests return **403**. Top up and the same key works again immediately. Reconcile spending from the console billing log, `GET /api/usage/token` (account summary), or `GET /api/log/token` (per-request detail).

:::tip
The `usage` in a non-streaming response reports token counts only — it never includes a dollar amount. Reconcile spend in the console billing log or via `GET /api/log/token`.
:::

## Use it from your tools

The same key and base URL work in your everyday tools:

- **Claude Code**: `ANTHROPIC_BASE_URL="https://api.mirapi.ai"` + `ANTHROPIC_AUTH_TOKEN="$MIRAPI_API_KEY"` — see [Claude Code](/docs/integrations/claude-code).
- **Codex CLI**: a `[model_providers.mirapi]` block in `~/.codex/config.toml` with `wire_api = "responses"` — see [Codex CLI](/docs/integrations/codex).
- **Cursor, Cline, LangChain, n8n and more**: point them at `https://api.mirapi.ai/v1` with the same key — see [Integrations](/docs/integrations).

## Related links

- [Configuration](/docs/configuration) — parameters, streaming, and timeouts
- [Models and pricing](/docs/models) — what the catalogue tells you about each model
- [Billing](/docs/billing) — how the prepaid balance and pricing work
- [Authentication](/docs/api-reference/authentication) — key formats and header rules
- [Errors](/docs/api-reference/errors) — full error envelope reference
- [Integrations](/docs/integrations) — connect your tools and frameworks