---
title: How the gateway works
description: Lovely Router passes each request to a model in the API format you sent it. This page covers the endpoints, model ids, auth headers, and the few things the gateway changes.
---

Lovely Router speaks the Anthropic, OpenAI and Gemini APIs on one host. It does not translate between them: a request in Anthropic format goes to a channel that accepts Anthropic format, and your request body reaches the channel as you wrote it, apart from [two small changes](#what-the-gateway-changes). Called in its own vendor's API, a model gets your request exactly as the vendor documents it. Parameters such as `thinking`, `cache_control`, `tools` or `generationConfig` reach the model unchanged, so the vendor's own documentation applies.

## Endpoints and base URLs

Point your SDK at the base URL for its API. The SDK adds the path.

| API | Endpoints | SDK base URL | Guide |
| --- | --- | --- | --- |
| Anthropic Messages | `POST /v1/messages`, `POST /v1/messages/count_tokens` | `https://lovelyrouter.com` | [Anthropic Messages](/docs/models/anthropic) |
| OpenAI Chat Completions | `POST /v1/chat/completions` | `https://lovelyrouter.com/v1` | [OpenAI Chat Completions](/docs/models/openai) |
| OpenAI Responses (GPT models) | `POST /v1/responses` | `https://lovelyrouter.com/v1` | [Responses API](/docs/models/openai#responses-api) |
| Gemini | `POST /v1beta/models/{model}:generateContent`, `:streamGenerateContent`, `:countTokens` | `https://lovelyrouter.com` | [Gemini](/docs/models/gemini) |
| OpenAI Images (image models) | `POST /v1/images/generations`, `POST /v1/images/edits` | `https://lovelyrouter.com/v1` | [Images](/docs/models/images) |
| Videos (character swap) | `POST /v1/videos` | `https://lovelyrouter.com/v1` | [Video](/docs/models/videos) |
| Live video | `POST /v1/videos/live` | `https://lovelyrouter.com/v1` | [Live video](/docs/models/live-video) |
| Music videos | `POST /v1/videos/music` | `https://lovelyrouter.com/v1` | [Music videos](/docs/models/music-videos) |
| Model list | `GET /v1/models`, `GET /v1beta/models` | | [Models & pricing](/docs/models/pricing) |

Other model endpoints return `404`. See [what is not available](#what-is-not-available). The [data tools](/docs/tools) and [browser agent](/docs/browser-agent) APIs share the same host and keys.

## Which API each model speaks

Every model has a native API: the format its vendor designed it for. Use it when you can.

| Model family | Native API | Also accepted today |
| --- | --- | --- |
| Claude (`claude-*`) | Anthropic Messages | OpenAI Chat Completions, Gemini |
| GPT (`gpt-*`) | OpenAI Chat Completions, OpenAI Responses | Anthropic Messages, Gemini |
| Gemini (`gemini-*`) | Gemini | OpenAI Chat Completions, Anthropic Messages |
| GPT Image (`gpt-image-*`) | OpenAI Images | none |
| [Hosted models](/docs/models/hosted) (`dongfangshuo-*`) | OpenAI Chat Completions | Anthropic Messages |
| [Hosted image models](/docs/models/hosted#images) (`z-image-*`) | OpenAI Images | none |

When you call a model in another format, the channel converts the request for the model, so some vendor features may not carry over. Vendor-specific parameters are defined for the vendor's own API. Anthropic `cache_control` and `thinking`, OpenAI `reasoning_effort` and Gemini `thinkingConfig` are only certain to work in the model's native format; in another format they may be ignored or rejected.

The formats a model accepts depend on the channels that serve it, so they can change. The [marketplace](/models) shows them per model. If no channel accepts your format, the request fails with `404` and a message like `Model 'gpt-6.1-sol' is not served in gemini format in any group.`

## Model ids

Use the ids from [`GET /v1/models`](/docs/models/pricing), such as `claude-sonnet-5.5`, `gpt-6.1-sol` or `gemini-3.1-pro`. The gateway also accepts the spellings other tools use and resolves them to the same model:

| You send | Resolves to |
| --- | --- |
| `claude-sonnet-5-5` | `claude-sonnet-5.5` |
| `anthropic/claude-sonnet-5.5` | `claude-sonnet-5.5` |
| `claude-haiku-4-5-20251001` | `claude-haiku-4.5` |
| `gemini-3.1-pro-preview` | `gemini-3.1-pro` |
| `models/gemini-3-flash` | `gemini-3-flash` |

The rules: case is ignored, a leading `vendor/` or `models/` prefix is dropped, `.` and `-` are interchangeable, and a trailing date (`-20251001`), `-preview` or `-latest` is dropped. Logs, key allow-lists and billing always use the canonical id.

An id that matches no model returns `404` with `Model '<id>' is not available. See GET /v1/models.`

## What the gateway changes

The request body is forwarded as you sent it, with two exceptions:

1. **The model id.** It is replaced with the id the serving channel expects. The `model` field in the response may therefore use the vendor's spelling, for example `claude-sonnet-5-5`.
2. **Usage on OpenAI streams.** Streaming Chat Completions requests get `stream_options.include_usage: true`, so the gateway can bill the call. Your stream ends with one extra chunk that has an empty `choices` array and a `usage` object. Guard for `choices` being empty when you read chunks.

Request headers are not forwarded, except `anthropic-version`, `anthropic-beta` and `openai-beta`. When `anthropic-version` is missing, `2023-06-01` is sent. On Gemini endpoints, query parameters such as `alt=sse` are forwarded; `key` is removed.

Responses come back byte for byte. The gateway keeps the `content-type` and `cache-control` headers and adds its own (see [response headers](#response-headers)). Vendor request ids and rate-limit headers are not passed through.

When a model rejects a request as invalid (`400`, `404`, `413`, `422`), you get the same status and the reason, in your API's error format. Other failures are retried on another channel first. See [Rate limits & failover](/docs/models/rate-limits) and [Errors](/docs/api/errors).

## Authentication

Every endpoint accepts your key in any of these places, so each SDK works with its default auth:

| Where | Used by |
| --- | --- |
| `Authorization: Bearer lr-...` | OpenAI SDK, Claude Code with `ANTHROPIC_AUTH_TOKEN`, most HTTP clients |
| `x-api-key: lr-...` | Anthropic SDK |
| `x-goog-api-key: lr-...` | Google Gen AI SDK, Gemini CLI |
| `?key=lr-...` query parameter | Gemini REST examples |

`GET /v1/models` and `GET /v1beta/models` need no key. See [Authentication](/docs/authentication) for key handling.

## Response headers

| Header | Value |
| --- | --- |
| `x-lovely-request-id` | Id of this call, for example `req_6f1c...`. Matches the entry in [Logs](/app/logs). Include it when you contact support. |
| `x-lovely-group` | The [channel group](/docs/models/channel-groups) that served the call, for example `claude-value`. |
| `x-lovely-channel` | The group's channel label, URL-encoded, for example `Pooled%20capacity`. |
| `x-lovely-queued-ms` | Only when the call waited for capacity: milliseconds spent waiting. |

Browsers can read the first three: they are listed in `access-control-expose-headers`.

## Lifecycle of a request

1. **Authenticate.** The key must be active and not expired, or you get `401`.
2. **Resolve the model.** The id is resolved as described above and checked against the key's model allow-list (`403` if not allowed).
3. **Check the balance.** A balance at or below zero, or a key past its spend limit, returns `402`.
4. **Apply key limits.** A key's requests-per-minute and concurrency limits are enforced (`429`). See [Rate limits & failover](/docs/models/rate-limits).
5. **Pick a channel.** A conversation already in progress goes back to the channel that holds its prompt cache. New conversations go to the best available channel in the [channel group](/docs/models/channel-groups). See [Prompt caching](/docs/models/caching).
6. **Call the model.** If a channel fails before producing output, the request moves to another channel, up to three attempts. Streams are held until the first token so this stays invisible. See [Streaming](/docs/models/streaming).
7. **Meter and log.** Token counts from the response set the charge, which is deducted from your balance within seconds. See [Models & pricing](/docs/models/pricing).

## What is not available

Only the endpoints above exist. These return `404`:

- Stored OpenAI responses (`/v1/responses/{id}`), legacy Completions, embeddings, image variations, audio, files and batches.
- Anthropic Message Batches, Files and Models-by-id endpoints.
- Gemini `cachedContents` (explicit context caching), file uploads, `embedContent` and the Live API.

The OpenAI Responses API is served for GPT models only. [Use with your tools](/docs/integrations) has settings for common clients.
