# Base URLs and authentication

Source: https://platform.lyrouter.com/ai_gateway/docs/call-gateway/en
Last updated: 2026-10-22

All calls go to the gateway address `https://api.lyrouter.com` and authenticate with the same LYRouter API key. Set the OpenAI SDK's Base URL to `https://api.lyrouter.com/v1` and the Anthropic SDK's to the root address `https://api.lyrouter.com`; put the key in the `Authorization: Bearer <API Key>` or `x-api-key` request header. In the request body, set `model` to a system model ID, `@vmodel/<name>` or `lyrouter/auto`; when it is omitted, the workspace's Default Model is used.

## Addresses

| Protocol | SDK Base URL | Request path |
| --- | --- | --- |
| Chat Completions | https://api.lyrouter.com/v1 | /v1/chat/completions |
| Responses | https://api.lyrouter.com/v1 | /v1/responses |
| Anthropic Messages | https://api.lyrouter.com | /v1/messages |

- **SDKs take only the Base URL**: the OpenAI SDK appends paths such as `/chat/completions`, `/responses` and `/models` after `/v1`, and the Anthropic SDK appends `/v1/messages` to the root address. With cURL or your own HTTP requests, write the full URL, for example `https://api.lyrouter.com/v1/chat/completions`.
- **Do not repeat `/v1`**: when the Anthropic SDK's Base URL is `https://api.lyrouter.com/v1`, the actual request goes to `/v1/v1/messages` and returns 404. An OpenAI SDK Base URL that goes as far as `/v1/chat/completions` also produces a wrong path.
- **Version prefixes**: besides `/v1`, the gateway also accepts the same paths without a version prefix (such as `/chat/completions`) or with another version prefix (such as `/v4/chat/completions`, used by some Zhipu clients), and handles them as the same endpoint. Use `/v1` for all new applications.
- **The console address is not the gateway address**: the console page you open in a browser (`/ai_gateway/...`) cannot be used as a Base URL. For a self-hosted deployment, replace `https://api.lyrouter.com` on this page with your gateway address.

## Authentication

Create an API key on the **API Keys** page of the current workspace; see [Workspaces and API keys](https://platform.lyrouter.com/ai_gateway/docs/api-keys/en). The gateway identifies the workspace by the API key and swaps in a platform or BYOK provider credential when it calls the upstream; your API key is never forwarded upstream. Neither a provider's API key nor a console login session can be used to call the gateway.

| Request header | Format | Applies to |
| --- | --- | --- |
| `Authorization` | `Bearer <API Key>`; `Bearer` is case-sensitive and followed by one space | All endpoints; the OpenAI SDK's `api_key` / `apiKey` and the Anthropic SDK's `auth_token` / `authToken` use this format |
| `x-api-key` | `<API Key>` as is, with no prefix | All endpoints; the Anthropic SDK's `api_key` / `apiKey` uses this format |

- **Only one is read**: when a request carries both headers, the gateway reads only `Authorization`. When `Authorization` is malformed, it returns 401 right away and does not fall back to `x-api-key`.
- **Headers only**: do not put the key in URL query parameters or in the request body.
- **When changes apply**: creating, disabling or editing a key reaches the gateway within a few seconds.

### Limits on the API key itself

You can set the following limits when you create or edit a key. Once one is triggered, the gateway rejects the request before calling the upstream:

| Setting (API key edit page) | Response when triggered | Notes |
| --- | --- | --- |
| "Expiry" under "Basic info" | 403 `api key expired` | Some time after expiry this becomes 401 `invalid api key`; create a new key to replace it |
| "Cost budget (¥)" and "Token budget (million tokens)" under "Budget limits" | 429 `rate limit exceeded on apikey <metric>/<window>` | "Monthly" resets on the 1st of each month and "Total" never resets; see [Budgets, quotas and rate limits](https://platform.lyrouter.com/ai_gateway/docs/quota/en) |
| "Enable IP allowlist" under "Access control" | 403 `your IP address is not allowed` | The gateway checks the egress IP the request arrives from; an empty allowlist or one with invalid entries returns 403 `ip access control misconfigured` |

Keys are also subject to the workspace's guardrail policies (model policies, quotas, client access control); see [Guardrails and semantic auditing](https://platform.lyrouter.com/ai_gateway/docs/guardrails/en). How to handle each error is covered in [401 / 403: authentication and access](https://platform.lyrouter.com/ai_gateway/docs/auth-errors/en) and [429: rate limits and quotas](https://platform.lyrouter.com/ai_gateway/docs/rate-errors/en).

## OpenAI SDK

Chat Completions, Responses, Models, Embeddings and the other OpenAI-compatible endpoints share one client whose Base URL ends at `/v1`:

**Request examples**

cURL:
```bash
curl https://api.lyrouter.com/v1/chat/completions \
  -H "Authorization: Bearer $LYROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "messages": [{"role": "user", "content": "Introduce yourself in one sentence"}]
  }'
```

Python:
```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["LYROUTER_API_KEY"],
    base_url="https://api.lyrouter.com/v1",
)

completion = client.chat.completions.create(
    model="MODEL_ID",
    messages=[{"role": "user", "content": "Introduce yourself in one sentence"}],
)
print(completion.choices[0].message.content)

# Call Responses with the same client
response = client.responses.create(model="MODEL_ID", input="Introduce yourself in one sentence")
print(response.output_text)
```

Node.js:
```js
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.LYROUTER_API_KEY,
  baseURL: "https://api.lyrouter.com/v1",
});

const completion = await client.chat.completions.create({
  model: "MODEL_ID",
  messages: [{ role: "user", content: "Introduce yourself in one sentence" }],
});
console.log(completion.choices[0].message.content);

// Call Responses with the same client
const response = await client.responses.create({ model: "MODEL_ID", input: "Introduce yourself in one sentence" });
console.log(response.output_text);
```

Replace `MODEL_ID` with a model ID copied from the model marketplace; setting the `LYROUTER_API_KEY` environment variable is covered in [Your first model call](https://platform.lyrouter.com/ai_gateway/docs/quickstart/en). Responses requires the model, and the channel that serves it, to support the Responses endpoint; see [Responses](https://platform.lyrouter.com/ai_gateway/docs/responses-api/en). `client.responses` in the Python example requires openai Python SDK 1.66 or later; older versions raise `AttributeError: 'OpenAI' object has no attribute 'responses'`.

## Anthropic SDK

The Anthropic SDK's Base URL is the root address, without `/v1`. `/v1/messages` does not require a model from Anthropic; you can call any chat model through it:

**Request examples**

cURL:
```bash
curl https://api.lyrouter.com/v1/messages \
  -H "x-api-key: $LYROUTER_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Introduce yourself in one sentence"}]
  }'
```

Python:
```python
import os
from anthropic import Anthropic

client = Anthropic(
    api_key=os.environ["LYROUTER_API_KEY"],
    base_url="https://api.lyrouter.com",
)

message = client.messages.create(
    model="MODEL_ID",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Introduce yourself in one sentence"}],
)
print(message.content[0].text)
```

Node.js:
```js
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: process.env.LYROUTER_API_KEY,
  baseURL: "https://api.lyrouter.com",
});

const message = await client.messages.create({
  model: "MODEL_ID",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Introduce yourself in one sentence" }],
});
console.log(message.content[0].text);
```

Details of requests, responses and streaming events are in [Anthropic Messages](https://platform.lyrouter.com/ai_gateway/docs/anthropic-messages/en).

### Switching existing code with environment variables only

Both SDKs read environment variables. When your existing code does not pass the address and key explicitly, setting the variables below is enough to route it through the gateway:

| SDK | Address variable | Key variable |
| --- | --- | --- |
| OpenAI (Python / Node.js) | `OPENAI_BASE_URL=https://api.lyrouter.com/v1` | `OPENAI_API_KEY=<LYRouter API Key>` |
| Anthropic (Python / Node.js) | `ANTHROPIC_BASE_URL=https://api.lyrouter.com` | `ANTHROPIC_API_KEY=<LYRouter API Key>` (sent as `x-api-key`) or `ANTHROPIC_AUTH_TOKEN=<LYRouter API Key>` (sent as `Authorization: Bearer`) |

The model names in your code also have to change to LYRouter model IDs. Configuration for coding tools such as Claude Code and Codex is in [Tools and compatibility](https://platform.lyrouter.com/ai_gateway/docs/tools/en).

## The `model` field

| Value | Meaning | Available on |
| --- | --- | --- |
| A system model ID, such as `deepseek/deepseek-v4-flash` | Calls this model; the gateway picks a provider channel as described in [Channels and routing](https://platform.lyrouter.com/ai_gateway/docs/routing/en) | Every endpoint that takes `model` |
| `@vmodel/<name>` (the old form `@preset/<name>` is equivalent) | Calls an enabled [virtual model](https://platform.lyrouter.com/ai_gateway/docs/presets/en), using its primary model, fallback models and params | Chat Completions, Anthropic Messages, Responses; also [embeddings](https://platform.lyrouter.com/ai_gateway/docs/embeddings/en) and [rerank](https://platform.lyrouter.com/ai_gateway/docs/rerank/en) when every model in its list is an embedding or rerank model |
| `lyrouter/auto` | Picks among the enabled models by task difficulty; see [Auto routing](https://platform.lyrouter.com/ai_gateway/docs/auto/en) | Chat Completions, Anthropic Messages, Responses |
| Omitted, or `""` or `null` | Uses the Default Model set for the workspace in **Smart routing** | Endpoints that take `model` |

- Model IDs are case-sensitive and must match the `id` shown in the model marketplace or returned by [`GET /v1/models`](https://platform.lyrouter.com/ai_gateway/docs/models/en) character for character; the naming rules are in [Model identifiers and discovery](https://platform.lyrouter.com/ai_gateway/docs/model-names/en).
- When `model` is omitted and the workspace has no Default Model, the request returns 400 `you must provide a model parameter` (`error.code` `missing_model`); when `model` is not a string, it returns 400 `invalid type for 'model': expected a string` (`invalid_model`).
- Virtual models and `lyrouter/auto` used on image, video or audio endpoints return 403 `Model is not available in the model plaza`; use a specific model ID on those endpoints.

## All endpoints

Every endpoint uses the same Base URL and the same authentication:

| Method | Path | Purpose | Documentation |
| --- | --- | --- | --- |
| POST | `/v1/chat/completions` | Chat generation (OpenAI Chat Completions format) | [Chat Completions](https://platform.lyrouter.com/ai_gateway/docs/chat-completions/en) |
| POST | `/v1/responses` | Chat generation (OpenAI Responses format) | [Responses](https://platform.lyrouter.com/ai_gateway/docs/responses-api/en) |
| POST | `/v1/messages` | Chat generation (Anthropic Messages format) | [Anthropic Messages](https://platform.lyrouter.com/ai_gateway/docs/anthropic-messages/en) |
| GET | `/v1/models` | List the models this API key can call | [List models](https://platform.lyrouter.com/ai_gateway/docs/models/en) |
| POST | `/v1/embeddings`, `/v1/rerank` | Text embeddings, reranking | [Create embeddings](https://platform.lyrouter.com/ai_gateway/docs/embeddings/en), [Rerank documents](https://platform.lyrouter.com/ai_gateway/docs/rerank/en) |
| POST | `/v1/images/generations`, `/v1/images/edits` | Image generation, editing | [Multimodal capabilities](https://platform.lyrouter.com/ai_gateway/docs/multimodal/en) |
| POST | `/v1/videos`, `/v1/videos/regenerations`, `/v1/videos/context` | Submit video tasks | [Asynchronous tasks](https://platform.lyrouter.com/ai_gateway/docs/async/en) |
| GET, DELETE | `/v1/videos/{id}`, `/v1/videos/{id}/content` | Query a task, download its output, cancel a task | [Asynchronous tasks](https://platform.lyrouter.com/ai_gateway/docs/async/en) |

Every endpoint, grouped by capability, is listed in [API documentation](https://platform.lyrouter.com/ai_gateway/docs/api-overview/en), and the gateway's own request and response headers in [Gateway headers and extensions](https://platform.lyrouter.com/ai_gateway/docs/gateway-headers/en).

## Address and authentication errors

On OpenAI-compatible endpoints the error body is `{"error": {"message": "...", "type": "...", "code": "..."}}`, and `code` appears only on some errors. Errors on `/v1/messages` are converted to the Anthropic format `{"type": "error", "error": {"type": "authentication_error", "message": "..."}}`, with `message` unchanged and no `code`.

| Status | Error message | Cause and fix |
| --- | --- | --- |
| 404 | `{"error_msg":"404 Route Not Found"}` | The path or method does not exist: the Base URL repeats `/v1`, the path has a trailing `/`, the endpoint is misspelled, or an endpoint that only accepts POST was called with GET. Check the full URL against "Addresses" above. This response is not a standard error body and is not converted to the Anthropic format |
| 401 | `missing credentials` | No API key was sent, or `Authorization` is `Bearer ` (with the space) with no key after it. Add `Authorization: Bearer <API Key>` or `x-api-key` |
| 401 | `invalid authorization scheme, expected 'Bearer'` | `Authorization` is not in the `Bearer <API Key>` format, for example it says lowercase `bearer`, has only the key, or is just `Bearer` with no space after it |
| 401 | `invalid api key` | The key was copied incompletely or with whitespace, or it was deleted, disabled or has expired; a newly created key needs a few seconds to sync |
| 401 | `api key verification unavailable` | The platform temporarily cannot verify keys; retry later |
| 400 | `unsupported content-type: application/x-www-form-urlencoded, only application/json is supported` | The `Content-Type` of a JSON request is not `application/json`. This happens when cURL sends with `-d` without `-H "Content-Type: application/json"`. On OpenAI-compatible endpoints this response is a single line of plain text, not JSON, yet its response header is currently still `Content-Type: application/json`; check whether the body is JSON before parsing it |
| 402 | `subscription expired; renew to continue` | The account's subscription has expired; renewing restores access; see [Unavailable models](https://platform.lyrouter.com/ai_gateway/docs/unavailable/en#balance-and-subscription) |
| 403 | `api key expired`, `your IP address is not allowed`, `ip access control misconfigured` | See "Limits on the API key itself" above |
| 403 | `Model is not available in the model plaza` | The workspace has not enabled the model, or a virtual model or `lyrouter/auto` was used on an image, video or audio endpoint; see [Unavailable models](https://platform.lyrouter.com/ai_gateway/docs/unavailable/en) |

Responses do not include a request ID. When you report a problem, record the call time, endpoint, model, API key name and the error message; if you can find the request in **Log analysis**, also include the Request ID at the top of the log detail. 401 requests cannot be attributed to a key and do not appear in the logs. All error codes are listed in [Errors and request identifiers](https://platform.lyrouter.com/ai_gateway/docs/errors/en).

## FAQ

### My OpenAI SDK Base URL is missing `/v1`. Why do calls still work?

**Answer:** The gateway also accepts paths without a version prefix, so `https://api.lyrouter.com/chat/completions` is equivalent to `/v1/chat/completions`. Other tools and SDKs may not build paths the same way, so always use `https://api.lyrouter.com/v1`.

### Can one API key be used by both OpenAI and Anthropic clients?

**Answer:** Yes. A key belongs to a workspace and is independent of the protocol; when both clients call the same model ID, cost, quotas and logs are all recorded under this key. The API Path column in the logs tells you which endpoint a request came through.

### Can I tell from the response which provider a request was routed to?

**Answer:** The response carries no provider information, and its `model` field is the value returned by the upstream. Open the request in **Log analysis**: Model (actual) and Provider show the model and channel that finally served it; see [Inspecting request routing](https://platform.lyrouter.com/ai_gateway/docs/route-log/en).
