Get started
From Anthropic
Point Claude Code or the Anthropic SDK at Melious with two environment variables
Melious implements Anthropic's Messages API (POST /v1/messages) alongside the OpenAI API. If you're using Claude Code, the Anthropic SDK, or anything that speaks that shape, you don't need a new client — just two environment variables.
Claude Code
Claude Code needs two environment variables and, if you want to choose the models per slot, five more. Claude Code has the full setup, including the .claude/settings.local.json form.
The base URL is https://api.melious.ai — not .../v1. Anthropic's SDK appends its own version prefix, so you give it the root.
Anthropic SDK
Same idea, different caller:
from anthropic import Anthropic
client = Anthropic(
api_key="sk-mel-<YOUR_API_KEY>",
base_url="https://api.melious.ai",
)
response = client.messages.create(
model="claude-sonnet-4",
max_tokens=256,
messages=[{"role": "user", "content": "Name three Hanseatic cities."}],
)
text = "".join(block.text for block in response.content if block.type == "text")
print(text)import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "sk-mel-<YOUR_API_KEY>",
baseURL: "https://api.melious.ai",
});
const response = await client.messages.create({
model: "claude-sonnet-4",
max_tokens: 256,
messages: [{ role: "user", content: "Name three Hanseatic cities." }],
});
const text = response.content
.filter((block) => block.type === "text")
.map((block) => block.text)
.join("");
console.log(text);Any current SDK release works. Python anthropic 2.x and TypeScript 1.x send anthropic-version: 2026-10-21 and the key as Authorization: Bearer; older releases send 2023-06-01 and x-api-key. We accept any version value and both headers. The SDKs read our request-id response header into _request_id and APIStatusError.request_id — that's the id to quote to support.
How model names are mapped
We don't run Claude. When you send a claude-* model ID, we map it to an open-weight model before the inference runs. The Anthropic SDK hardcodes these names, and Claude Code ships with them — so the mapping is what lets those clients work unmodified.
The defaults:
| You send | We run |
|---|---|
anything containing opus (case-insensitive) | the main model |
anything containing sonnet | the secondary model |
anything containing haiku | the lightweight model |
| anything else | the string as-is |
Which open-weight model fills each slot is shown on melious.ai/hub/models.
The response carries the original name back. If you sent claude-sonnet-4, the response model field is claude-sonnet-4 — so Claude Code's internal assumptions don't break.
To run a specific open-weight model directly, send its ID:
response = client.messages.create(
model="<MODEL_ID>", # no mapping — runs exactly this model
max_tokens=256,
messages=[...],
)What's supported
Everything Anthropic SDK clients rely on for normal chat work:
- System prompts —
systemas string or content blocks - Multi-turn messages — the usual
role: "user" | "assistant"alternation - Tool use — Anthropic-shape
tools+tool_choice, withtool_use/tool_resultblocks in the response - Streaming — SSE with Anthropic event types (
message_start,content_block_delta,message_stop) - Vision —
imagecontent blocks with base64 or URL sources (model has to support it) - Stop sequences, temperature, top_p, top_k, max_tokens — passed through. Whether a model honors
top_kis up to the provider. - Extended thinking works on reasoning models. Send
thinking: {"type": "enabled", "budget_tokens": 8000}to turn it on,{"type": "disabled"}to turn it off, or leave it out for the model's default.output_config: {"effort": "high"}(low,medium,high,xhigh, ormax, lowercase) picks the depth directly and wins over the budget;disabledwins over both.xhighandmaxreach the model as sent only onglm-5.3andglm-5.3-flash; elsewhere they fold tohigh. Thinking comes back as athinkingcontent block before the text (signatureis always an empty string — don't send it back expecting Anthropic to verify it). Read the firsttextblock, notcontent[0].
Token counting is also implemented:
counted = client.messages.count_tokens(
model="claude-sonnet-4",
messages=[{"role": "user", "content": "Hello"}],
)
print(counted.input_tokens)See the Messages and Count tokens reference pages for full field details.
What's not supported
Honest list:
- Explicit
cache_controlblocks aren't exposed — there's no handle to mark a prefix as cacheable. Transparent prefix caching still happens on the provider side and shows up asusage.cache_read_input_tokens, billed at the cheaper cache-read rate. See Models. - Fine-grained tool streaming events — we emit
content_block_deltafor text andinput_json_deltafor tool arguments, matching the SDK's parser; less common events may be absent.
The intent is: if Claude Code and the stock Anthropic SDK work, we call it supported. If you're doing something exotic and something's missing, open an issue.
When it breaks
404on every request —ANTHROPIC_BASE_URLends in/v1. The SDK appends/v1/messagesitself, so the request goes to/v1/v1/messages, which doesn't exist. Set the base URL tohttps://api.melious.ai.- Tool loops behave differently than with Claude — this is a model-capability thing, not a protocol thing. Stronger models handle longer tool sequences better than smaller ones.
Error codes and retry guidance: Errors.