Anthropic SDK · Node.js · MonkeyAI · Evidence-anchored 2026-08-09

Use the Anthropic Node SDK with a custom baseURL.

The Anthropic Node SDK (@anthropic-ai/sdk) defaults to https://api.anthropic.com. To route it through MonkeyAI, pass baseURL: to 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.

baseURLhttps://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, meaning the relay gates on auth before any upstream call. The Node SDK behaviour mirrors the Python SDK because both implement the same wire protocol.

ProbeHeadersResponseWhat it confirms
POST /v1/messagesx-api-key only401 INVALID_API_KEYSDK-default auth path works without anthropic-version
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
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 client

The Anthropic Node SDK is on npm as @anthropic-ai/sdk. It accepts baseURL, apiKey, and authToken on the constructor. The README documents ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY as environment fallbacks.

npm install @anthropic-ai/sdk

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

Do not commit the key into source. process.env is fine for the snippet below; for production prefer a secrets manager or a .env.local file outside version control.

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
  baseURL: process.env.ANTHROPIC_BASE_URL,
});
Pass baseURL as the API root without a trailing /v1 or /messages. The SDK builds the full URL itself: {baseURL}/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 a models.list() helper. 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.

const resp = await client.messages.create({
  model: "claude-3-5-sonnet-20241022",
  max_tokens: 1,
  messages: [{ role: "user", content: "Reply with OK" }],
});
console.log(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 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 throws APIError for non-2xx responses and AnthropicError for other SDK-side issues. Both expose .status and .headers. Log the request ID from the error headers; do not log the API key.

try {
  const resp = await client.messages.create({
    model: "claude-3-5-sonnet-20241022",
    max_tokens: 64,
    messages: [{ role: "user", content: "hi" }],
  });
} catch (err) {
  if (err.status) {
    const reqId = err.headers?.get?.("x-request-id");
    console.error("HTTP", err.status, "request_id", reqId);
  } else {
    console.error("network/TLS:", err.cause ?? err.message);
  }
  throw err;
}

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 exposes a stream helper via client.messages.stream(...). Retries on 429 and 5xx are on by default; set maxRetries: 0 while debugging so a transient 429 does not silently mask the real failure.

const stream = client.messages.stream({
  model: "claude-3-5-sonnet-20241022",
  max_tokens: 256,
  messages: [{ role: "user", content: "Summarise this in one sentence." }],
});

for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

const final = await stream.finalMessage();

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 baseURL should I pass?

Pass baseURL: https://monkeytheme.com. The SDK appends /v1/messages.

Does the SDK send Authorization Bearer?

No. @anthropic-ai/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 Node SDK?

No. The Anthropic SDK does not expose a models list helper. Use GET /v1/models via fetch or undici 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 Node SDK

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

Open page

Anthropic Python SDK

Same wiring for Python, using anthropic.Anthropic(base_url=).

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