Anthropic SDK · Python · MonkeyAI · Evidence-anchored 2026-08-09

Use the Anthropic Python SDK with a custom Base URL.

The Anthropic Python SDK defaults to https://api.anthropic.com. To route it through MonkeyAI, override base_url= on the client constructor or export ANTHROPIC_BASE_URL. The SDK then sends x-api-key plus anthropic-version: 2023-06-01 to /v1/messages. This guide verifies that path against production on 2026-08-09 and walks through a real client.messages.create() call.

Base URLhttps://monkeytheme.com
EndpointPOST /v1/messages
Auth headerx-api-key (SDK default)
Verified2026-08-09

What was actually verified on production?

Six probes were sent to https://monkeytheme.com/v1/messages with a deliberately invalid test key, on 2026-08-09. Every probe returned HTTP 401 with a structured JSON body and the x-request-id header in the response. The sub2api backend log shows ingress_reject_reason=invalid_api_key with latency_ms=0-3 on every request, meaning the relay gates on auth before any upstream call.

ProbeHeadersResponseWhat it confirms
POST /v1/messagesx-api-key only401 INVALID_API_KEYSDK-default auth path works; no anthropic-version required
POST /v1/messagesx-api-key + anthropic-version: 2023-06-01401 INVALID_API_KEYSDK-style dual-header request reaches the relay intact
POST /v1/messagesAuthorization: Bearer ***401 INVALID_API_KEYBearer also accepted on Messages, same as OpenAI routes
GET /v1/modelsx-api-key401 INVALID_API_KEYModels endpoint also gates on auth (probe, not real list)
GET /v1/modelsanthropic-version alone401 API_KEY_REQUIREDanthropic-version is NOT used as an auth header
POST /v1/messagesx-api-key + tools + stream=true401 INVALID_API_KEYAuth gate runs before schema parse or stream branch
This page does not run authenticated inference against a real MonkeyAI account. A 401 INVALID_API_KEY on the right path proves routing and auth, not generation. To confirm Claude inference end-to-end, run the snippet below with your own account key.

Install and configure the SDK

The Anthropic Python SDK is on PyPI as anthropic. The README documents ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY environment variables; the constructor also accepts base_url= and api_key= directly.

python -m venv .venv
source .venv/bin/activate
pip install anthropic

export ANTHROPIC_BASE_URL="https://monkeytheme.com"
export ANTHROPIC_API_KEY="***"

Do not commit the key into source. os.environ is fine for the snippet below; for production prefer a secrets manager or ~/.zshrc-level shell export.

import os
import anthropic

client = anthropic.Anthropic(
    api_key=os.environ["ANTHROPIC_API_KEY"],
    base_url=os.environ["ANTHROPIC_BASE_URL"],
)
Set base_url to the API root without a trailing /v1 or /messages. The SDK builds the full URL itself: {base_url}/v1/messages. Appending /v1 by hand causes a 404 because the resulting path becomes /v1/v1/messages.

Verify the key before sending real prompts

The Anthropic SDK does not expose models.list(). To confirm a key is alive, send a single-token client.messages.create() call with max_tokens=1. If the key is bad you get a 401 with a request ID; if the key is good you get a 1-token Claude reply with a model field that confirms the upstream model name.

resp = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1,
    messages=[{"role": "user", "content": "Reply with OK"}],
)
print(resp.model, resp.stop_reason, resp.usage)

If resp.model prints a Claude model name visible to your account, the SDK wiring is correct. The Anthropic SDK README pins anthropic-version to 2023-06-01 on every request; you do not need to set it yourself.

How should errors be handled?

The SDK raises anthropic.APIStatusError for non-2xx responses. For connection and timeout failures it raises anthropic.APIConnectionError. Log the request ID from the exception; do not log the API key.

import anthropic

try:
    resp = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=64,
        messages=[{"role": "user", "content": "hi"}],
    )
except anthropic.APIStatusError as exc:
    print("HTTP", exc.status_code, "request_id", exc.request_id)
    raise
except anthropic.APIConnectionError as exc:
    print("network/TLS:", repr(exc.__cause__))
    raise

A 401 with code=INVALID_API_KEY from MonkeyAI is the same code the OpenAI route returns. The relay does not distinguish between Anthropic and OpenAI keys at this layer; both are MonkeyAI keys, and they live in the same backend.

Streaming, tools and retries

Streaming on /v1/messages uses Server-Sent Events. The Anthropic SDK returns an iterator you can for-loop over. Retries on 429 and 5xx are on by default; set max_retries=0 while debugging so a transient 429 does not silently mask the real failure.

with client.messages.stream(
    model="claude-3-5-sonnet-20241022",
    max_tokens=256,
    messages=[{"role": "user", "content": "Summarise this in one sentence."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    final = stream.get_final_message()

Tools work the same way they do against api.anthropic.com. If a tool_use block comes back, the SDK parses it into resp.content. If you instead see a 400 from upstream after a 200 from the relay, the upstream account likely rejected the tool schema, not MonkeyAI.

Common configuration mistakes

Sources

FAQ

What Base URL should I use?

Set base_url to https://monkeytheme.com. The SDK appends /v1/messages.

Does the SDK send Authorization Bearer?

No. The Anthropic Python SDK sends x-api-key by default. MonkeyAI also accepts Authorization: Bearer on /v1/messages.

Does anthropic-version matter?

The Anthropic SDK sets it on every request. MonkeyAI does not require it but passes it upstream; stripping it on the client side breaks upstream, not MonkeyAI.

Does models.list() exist on the Anthropic SDK?

No. The Anthropic SDK does not expose a models list. Use GET /v1/models via curl or the requests library instead.

Does 401 prove the SDK wiring is correct?

No. 401 INVALID_API_KEY proves the request reached the relay and auth was rejected. Run a real client.messages.create() with your own key to verify generation.

Related guides

OpenAI Python SDK

The OpenAI-compatible equivalent for /v1/chat/completions and /v1/responses.

Open page

Anthropic Node SDK

Same wiring for Node.js, using @anthropic-ai/sdk and baseURL.

Open page

Claude Code gateway

Use the Anthropic SDK with Claude Code CLI via ANTHROPIC_BASE_URL.

Open page

401 invalid token

What 401 INVALID_API_KEY actually means on /v1/messages.

Open page

Endpoint coverage

The full /v1 matrix on MonkeyAI, probed on 2026-08-09.

Open page

504 upstream timeout

Why a 401 is fast and a 504 is slow on the same route.

Open page