# Configuration

> Base URLs and authentication for the OpenAI, Anthropic, and Gemini protocols, plus chat parameters, streaming, billing, errors, and retry guidance for MirAPI requests.

Everything you configure for a request lives in two places: the base URL decides which protocol you call, and the request body decides which model and parameters you use. This page covers both, plus the parameters, error handling, and retry behaviour that apply across every request.

## Base URLs

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

Use the same key everywhere; the protocol is determined by the URL you call.

**Rule of thumb:** if your tool appends its own path (for example `/chat/completions`), point it at `https://api.mirapi.ai/v1`. Anthropic clients point at the bare `https://api.mirapi.ai` instead.

## Authentication

Send the key as `Authorization: Bearer <key>` — the scheme is case-insensitive, and a bare key with no scheme is also accepted. Anthropic endpoints additionally accept `x-api-key`; Gemini endpoints accept `x-goog-api-key` or `?key=`. The `OpenAI-Organization` header, if your client sends it, is ignored.

A key can carry four constraints: model whitelist (models outside it get 403), validity period, quota cap, and IP allowlist. A **401** means the key is missing, invalid, or unknown; a **403** means the key is valid but the request was rejected (balance, whitelist, quota, or IP).

See [Authentication](/docs/api-reference/authentication) for the full details.

## Chat parameters

The chat endpoint accepts the standard OpenAI-style parameters:

| Parameter | Purpose |
|---|---|
| `model` | Model name exactly as returned by `GET /v1/models` |
| `messages` | Conversation history with `system`, `user`, `assistant`, and `tool` roles |
| `temperature` | Sampling randomness, 0–2 (default 1) |
| `top_p` | Nucleus sampling, 0–1 (default 1) |
| `max_tokens` / `max_completion_tokens` | Upper bound on output tokens |
| `presence_penalty` / `frequency_penalty` | Discourage repeated tokens; negative values encourage reuse |
| `stop` | Up to 4 strings that stop generation |
| `seed` | Best-effort reproducibility where the model supports it |
| `stream` | `true` for SSE streaming |
| `tools` / `tool_choice` | Function calling — see [Tool calling](/docs/tutorials/tool-calling-agent) |
| `response_format` | JSON output — see [Structured outputs](/docs/guides/structured-outputs) |
| `reasoning_effort` | OpenAI-style reasoning control — see [Reasoning models](/docs/guides/reasoning) |

Not every model accepts every parameter. Check the model's `supported_parameters` in the catalogue (or its card in the console) for the supported set.

## Protocol variants

All three protocols share the same key and the same models. Choose the one your client already speaks.

### OpenAI-compatible

Use `https://api.mirapi.ai/v1` as the base URL. Chat runs through `POST /v1/chat/completions` (or `POST /v1/responses` for Responses-API clients). Authenticate with `Authorization: Bearer`. Errors come back in the OpenAI envelope `{"error":{"message","type","param","code"}}`, where `type` is `new_api_error` (gateway-side) or `upstream_error` (upstream failure, message sanitized).

### Anthropic

Use the bare `https://api.mirapi.ai` (no `/v1`) with the Anthropic SDK. The endpoint is `POST /v1/messages`, authenticated with `x-api-key` or `Authorization: Bearer`. Enable prompt caching with `cache_control: {"type":"ephemeral"}` — up to four explicit breakpoints, extendable to one hour with `"ttl":"1h"` at a higher write price. Errors use the Anthropic envelope `{"type":"error","error":{"type":"permission_error","message"}}`.

### Gemini

Use `https://api.mirapi.ai` or `https://api.mirapi.ai/v1beta` and authenticate with `x-goog-api-key` or `?key=`. Generation runs through `POST /v1beta/models/{model}:generateContent`; embeddings are also available in Gemini style at `POST /v1/engines/{model}/embeddings`.

## Streaming

Set `stream: true` and the endpoint answers with standard SSE — `data:` lines, one per chunk, terminated by `data: [DONE]`:

```bash
curl -N 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": "Count to three"}],
    "stream": true
  }'
```

Each chunk carries a `delta`; the final chunk carries the `usage` object. With reasoning models, the reasoning content arrives before the answer. Any OpenAI-compatible SDK parses the stream for you.

## Usage in responses

Non-streaming responses include a `usage` object with `prompt_tokens`, `completion_tokens`, and `total_tokens`. It reports token counts only — the monetary amount is in the console billing log and `GET /api/log/token`, never in the API response. To confirm a prompt-cache hit, look at `usage.prompt_tokens_details.cached_tokens` (and `cache_write_tokens` for writes).

## Billing

- MirAPI is prepaid: you top up USD at https://console.mirapi.ai; there is no subscription or minimum, and your balance never expires.
- Text and multimodal chat bill per 1M tokens in three tiers (input, output, cache read); image generation bills per image; video generation bills per second of output.
- Reasoning/thinking tokens bill as output; cache reads are cheaper than fresh input.
- An exhausted balance returns **403**, and topping up restores the same key immediately.
- Reconcile through the console billing log, `GET /api/usage/token` (account summary), or `GET /api/log/token` (per-request detail).

See [Billing & top-ups](/docs/billing) for the full picture.

## Errors

The API uses standard HTTP status codes:

| Status | Meaning |
|---|---|
| 401 | Missing, invalid, or unknown key — fix the credential |
| 403 | Valid key but request rejected (balance, whitelist, quota, IP) — resolve and retry |
| 413 | Request body too large — reduce it |
| 429 | Rate limited — back off and retry |
| 500 | Gateway or upstream failure — safe to retry idempotent requests |

Insufficient balance is rejected with **403**. Every error message ends with a request ID — include it in support tickets. See [Errors](/docs/api-reference/errors) for the response envelopes and sanitization behaviour.

## Timeouts and retries

- MirAPI does **not** retry requests on your behalf — retry logic belongs in your client.
- On 429, back off with exponential delay and jitter (1s → 2s → 4s, capped at ~30s) and stop after a few attempts. The 429 response has no `Retry-After` header.
- Retrying idempotent failures (429, 5xx) is safe. For non-idempotent requests (image/video generation, tool side effects), do not blindly replay the request.
- Set generous timeouts for non-streaming calls (30–60s) and no timeout for SSE streams.

## Troubleshooting

- **Wrong model or unsupported parameter** — copy the exact `id` from `GET /v1/models` and check its `supported_parameters`. The `vendor/` prefix is console-only and never part of an API request.
- **403 on a working key** — usually an exhausted balance (top up to restore it instantly), or a whitelist / quota / IP restriction on the key.
- **429 rate limits** — back off with jitter and retry; no `Retry-After` header is sent.
- **404 on an endpoint** — `/v1/files`, `/v1/fine-tunes`, and `/v1/messages/count_tokens` are not implemented and return 404.
- **Unexpected cost** — reasoning tokens are billed as output, and cache reads are cheaper than fresh input; reconcile in `GET /api/log/token`.

## Related links

- [Models & pricing](/docs/models)
- [Billing & top-ups](/docs/billing)
- [Errors](/docs/api-reference/errors)
- [Quickstart](/docs/quickstart)
- [Integrations](/docs/integrations)