Anthropic SDK
Aile's /v1/messages is the Anthropic wire format exactly.
1import os2from anthropic import Anthropic34client = Anthropic(5 base_url="https://api.aile.sh",6 api_key=os.environ["AILE_KEY"],7)89msg = client.messages.create(10 model="cc/claude-sonnet-5",11 max_tokens=256,12 messages=[{"role": "user", "content": "Say hello."}],13)14print(msg.content[0].text)
The base URL has no /v1
The Anthropic SDK appends /v1/messages itself, so it takes the bare origin:
https://api.aile.sh. This is the opposite of the OpenAI client, which wants the
/v1 suffix. If you pass https://api.aile.sh/v1 anyway, Aile serves the
doubled /v1/v1/messages as /v1/messages, so it still works.
Authentication
The Anthropic SDK sends x-api-key and only that. Aile accepts it, and accepts
Authorization: Bearer from OpenAI-shaped clients. Both reach the same key.
Non-Claude models work here too
The endpoint fixes the wire dialect; the model you name still comes from the
whole catalogue, and names its provider. codex/gpt-5.6-sol through the Anthropic
SDK routes cleanly to a Codex account:
1msg = client.messages.create(2 model="codex/gpt-5.6-sol",3 max_tokens=256,4 messages=[{"role": "user", "content": "Say hello."}],5)
Aile converts your Anthropic body into canonical OpenAI Chat first, then into the provider's own shape. See Model names.
Sending Aile headers
1msg = client.messages.create(2 model="cc/claude-sonnet-5",3 max_tokens=256,4 messages=[{"role": "user", "content": "Say hello."}],5 extra_headers={"x-aile-max-price": "8"},6)
Models that always think
Claude Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1 refuse a request that turns
thinking off or forces a tool choice. Rather than forward that into a 400, Aile
sends the nearest request the model accepts:
| You send | What goes upstream |
|---|---|
thinking: {"type": "disabled"} | Sonnet 5.5: {"type": "between_tools"}, its no-up-front-thinking setting. The others: thinking left at the model's default |
reasoning_effort: "none" or "minimal" (OpenAI SDK) | the lowest thinking setting, at effort low |
thinking: {"type": "enabled", "budget_tokens": N} on a model that only takes adaptive thinking | {"type": "adaptive"}, at the effort you named |
tool_choice forcing any or one tool | auto |
an effort the model does not take (xhigh or max) | the nearest one it does |
No response header reports these rewrites. The same rules apply whether you
call /v1/messages or /v1/chat/completions.
Counting tokens
1client.messages.count_tokens(2 model="cc/claude-sonnet-5",3 messages=[{"role": "user", "content": "…"}],4)
Advisory only: it probes no sharer, bills nothing, and estimates at roughly four characters per token.
Errors come back in Anthropic's shape
Because you called /v1/messages, errors are:
1{ "type": "error", "error": { "type": "invalid_request_error", "message": "…" } }
There is no code field in this shape: that is what the Anthropic SDK parses.
The shape follows the endpoint you called, regardless of the model you asked for.
See Error codes.