How the gateway works
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. 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 |
| OpenAI Chat Completions | POST /v1/chat/completions | https://lovelyrouter.com/v1 | OpenAI Chat Completions |
| OpenAI Responses (GPT models) | POST /v1/responses | https://lovelyrouter.com/v1 | Responses API |
| Gemini | POST /v1beta/models/{model}:generateContent, :streamGenerateContent, :countTokens | https://lovelyrouter.com | Gemini |
| OpenAI Images (image models) | POST /v1/images/generations, POST /v1/images/edits | https://lovelyrouter.com/v1 | Images |
| Videos (character swap) | POST /v1/videos | https://lovelyrouter.com/v1 | Video |
| Live video | POST /v1/videos/live | https://lovelyrouter.com/v1 | Live video |
| Music videos | POST /v1/videos/music | https://lovelyrouter.com/v1 | Music videos |
| Model list | GET /v1/models, GET /v1beta/models | Models & pricing |
Other model endpoints return 404. See what is not available. The data tools and 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 (dongfangshuo-*) | OpenAI Chat Completions | Anthropic Messages |
Hosted image models (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 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, 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:
- The model id. It is replaced with the id the serving channel expects. The
modelfield in the response may therefore use the vendor's spelling, for exampleclaude-sonnet-5-5. - 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 emptychoicesarray and ausageobject. Guard forchoicesbeing 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). 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 and 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 for key handling.
Response headers#
| Header | Value |
|---|---|
x-lovely-request-id | Id of this call, for example req_6f1c.... Matches the entry in Logs. Include it when you contact support. |
x-lovely-group | The channel group 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#
- Authenticate. The key must be active and not expired, or you get
401. - Resolve the model. The id is resolved as described above and checked against the key's model allow-list (
403if not allowed). - Check the balance. A balance at or below zero, or a key past its spend limit, returns
402. - Apply key limits. A key's requests-per-minute and concurrency limits are enforced (
429). See Rate limits & failover. - 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. See Prompt caching.
- 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.
- Meter and log. Token counts from the response set the charge, which is deducted from your balance within seconds. See 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,embedContentand the Live API.
The OpenAI Responses API is served for GPT models only. Use with your tools has settings for common clients.