# Choosing an API

llm.buzz serves each kind of model on the API made for it. A chat model answers Chat Completions, Responses and Messages alike; embeddings, image, audio and decision models have their own routes.

## The APIs

Routes are relative to `https://api.llm.buzz/api/v1`, except the decisions route that names its own base.

| API | Route | Models | Clients | Streams | Replays a keyed retry | Error format |
|---|---|---|---|---|---|---|
| [Chat Completions](chat-completions.md) | `POST /chat/completions` | Text models | OpenAI and OpenRouter SDKs, Cline, OpenCode, Aider | Server-sent events | Yes | OpenRouter's envelope |
| [Responses](responses.md) | `POST /responses`, and `GET /responses` as a WebSocket | Text models | OpenAI SDK, Codex | Server-sent events, or the WebSocket | Yes, over HTTP | OpenRouter's envelope; OpenAI's error frames on the WebSocket |
| [Messages](messages.md) | `POST /messages`, `POST /messages/count_tokens` | Text models | Anthropic SDK, Claude Code | Server-sent events | No | Anthropic's error body |
| [Embeddings](embeddings.md) | `POST /embeddings` | Embeddings models | OpenAI and OpenRouter SDKs | Never | No | OpenRouter's envelope |
| [Images](images.md) | `POST /images`, `POST /images/generations` | Image models | OpenRouter SDK on `/images`, OpenAI SDK on `/images/generations` | Never | No | OpenRouter's envelope |
| [Speech to text](audio.md#speech-to-text) | `POST /audio/transcriptions` | Speech-to-text models | OpenAI and OpenRouter SDKs | Never | No | OpenRouter's envelope |
| [Text to speech](audio.md#text-to-speech) | `POST /audio/speech` | Text-to-speech models | OpenAI and OpenRouter SDKs | Never | No | OpenRouter's envelope |
| [Decisions](decisions.md) | `POST /systemone`, `POST https://api.llm.buzz/api/alpha/decisions` | None today | OpenRouter's SDKs | Never | No | OpenRouter's envelope |

Only Chat Completions and Responses replay a request sent again with the same `Idempotency-Key`, and Responses does so over HTTP only: a key on the WebSocket does not apply. On every other API a retry runs as a request of its own: [Retries and idempotency](retries-and-idempotency.md). Every API takes your key as a bearer token, and Messages also takes it in `x-api-key`: [Authentication](authentication.md#send-the-key).

The SDKs take the base URL in their own setting. The OpenAI SDK takes `base_url="https://api.llm.buzz/api/v1"` (`baseURL` in TypeScript), the OpenRouter SDKs take `server_url="https://api.llm.buzz/api/v1"` (`serverURL` in TypeScript), and the Anthropic SDK takes `base_url="https://api.llm.buzz/api"` (`baseURL` in TypeScript), without `/v1`: [Base URL and SDKs](api-reference.md#base-url-and-sdks). The OpenRouter SDKs reach decisions through a server URL of their own: [Decisions](decisions.md#routes).

## Which text API

Chat Completions, Responses and Messages reach the same models. llm.buzz turns each into one request, so the providers a model has, how a request is routed, what it costs and the limits it runs under do not depend on the API you call. A text model answers all three, whoever made it: a Claude model answers Chat Completions, and a model that is not Claude answers Messages. A chat model that returns images is the exception ([below](#find-a-model-for-an-api)).

Pick the API your client speaks.

- **Chat Completions** for most SDKs and coding agents: the OpenAI and OpenRouter SDKs, Cline, OpenCode and Aider.
- **Responses** for the OpenAI SDK's newer API and for Codex, and when you want llm.buzz to keep the conversation, so a follow-up sends only its own input.
- **Messages** for the Anthropic SDK and Claude Code.

[Cheapest models for coding agents](/docs/guides/cheapest-models-for-coding-agents) sets up Claude Code, Codex, Cline, OpenCode and Aider. What differs between the three:

| | Chat Completions | Responses | Messages |
|---|---|---|---|
| Conversation | You send the whole history each time. | You send your next input and `previous_response_id`; llm.buzz keeps a turn for up to 24 hours, unless you send `store: false`. | You send the whole history each time. |
| System instruction | A `system` or `developer` message. | `instructions`, for this request only. | `system`. |
| Output limit | `max_tokens`, `max_completion_tokens` or `max_output_tokens`, one per request. | `max_output_tokens`. | `max_tokens`, required. |
| Structured output | `response_format`, with `json_schema` or `json_object`. | `text.format`, with `json_schema`; `json_object` is a 400. | Anthropic's `output_config.format`. An `output_config` that holds more than `effort` is sent as you wrote it when every provider that may serve the request takes Anthropic's API, and otherwise dropped and named; its `effort` still applies. `response_format` is dropped and named. |
| `Idempotency-Key` | Replays a retry. | Replays a retry sent over HTTP. | Not used. |
| The `provider` object in the request | Read. | Read. | Read. |
| `provider` in the answer | The name of the provider that answered, on the body and on every stream chunk. | Not in the answer. | Not in the answer. |
| Readable reasoning | `message.reasoning` and `delta.reasoning`. | `summary_text` of a reasoning item. | `thinking` blocks. |
| Token probabilities | `logprobs` and `top_logprobs`. | `include: ["message.output_text.logprobs"]` with `top_logprobs`. | Not offered. |
| Tool search declaration | `{"type": "openrouter:tool_search"}`. | `{"type": "tool_search"}`. | `tool_search_tool_bm25` or `tool_search_tool_regex`. |

[Tools and structured output](tools-and-structured-output.md), [Streaming](streaming.md), [Reasoning](reasoning.md) and [Images in requests](images-in-requests.md) explain what the three share, with each API's spelling.

## Find a model for an API

`GET https://api.llm.buzz/api/v1/models` lists the models your key can call, and the public models without a key. Its `output_modalities` parameter picks the kind: it defaults to `text`, `all` lists every kind, and a comma list such as `text,embeddings` lists models that produce any of them.

```bash
curl -s "https://api.llm.buzz/api/v1/models?output_modalities=embeddings"
```

| `output_modalities` | Lists | Call it on |
|---|---|---|
| `text` | Text models. | Chat Completions, Responses, Messages |
| `embeddings` | Embeddings models. | Embeddings |
| `image` | Image generation models, and chat models that return images. | Images; Chat Completions for a chat model |
| `transcription` | Speech-to-text models. | Speech to text |
| `speech` | Text-to-speech models. | Text to speech |
| `decisions` | Models that answer decisions: none today. | Decisions |

A model sent to an API that does not serve it answers 400 on `model`. The text APIs name the route an embeddings, image or audio model takes. A chat model that returns images serves Chat Completions only: Responses and Messages refuse it.

## Not served

- `POST /api/v1/completions`, OpenAI's older text-completions route, answers 404. Send the prompt as one user message to Chat Completions.
- Rerank and video generation answer 404 too.

[Coming from OpenRouter](from-openrouter.md) lists every route and feature of OpenRouter's that llm.buzz does not offer.
