# Endpoints & API Paths

This page consolidates how QCode.cc exposes three API protocols, four access domains, and how to set `BASE_URL` correctly. **A single API Key works across all three protocols** — the protocol is chosen by the request path, and our backend routes automatically.

## 1. Three API Protocols

QCode.cc is compatible with the **Anthropic Messages**, **OpenAI**, and **Google Gemini** protocols:

| Protocol | Typical Clients | Path |
|----------|-----------------|------|
| Anthropic Messages | Claude Code / Claude Agent SDK / Cline / Aider | `/api/v1/messages` or equivalently `/claude/v1/messages` |
| OpenAI Chat Completions | Official OpenAI SDK / LangChain / DeepSeek-TUI / generic clients | `/openai/v1/chat/completions` |
| OpenAI Responses | Codex CLI (required for Codex) | `/openai/v1/responses` |
| Google Gemini API | Gemini CLI / OpenCode (`google` provider) / Google `@google/genai` SDK | `/gemini/v1beta/models/{model}:generateContent` |

Request bodies follow the corresponding official schema (Anthropic `POST /v1/messages`, OpenAI `POST /v1/chat/completions`, OpenAI `POST /v1/responses`, Google `POST /v1beta/models/{model}:generateContent`).

> **Note**: `/api`, `/claude`, and `/openai/v1` are **path prefixes**, not standalone endpoints. SDKs automatically append `/v1/messages`, `/chat/completions`, or `/responses`. Directly running `curl https://api.qcode.cc/api` will return 404 — that's **expected**.

## 2. Which Models Work on Which Protocol

**The protocol is determined by the request path, but not every model family works on every
protocol.** The table below is the single source of truth; other pages defer to it.

| Model family | Anthropic<br>`/api/v1/messages` | OpenAI Chat<br>`/openai/v1/chat/completions` | OpenAI Responses<br>`/openai/v1/responses` | Gemini<br>`/gemini/v1beta/…` |
|---|:--:|:--:|:--:|:--:|
| Claude (`claude-opus-*` / `-sonnet-*` / `-haiku-*` / `-fable-*`) | ✅ | ❌ | ❌ | — |
| GPT (`gpt-5.x`) | ❌ | ✅ | ✅ used by Codex | — |
| GLM / Kimi / DeepSeek / Qwen | ✅ | ✅ | ❌ | — |
| Gemini | ❌ | ❌ | — | ✅ |

🔴 **Claude models only work on the Anthropic protocol.** Putting `claude-…` into
`/openai/v1/chat/completions` returns:

```json
{"error":{"code":"model_not_available_on_endpoint",
          "message":"Model 'claude-sonnet-5' is not available on this endpoint.",
          "type":"invalid_request_error"}}
```

**This check runs before authentication** — you get this error even with an invalid key. So
`model_not_available_on_endpoint` means **you picked the wrong protocol, not that your key is
bad**; a bad key returns `Invalid API key` instead. Don't confuse the two.

**The restriction is specific to Claude**, not a blanket "no cross-protocol" rule:

- The four Chinese families (GLM / Kimi / DeepSeek / Qwen) work on **both** the Anthropic leg
  and the OpenAI Chat leg
- GPT models use the two OpenAI legs; they do not work on the Anthropic leg either

**What this means when choosing a tool**: clients that only speak the OpenAI protocol and offer
no custom Anthropic endpoint (for example DeepSeek-TUI and WorkBuddy) **cannot use Claude models**
through QCode, though GPT and the Chinese models work fine. For Claude, pick a client that speaks
the Anthropic protocol (Claude Code, Cline, Zed, or Cursor's Anthropic path).

## 3. Four Access Domains

All four domains serve identical business capabilities; they differ only in **network routing**:

| Domain | Target Users | Scheme | Notes |
|--------|--------------|--------|-------|
| `api.qcode.cc` | Global (Route 53 latency-based) | HTTPS | Primary for outside China, picks nearest node |
| `us.qcode.cc` | North America (Backup) | HTTPS | Los Angeles, launched 2026-04-22 |
| `eu.qcode.cc` | Europe (Backup) | HTTPS | Frankfurt |
| `asia.qcode.cc` | Asia (Backup) | HTTPS | Hong Kong |

A single API Key works on all four domains — feel free to switch.

> **🇨🇳 Note for CN users**: We recommend `asia.qcode.cc` (Hong Kong, lowest latency); switch to `api.qcode.cc` (global Route 53) if unstable. All domains report to [probe.qcode.cc](https://probe.qcode.cc) — enter your API Key on that page to inspect request details, context length, usage, and more.

## 4. BASE_URL Cheatsheet

Fill in the following based on your tool:

| Tool | Env Var / Config Key | Value | SDK Will Send To |
|------|---------------------|-------|------------------|
| Claude Code | `ANTHROPIC_BASE_URL` | `https://api.qcode.cc/api` | `/api/v1/messages` |
| Claude Agent SDK | `base_url=` constructor arg | `https://api.qcode.cc/api` | `/api/v1/messages` |
| Cline / Aider | Anthropic mode base URL | `https://api.qcode.cc/api` | `/api/v1/messages` |
| OpenAI Python/JS SDK | `base_url=` constructor arg | `https://api.qcode.cc/openai/v1` | `/openai/v1/chat/completions` |
| DeepSeek-TUI (`openai` provider) | TOML `base_url =` or `OPENAI_BASE_URL` | `https://api.qcode.cc/openai/v1` | `/openai/v1/chat/completions` |
| Codex CLI | TOML `base_url =` | `https://api.qcode.cc/openai` | `/openai/v1/responses` |
| OpenCode (`google` provider) | `baseURL` | `https://api.qcode.cc/gemini/v1beta` | `/gemini/v1beta/models/{model}:generateContent` |
| Gemini CLI / Google `@google/genai` SDK | base URL | `https://api.qcode.cc/gemini` | `/gemini/v1beta/models/{model}:generateContent` |


> **Why two forms for Gemini?** OpenCode's `google` provider does **not** auto-append `/v1beta/`, so the `baseURL` must include it (`/gemini/v1beta`). Gemini CLI and Google's official `@google/genai` SDK **do** auto-append `/v1beta/`, so the base URL only goes up to `/gemini` — appending `/v1beta` yourself would yield `/gemini/v1beta/v1beta/...` and return 404.

> **⚠️ Gemini CLI transition**: Gemini CLI reached end-of-life on 2026-06-18 (Pro / free tiers) — use the **Google Antigravity CLI** going forward; enterprise paid keys are unaffected. QCode.cc continues to serve Gemini models, and the Gemini base URL and API Key above are unchanged — Antigravity CLI uses the same `/gemini` endpoint.

## 5. Self-Test with curl

Before wiring up a full SDK, you can verify the path and network connectivity with a plain POST:

```bash
KEY="cr_your_key"

# Anthropic protocol path test
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://api.qcode.cc/api/v1/messages \
  -H "Authorization: Bearer $KEY"
# → 400 = path & key both OK (missing body is expected); 401 = invalid key

# OpenAI Chat Completions path test
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://api.qcode.cc/openai/v1/chat/completions \
  -H "Authorization: Bearer $KEY"
# → 400 / 401 as above

# OpenAI Responses (used by Codex)
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://api.qcode.cc/openai/v1/responses \
  -H "Authorization: Bearer $KEY"
# → 400 / 401 as above

# Google Gemini protocol path test
curl -s -o /dev/null -w '%{http_code}\n' -X POST "https://api.qcode.cc/gemini/v1beta/models/gemini-2.5-pro:generateContent" \
  -H "x-goog-api-key: $KEY"
# → 400 / 401 = path OK
```

**Interpretation**: with a key attached, `400` (missing body) or `401` (key issue) both mean the path mapping and network are fine; `404` means a wrong path prefix — fix it against the table in section 3. Note: hitting these paths **without a key** returns an HTML intro page (HTTP 200) rather than an error — seeing it means your key wasn't attached.

End-to-end test with a real API Key:

```bash
curl -X POST https://api.qcode.cc/api/v1/messages \
  -H "x-api-key: YOUR_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-5","max_tokens":64,"messages":[{"role":"user","content":"ping"}]}'
```

Swapping the domain to `us.qcode.cc` / `eu.qcode.cc` / `asia.qcode.cc` with the same path should produce the same result — this confirms the alternate domain is usable for you.

## 6. FAQ

**Q: Why does `curl https://api.qcode.cc/api` return 404?**

A: `/api` is a path prefix, not an endpoint. The full path is `/api/v1/messages`.

**Q: Any difference between `/api/v1/messages` and `/claude/v1/messages`?**

A: No. Both prefixes route to the Anthropic Messages protocol — use whichever your SDK defaults to. Our docs default to `/api` because that's what most Claude-ecosystem SDKs expect.

**Q: Can one API Key call Claude, Codex, and Gemini all?**

A: Yes. Keys are protocol-agnostic; **the protocol is chosen by the request path**. `/api/v1/messages` means Anthropic, `/openai/v1/responses` means OpenAI Responses, `/gemini/v1beta/models/...` means Google Gemini.

**Q: Should Gemini's `baseURL` end with `/v1beta` or not?**

A: It depends on the tool. **OpenCode's `google` provider needs it** (set `baseURL` to `/gemini/v1beta`) because it does not auto-append `/v1beta/`. **Gemini CLI and Google's `@google/genai` SDK do not** (set base URL to `/gemini`) — the SDK appends `/v1beta/` itself, and adding it manually would produce `/gemini/v1beta/v1beta/...` and return 404.

**Q: Which domain should I pick?**

A: Mainland China → `asia.qcode.cc` (Hong Kong, lowest latency) or `api.qcode.cc` (global Route 53); North America → `us.qcode.cc`; Europe → `eu.qcode.cc`. Switch freely between backups if your primary domain stalls.

**Q: Can I see my own request history?**

A: Yes. Requests sent through any domain (`api.qcode.cc` / `asia.qcode.cc` / `us.qcode.cc` / `eu.qcode.cc`) are reported to [probe.qcode.cc](https://probe.qcode.cc). Enter your API Key there to view the request list, models, tokens, and more.

**Q: Should I include a trailing slash in BASE_URL?**

A: **No**. Most SDKs auto-append paths like `/v1/messages`; a trailing slash would produce `//v1/messages` and cause 404.