API reference
Base URLs, authentication, request conventions, limits and retry guidance that apply to every Lovely Router endpoint.
Lovely Router serves two kinds of API from one host, with one key and one balance:
- Model APIs in the vendors' own formats: Anthropic Messages, OpenAI Chat Completions and Gemini. Requests and responses follow the vendor's API reference, so the official SDKs work unchanged. Lovely Router adds a few response headers.
- Lovely Router APIs for data tools (
/v1/tools) and the browser agent (/v1/browser): JSON APIs with the conventions described below.
Messages, Chat Completions, Gemini, token counting and the model list.
Search the catalog, run tools and fetch results.
Start and steer browser agent runs, and manage secrets, files and profiles.
Turn a song into a music video, review its scenes and download it.
Status codes, error bodies and retry policy.
Base URLs#
All endpoints are served over HTTPS from https://lovelyrouter.com.
| API | SDK base URL | Endpoints |
|---|---|---|
| Anthropic Messages | https://lovelyrouter.com | POST /v1/messages, POST /v1/messages/count_tokens |
| OpenAI Chat Completions | https://lovelyrouter.com/v1 | POST /v1/chat/completions |
| Gemini | https://lovelyrouter.com | POST /v1beta/models/{model}:generateContent, :streamGenerateContent, :countTokens |
| Model list | — | GET /v1/models, GET /v1beta/models |
| Data tools | https://lovelyrouter.com/v1 | /v1/tools/... |
| Browser agent | https://lovelyrouter.com/v1 | /v1/browser/... |
| Music videos | https://lovelyrouter.com/v1 | /v1/videos/music/... |
| MCP server | — | POST /mcp |
Endpoints not listed here, such as OpenAI's Responses, Embeddings and Images APIs, return 404.
Authentication#
Send your API key as a bearer token. The model endpoints also accept the vendors' own headers, so each SDK works with its defaults.
Authorization: Bearer lr-...| Header | Typical use |
|---|---|
Authorization: Bearer lr-... | OpenAI SDK, data tools, browser agent, MCP |
x-api-key: lr-... | Anthropic SDK |
x-goog-api-key: lr-... | Google Gen AI SDK |
The model list and the tool catalog need no key. Everything else does. See Authentication.
Requests and responses#
- JSON in, JSON out. Send request bodies as JSON with
content-type: application/json. The exceptions are file uploads to the browser agent, which take the raw file ormultipart/form-data, and run screenshots, which returnimage/jpeg. - Streaming. Anthropic and OpenAI requests with
"stream": truereturn server-sent events (text/event-stream). Gemini's:streamGenerateContentstreams a JSON array, or server-sent events with?alt=sse, as Google's API does. See Streaming. - Cross-origin requests are allowed from any origin. That doesn't make it safe to call the API from a browser: anyone can read a key shipped in front-end code.
Lovely Router's own APIs follow these conventions:
| Convention | Example |
|---|---|
| Ids carry a type prefix | run_… for tool runs, brun_… for browser runs |
| Timestamps are ISO 8601 in UTC | "created_at": "2026-10-11T09:30:00.000Z" |
| Money is in US dollars, as numbers | "charge_usd": 0.042, "reserved_usd": 0.3 |
| Lists are wrapped in an object | {"object": "list", "data": [...]} |
Long-running work returns 202 | The body includes a poll path to check on it |
| Waiting is a query parameter | GET /v1/tools/runs/{id}?wait=60 holds the request until the run finishes or the time is up |
Response headers#
Model responses carry these headers in addition to the vendor's:
| Header | Meaning |
|---|---|
x-lovely-request-id | Unique id of the request, also shown in Logs. Include it when you contact support. |
x-lovely-group | The channel group that served the request |
x-lovely-channel | A short, URL-encoded description of that channel group |
x-lovely-queued-ms | Milliseconds the request waited for capacity, when it had to wait |
retry-after | On 429 responses: seconds to wait before retrying |
Versioning#
Model APIs follow the vendor's versioning. Send the headers your SDK sends: anthropic-version and anthropic-beta for Anthropic, and openai-beta for OpenAI. Gemini requests use the /v1beta path, as Google's API does. Lovely Router forwards these headers and no others, so features that depend on a different vendor header aren't available.
Lovely Router APIs are versioned by path and live under /v1. New fields can appear in responses, so write clients that ignore fields they don't recognise.
Rate limits#
These limits apply to your requests:
| Limit | Applies to | When exceeded |
|---|---|---|
| Requests per minute and concurrency you set on a key | Model requests from that key | 429 with retry-after |
| Model capacity | Model requests. Short bursts wait in a queue for a few seconds first. | 429, usually with retry-after |
| 10 runs in progress per account | Data tool and browser runs | 429 |
| 100 requests per minute per key; 100 per minute shared by all callers without a key | POST /v1/tools/suggest | 429 with retry-after |
See Rate limits & failover and API keys.
Retries and idempotency#
Lovely Router retries failed model requests on other channels before it returns an error, so a 5xx you receive has already been retried. It's still worth retrying 429 and 5xx responses yourself with exponential backoff, honouring retry-after. Don't retry other 4xx errors without changing the request. The official OpenAI and Anthropic SDKs retry twice by default; raise max_retries (maxRetries in Node.js) for batch jobs.
The API doesn't take idempotency keys. Plan for these cases:
- A model request that times out on your side may still have completed and been charged. If you retry, you may pay twice. Use generous client timeouts for long generations, or stream.
- Starting a tool or browser run is not idempotent. If
POST /v1/tools/{id}/runorPOST /v1/browser/runstimes out, list your recent runs withGET /v1/tools/runsorGET /v1/browser/runsbefore starting another. - Reading is always safe to repeat. Polling a run, listing runs and fetching results never charge.
Retry code in Python and Node.js is in Retry failed requests.
Errors#
Model endpoints return errors in the vendor's format, so SDKs raise their usual exceptions. Lovely Router's own APIs return:
{"error": {"type": "invalid_request_error", "message": "\"goal\" is required (max 4,000 characters)"}}Every status code, with sample bodies for each format, is in Errors.