# OpenAI-compatible API for open models: change the base URL
URL: https://docs.munito.ai/migrate-from-openai

Munito AI is an OpenAI-compatible API for open models, and it also serves the Anthropic Messages API. To move an app to Munito AI, keep your OpenAI or Anthropic SDK and change three values: the base URL, the API key and the model name.
The request and response formats stay the same, so the rest of your code does not change.

| SDK           | Base URL                             | Key                                      |
| ------------- | ------------------------------------ | ---------------------------------------- |
| OpenAI SDK    | `https://api.munito.ai/inference/v1` | `MUNITO_API_KEY`, sent as a Bearer token |
| Anthropic SDK | `https://api.munito.ai/inference`    | `MUNITO_API_KEY`, sent as `X-API-Key`    |

The Anthropic SDK adds `/v1/messages` itself, so its base URL has no `/v1`.
Create a key in the [console](https://console.munito.ai/keys) and export it:

```bash
export MUNITO_API_KEY="munitoai_..."
```

## OpenAI SDK in Python [#openai-sdk-in-python]

```bash
pip install openai
```

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.munito.ai/inference/v1",
    api_key=os.environ["MUNITO_API_KEY"],
)
response = client.chat.completions.create(
    model="qwen/qwen3.8-27b",
    messages=[{"role": "user", "content": "Name three rivers in Europe."}],
    max_tokens=2048,
)
print(response.choices[0].message.content)
```

## OpenAI SDK in TypeScript [#openai-sdk-in-typescript]

```bash
npm install openai
```

```ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.munito.ai/inference/v1",
  apiKey: process.env.MUNITO_API_KEY,
});
const response = await client.chat.completions.create({
  model: "qwen/qwen3.8-27b",
  messages: [{ role: "user", content: "Name three rivers in Europe." }],
  max_tokens: 2048,
});
console.log(response.choices[0].message.content);
```

## Anthropic SDK in Python [#anthropic-sdk-in-python]

```bash
pip install anthropic
```

```python
import os
from anthropic import Anthropic

client = Anthropic(
    base_url="https://api.munito.ai/inference",
    api_key=os.environ["MUNITO_API_KEY"],
)
message = client.messages.create(
    model="qwen/qwen3.8-27b",
    max_tokens=2048,
    messages=[{"role": "user", "content": "Name three rivers in Europe."}],
)
for block in message.content:
    if block.type == "text":
        print(block.text)
```

The answer also holds a `thinking` block before the `text` block, because the model reasons first. See [Reasoning](https://docs.munito.ai/reasoning).

## Model names [#model-names]

Munito AI names each model `<organization>/<model>`. Replace your OpenAI or Anthropic model name with one of these:

| Model                                  | Input               |
| -------------------------------------- | ------------------- |
| `qwen/qwen3.8-27b`                     | Text, images, video |
| `zai-org/glm-5.3-flash`                | Text, images, video |
| `deepseek-ai/deepseek-v4.1-flash-1017` | Text, images        |
| `deepseek-ai/deepseek-v4-flash`        | Text                |
| `aleph-alpha/kolibri-1`                | Text                |

The [model catalog](https://docs.munito.ai/models) has the details of each model, and `GET /inference/v1/models` lists the models that your key can use.
A model name that Munito AI does not serve returns `404` with code `model_not_found`:

```json
{
  "error": {
    "message": "The model gpt-4o does not exist, or you do not have access to it.",
    "type": "invalid_request_error",
    "param": "model",
    "code": "model_not_found"
  }
}
```

## Endpoints [#endpoints]

| Endpoint                         | Format                  |
| -------------------------------- | ----------------------- |
| `POST /v1/chat/completions`      | OpenAI Chat Completions |
| `POST /v1/responses`             | OpenAI Responses        |
| `POST /v1/messages`              | Anthropic Messages      |
| `POST /v1/messages/count_tokens` | Anthropic token count   |
| `POST /v1/audio/transcriptions`  | OpenAI speech to text   |
| `GET /v1/models`                 | OpenAI model list       |

Each path starts with `https://api.munito.ai/inference`. Munito AI has no embeddings endpoint and no file upload endpoint.
A path that Munito AI does not serve returns `404` with the detail `No API operation has this path.`

## What works differently [#what-works-differently]

Munito AI never ignores a parameter in silence. A parameter that it cannot apply returns `400`, so that you know at once.

### Chat Completions [#chat-completions]

| Parameter                             | On Munito AI                                                                                      |
| ------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `tools`                               | Function tools only. See [Tool calling](https://docs.munito.ai/tool-calling).                                 |
| `response_format`                     | `text`, `json_object` and `json_schema`. See [Structured outputs](https://docs.munito.ai/structured-outputs). |
| `reasoning_effort`                    | The levels differ for each model. See [Reasoning](https://docs.munito.ai/reasoning).                          |
| `max_tokens`, `max_completion_tokens` | A value above the model maximum is lowered to the maximum. It does not fail.                      |
| `n`                                   | 1 to 8.                                                                                           |
| `stop`                                | Up to 4 sequences.                                                                                |
| `logit_bias`                          | Not available on the public models.                                                               |
| `service_tier`                        | `priority`, `flex`, or `default` for standard. See [Service tiers](https://docs.munito.ai/service-tiers).     |
| `prompt_cache_key`, `user`            | Accepted. Munito AI uses them to keep a conversation where its prompt is cached.                  |
| `audio`, `modalities`                 | Rejected. Munito AI generates text only.                                                          |
| `prediction`                          | Rejected.                                                                                         |
| `functions`, `function_call`          | Rejected. Use `tools` and `tool_choice`.                                                          |
| `verbosity`                           | Rejected. Control the length with the prompt or `max_tokens`.                                     |
| `web_search_options`                  | Rejected. Munito AI has no hosted web search.                                                     |
| `prompt_cache_retention`              | Rejected. The cache retention is not configurable.                                                |

Munito AI also accepts `top_k`, `repetition_penalty` and `chat_template_kwargs`. `min_p` works on `aleph-alpha/kolibri-1` only.

A rejected parameter returns a message in this form:

```json
{
  "error": {
    "message": "'web_search_options' is not supported: hosted web search is not available",
    "type": "invalid_request_error",
    "param": "web_search_options",
    "code": null
  }
}
```

A parameter that no API knows returns `unknown parameter: 'name'`.

### Responses [#responses]

- Function tools work. A hosted web search tool is removed from the request, and the model answers without a search. Other hosted tools return `400`.
- Munito AI stores a response only when you send `store: true` (or `background: true`). OpenAI stores by default, so add `store: true` where your code uses `previous_response_id`.
  Without it, the chained request returns `400` with `previous response resp_... was not stored. Send store: true to continue a response.`
- `conversation`, `prompt`, `max_tool_calls`, `context_management`, `stream_options`, `prompt_cache_retention` and `text.verbosity` return `400`.
- `include` accepts only `message.output_text.logprobs` and `reasoning.encrypted_content`.

### Messages [#messages]

- The request accepts `model`, `messages`, `system`, `max_tokens`, `metadata`, `stop_sequences`, `stream`, `temperature`, `top_p`, `top_k`, `tools`, `tool_choice`, `thinking`, `output_config` and `chat_template_kwargs`.
  Another field returns `400` with `unknown messages parameter: <name>`.
- `max_tokens` is required. A value above the model maximum is lowered to the maximum.
- `tools` accepts only your own tools. A server tool, such as web search, returns `'tools' is not supported: only function tools are available`.
- `thinking.budget_tokens` is accepted, but the model does not keep to it. `max_tokens` limits the whole output.
- `context_management` is accepted and has no effect.
- To choose a [service tier](https://docs.munito.ai/service-tiers), send the `munito-service-tier` header.

## Reasoning models [#reasoning-models]

The public chat models reason before they answer by default, except `google/gemma-4-12b`. The reasoning uses output tokens, and it comes before the answer.
Set `max_tokens` to 2048 or more. With a small value, the output can stop during the reasoning, and `content` is then `null`.
See [Reasoning](https://docs.munito.ai/reasoning) to lower or turn off the reasoning.

## Errors and headers [#errors-and-headers]

Each API returns errors in its own format: OpenAI's `{"error": {...}}` on the OpenAI endpoints, and Anthropic's `{"type": "error", ...}` on Messages.
The SDKs therefore raise their usual exception types.
Rate limits return `429`, and a model with no free capacity returns `503`. See [Rate limits](https://docs.munito.ai/rate-limits).
