# What is a base URL? For the OpenAI, Anthropic, Gemini SDKs

> What a base URL is, the official one for the OpenAI, Anthropic and Gemini SDKs, how to set it in code or Claude Code, and how to fix 404 and 401 errors.

Updated: 2026-11-01

A base URL is the fixed start of every address an API answers on, such as `https://api.openai.com/v1`. Your SDK adds the path for each request, like `/chat/completions`. Change the base URL, and the same code sends its requests to another compatible service, as long as the key and the model id match it.

## What is a base URL?

Every request to an AI API goes to a full address made of two parts. The base URL is the part that stays the same for all requests: the scheme, the host and often a version, as in `https://api.openai.com/v1`. The path is the part that names the operation, as in `/chat/completions` for a chat reply or `/models` for the list of models.

```text
base URL   https://api.openai.com/v1
+ path     /chat/completions
= request  https://api.openai.com/v1/chat/completions
```

The official SDKs keep the paths inside the library. You give them the base URL once, and they build each address from it. The key is not part of the address: it goes in a request header. The model id goes in the request body, or in the path for Gemini.

## Base URL vs endpoint

An endpoint is one full address with its HTTP method, such as `POST /v1/messages` for a Claude reply. The base URL is the shared start of all the endpoints. When a tool asks for a "base URL", an "API base" or a "custom endpoint", it usually means this shared start, not the address of a single request.

## Why change the base URL?

- **A gateway or proxy.** The same code goes through a service that controls keys, spending and logs.
- **A compatible service.** Another provider that speaks the same format as the official API.
- **Tests.** A local or staging server that answers like the real one.

The two official Python SDKs we checked pick the base URL in the same order: a value in your code wins over the environment variable, and the variable wins over the built-in default. The variable is `OPENAI_BASE_URL` in OpenAI's library and `ANTHROPIC_BASE_URL` in Anthropic's.

## The official base URLs

Checked on 2026-11-01 in each provider's docs and SDK source:

| Provider | Official base URL | The library or request adds | Key header |
| --- | --- | --- | --- |
| OpenAI | `https://api.openai.com/v1` | `/chat/completions`, `/responses` | `Authorization: Bearer` |
| Anthropic | `https://api.anthropic.com` | `/v1/messages` | `Authorization: Bearer` or `x-api-key`, plus `anthropic-version` |
| Google Gemini | `https://generativelanguage.googleapis.com/v1beta` | `/models/{model}:generateContent` | `x-goog-api-key` |

The version sits in a different place for each provider. OpenAI's base URL ends in `/v1`. Anthropic's has no version, because the library adds `/v1/messages` itself. Gemini's ends in `/v1beta`. Many setup errors come from this one difference.

## The base URL in the OpenAI library

The OpenAI library takes the base URL as `base_url` in code or from `OPENAI_BASE_URL`, and the key from `OPENAI_API_KEY`. Keep `/v1` at the end: the library adds only the operation, such as `/chat/completions` or `/responses`.

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.5abeer.ai/v1",
    api_key=os.environ["KHABEER_API_KEY"],
)
```

5abeer's OpenAI format is OpenAI-compatible: change the base URL and keep your code. It serves Chat Completions and Responses, and you can call Claude models in this format too. Each model's page in the [models list](https://5abeer.ai/en/models) shows the formats it supports. The same setup with environment variables, for macOS, Linux and Windows, is in [The OpenAI library](https://5abeer.ai/en/docs/start/base-urls.md#openai).

## The base URL in the Anthropic library

The Anthropic library takes `base_url` in code or `ANTHROPIC_BASE_URL`, and the key from `ANTHROPIC_API_KEY`. Leave out `/v1`: the library adds `/v1/messages` itself, and it sends the `anthropic-version` header for you.

```python
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://api.5abeer.ai",
    api_key=os.environ["KHABEER_API_KEY"],
)
```

5abeer's Anthropic format is compatible with the Anthropic Messages API, so code built on the Anthropic library keeps working. The steps are in [The Anthropic library](https://5abeer.ai/en/docs/start/base-urls.md#anthropic), and the request fields in [Anthropic Messages](https://5abeer.ai/en/docs/api/messages.md).

## The base URL in Claude Code

Claude Code reads `ANTHROPIC_BASE_URL` too, so the rule is the same: no `/v1` at the end. Anthropic's gateway guide, checked on 2026-11-01, adds two points:

- **The key goes in its own variable.** `ANTHROPIC_AUTH_TOKEN` sends it as `Authorization: Bearer`, and `ANTHROPIC_API_KEY` sends it as `x-api-key`. A key in the wrong variable reaches the gateway in a header it doesn't read, and the request fails with `401`.
- **The base URL alone doesn't switch your account.** Setting only `ANTHROPIC_BASE_URL` doesn't replace a saved claude.ai login; without a gateway key, that login stays the active credential.

Our [Claude Code guide](https://5abeer.ai/en/docs/apps/claude-code.md#configure) puts your 5abeer key in `ANTHROPIC_AUTH_TOKEN`. To check the setup, run `/status` inside Claude Code: it shows an `Anthropic base URL` line only when a gateway address is set. Anthropic also warns against putting the key in a project's `.claude/settings.json`, because that file is committed and shared. Use `~/.claude/settings.json` instead.

With a 5abeer subscription that includes Claude Code, the 5abeer AI app sets it up for you with no API key and no files to edit, as in [Claude Code](https://5abeer.ai/en/docs/apps/claude-code.md#easy). Codex CLI takes its base URL in `~/.codex/config.toml`; the steps are in [Codex CLI with an API key](https://5abeer.ai/en/guides/codex-cli-api-key).

## The base URL for Gemini

Gemini's own format puts the model in the path. The base URL is `https://generativelanguage.googleapis.com/v1beta`, a request goes to `/models/{model}:generateContent`, and the key goes in the `x-goog-api-key` header. Google also runs an OpenAI-compatible address, `https://generativelanguage.googleapis.com/v1beta/openai/`, for the OpenAI libraries, and says this support "is still in beta while we extend feature support".

On 5abeer, the Gemini format sits under `/v1beta` and needs a key for Gemini models: Claude and GPT keys don't work there. Gemini CLI reads its base URL from `GOOGLE_GEMINI_BASE_URL`. The full setup is in [Gemini CLI](https://5abeer.ai/en/docs/apps/gemini-cli.md#configure), and the request shapes in [Gemini generateContent](https://5abeer.ai/en/docs/api/gemini.md).

## Common base URL errors

The error usually points to the part of the request that is wrong:

| What you see | Likely cause | Fix |
| --- | --- | --- |
| `404` Not Found | `/v1` is doubled or missing, so the path doesn't exist | OpenAI library: keep `/v1`. Anthropic library and Claude Code: remove it |
| `401` with `API_KEY_REQUIRED` or `INVALID_API_KEY` | The key is missing, mistyped, or in a header the service doesn't read | Copy the key again and check which variable or header carries it |
| `403` with `MODEL_PLATFORM_NOT_ALLOWED` | The key belongs to one provider and the model to another | Use a key for that model's provider, as in [One key per provider](https://5abeer.ai/en/docs/start/keys.md#per-provider) |
| `ENOTFOUND` or a refused connection | The host is mistyped or unreachable | Copy the base URL again from the table below |
| An HTML page instead of JSON, or an error saying the reply is empty or can't be read | The base URL points at a website, not the API | Use the API address, not the site address |

`400`, `401` and `403` errors don't clear when you retry, so fix the request first. Each code and its fix is in [Errors and fixes](https://5abeer.ai/en/docs/help/errors.md#codes), for example [`INVALID_API_KEY`](https://5abeer.ai/en/docs/help/errors.md#INVALID_API_KEY).

## Test the base URL with one request

Before you change a large project, send one request to the full address. If a reply comes back, the base URL and the key are right. In the OpenAI format:

```bash
curl --request POST "https://api.5abeer.ai/v1/chat/completions" \
  --header "Authorization: Bearer $KHABEER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"model":"claude-sonnet-5.5","messages":[{"role":"user","content":"Write a product idea in one sentence."}]}'
```

```python
import os
import requests

response = requests.post(
    "https://api.5abeer.ai/v1/chat/completions",
    headers={
        "Authorization": f"Bearer {os.environ['KHABEER_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
    "model": "claude-sonnet-5.5",
    "messages": [
        {
            "role": "user",
            "content": "Write a product idea in one sentence."
        }
    ]
},
    stream=False,
    timeout=60,
)

response.raise_for_status()
print(response.json())
```

And in the Anthropic format:

```bash
curl --request POST "https://api.5abeer.ai/v1/messages" \
  --header "x-api-key: $KHABEER_API_KEY" \
  --header "Content-Type: application/json" \
  --header "anthropic-version: 2023-06-01" \
  --data '{"model":"claude-sonnet-5.5","max_tokens":512,"messages":[{"role":"user","content":"Write a product idea in one sentence."}]}'
```

```python
import os
import requests

response = requests.post(
    "https://api.5abeer.ai/v1/messages",
    headers={
        "x-api-key": os.environ['KHABEER_API_KEY'],
        "Content-Type": "application/json",
        "anthropic-version": "2023-06-01",
    },
    json={
    "model": "claude-sonnet-5.5",
    "max_tokens": 512,
    "messages": [
        {
            "role": "user",
            "content": "Write a product idea in one sentence."
        }
    ]
},
    stream=False,
    timeout=60,
)

response.raise_for_status()
print(response.json())
```

These examples read the key from `KHABEER_API_KEY` and write out the full address, so you can see the base URL and the path joined.

## 5abeer's base URLs

5abeer answers in three formats. Use the base URL that matches your library, and send the key in that format's header, as in [Where the key goes in a request](https://5abeer.ai/en/docs/start/keys.md#headers):

| Format | Base URL | Key header |
| --- | --- | --- |
| OpenAI | `https://api.5abeer.ai/v1` | `Authorization: Bearer <KEY>` |
| Anthropic | `https://api.5abeer.ai` | `x-api-key: <KEY>` |
| Gemini | `https://api.5abeer.ai/v1beta` | `x-goog-api-key: <KEY>` |

A 5abeer API key pays per token from your balance, and every model priced per token costs less than its official price. Compare the models on the [API page](https://5abeer.ai/en/api), or by provider on [Claude API](https://5abeer.ai/en/api/claude), [OpenAI API](https://5abeer.ai/en/api/openai) and [Gemini API](https://5abeer.ai/en/api/gemini). Each key can have a spend limit, an expiry date and an IP allow-list, as in [Control every key](https://5abeer.ai/en/docs/start/keys.md#controls).

Plans are for the supported apps; to use the models from your own code, create an API key. The apps are on [5abeer apps](https://5abeer.ai/en/apps) and the plans on the [pricing page](https://5abeer.ai/en/pricing). New to keys? Start with [How to get an API key](https://5abeer.ai/en/guides/ai-api-key-guide), and read [What is a token](https://5abeer.ai/en/guides/what-is-a-token) to see how each request is billed.

## FAQ

### Is a base URL the same as an endpoint?

No. The base URL is the shared start, such as `https://api.anthropic.com`. An endpoint is one full operation, such as `POST /v1/messages`. The SDK joins the two for every request.

### Do I add /v1 at the end of the base URL?

It depends on the library. The OpenAI library expects `/v1` in the base URL. The Anthropic library and Claude Code expect no version, because they add `/v1/messages` themselves. Gemini's own address ends in `/v1beta`.

### Where do I set the base URL?

In code, as the `base_url` argument, or in an environment variable: `OPENAI_BASE_URL` for the OpenAI library, and `ANTHROPIC_BASE_URL` for the Anthropic library and Claude Code. In the Python libraries, a value in code wins over the variable.

### Do I need new code to switch the base URL?

Usually not, if the new service speaks the same format. You change the base URL, the key and, if needed, the model id. Check any feature your code relies on, since a service may not support every option of the format.

### Where does the API key go?

In a request header, not in the base URL. On 5abeer that is `Authorization: Bearer` for the OpenAI format, `x-api-key` with `anthropic-version` for the Anthropic format, and `x-goog-api-key` for Gemini. Keep the key in an environment variable, not in your code or a shared file.

### Why does Claude Code still use my claude.ai login?

Setting only `ANTHROPIC_BASE_URL` doesn't replace a saved login. Put your key in `ANTHROPIC_AUTH_TOKEN` as in our [Claude Code guide](https://5abeer.ai/en/docs/apps/claude-code.md#configure), then check the `Anthropic base URL` line in `/status`.

## Sources

Checked on 2026-11-01:

- OpenAI: [API overview](https://developers.openai.com/api/reference/overview)
- OpenAI: [openai-python library](https://github.com/openai/openai-python)
- Anthropic: [API overview](https://platform.claude.com/docs/en/api/overview)
- Anthropic: [Python SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/python) and the [anthropic-sdk-python library](https://github.com/anthropics/anthropic-sdk-python)
- Claude Code: [Connect Claude Code to an LLM gateway](https://code.claude.com/docs/en/llm-gateway-connect)
- Claude Code: [Other LLM gateways](https://code.claude.com/docs/en/llm-gateway)
- Google AI for Developers: [Generating content](https://ai.google.dev/api/generate-content)
- Google AI for Developers: [Getting started](https://ai.google.dev/gemini-api/docs/quickstart)
- Google AI for Developers: [OpenAI compatibility](https://ai.google.dev/gemini-api/docs/openai)

> 5abeer is an independent service, not affiliated with OpenAI, Anthropic or Google.

## Get started

Copy the base URL for your library from the table above, create a key, and send your first request.
