Anthropic API SDK for Node.js: Setup and Usage Guide
If you're building a Node.js application that talks to Claude, you have two main paths: install Anthropic's official @anthropic-ai/sdk package and manage your own API key and billing, or use a gateway that wraps the same API surface with extra tooling. This article covers the official SDK first — installation, authentication, message creation, streaming, and tool use — then explains when a layer like SubToAPI makes sense instead.
The official Anthropic SDK for Node.js is a thin, well-typed wrapper around the Anthropic REST API. It handles request signing, retries, streaming parsing, and gives you typed responses out of the box if you're on TypeScript. It does not add caching, team billing, or usage dashboards — that's a deliberate scope decision, and it's why a lot of teams pair it with something else once they move past prototyping.
Installing and Authenticating
Install the package with npm, yarn, or pnpm:
npm install @anthropic-ai/sdk
Set your API key as an environment variable rather than hardcoding it:
export ANTHROPIC_API_KEY="sk-ant-..."
Then create a client:
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
If you omit apiKey, the SDK automatically reads ANTHROPIC_API_KEY from process.env, so in most server setups you don't need to pass it explicitly.
Sending Your First Message
The core method is messages.create. It takes a model, a max token count, and an array of messages with role and content:
const response = await anthropic.messages.create({
model: "claude-opus-4-20250514",
max_tokens: 1024,
messages: [
{ role: "user", content: "Summarize the plot of Dune in three sentences." },
],
});
console.log(response.content[0].text);
The response object includes usage (input and output token counts), stop_reason, and the model that actually served the request. This is the same shape you'll see across SDKs for other languages, so if you've used the Python SDK before, the Node version will feel familiar.
Streaming Responses
For chat UIs or anything latency-sensitive, streaming avoids waiting for the full completion before showing text to the user. The SDK exposes a stream helper:
const stream = anthropic.messages.stream({
model: "claude-opus-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Write a haiku about Node.js." }],
});
stream.on("text", (text) => {
process.stdout.write(text);
});
const finalMessage = await stream.finalMessage();
The stream object emits incremental text events as tokens arrive, and finalMessage() resolves once the full response is complete, giving you both real-time output and a final structured object in one call.
Tool Use (Function Calling)
Claude supports tool use, where you describe available functions and the model decides when to call them. You define tools with a JSON schema and pass them alongside your messages:
const response = await anthropic.messages.create({
model: "claude-opus-4-20250514",
max_tokens: 1024,
tools: [
{
name: "get_weather",
description: "Get the current weather for a city",
input_schema: {
type: "object",
properties: {
city: { type: "string" },
},
required: ["city"],
},
},
],
messages: [{ role: "user", content: "What's the weather in Lisbon?" }],
});
When Claude decides to call get_weather, the response contains a tool_use content block with structured input. Your code executes the actual function, then sends the result back in a follow-up message with role user and a tool_result content block. This loop — model requests a tool, your code runs it, you return the result — is the backbone of most agentic Node.js apps built on Claude.
Error Handling and Retries
The SDK throws typed errors (Anthropic.APIError, Anthropic.RateLimitError, Anthropic.AuthenticationError, etc.) so you can branch on failure type:
try {
await anthropic.messages.create({ /* ... */ });
} catch (err) {
if (err instanceof Anthropic.RateLimitError) {
console.log("Rate limited, retry after", err.headers["retry-after"]);
} else {
throw err;
}
}
It also retries transient failures (like 5xx responses) automatically with exponential backoff, configurable via the maxRetries option on the client constructor.
When to Add a Gateway on Top
The official SDK is the right starting point for a single developer building against their own Anthropic account. Problems show up once you have multiple apps, multiple environments, or a team: everyone shares one raw API key, there's no per-app usage breakdown, and billing is a single line item with no way to attribute spend.
SubToAPI sits between your Node.js code and Claude, turning your existing Claude access into a proper HTTPS API with scoped application keys (sub_live_...), per-app usage metadata, streaming, and tool use support — the same request shapes shown above, just pointed at https://api.subtoapi.app/v1/messages instead of Anthropic's endpoint. Swapping the base URL and key is usually a one-line change:
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "claude-opus-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello" }],
}),
});
This is useful for teams running several internal tools or client projects off one Claude subscription, since each app gets its own key and its own usage trail without anyone sharing root credentials. See the quickstart, messages, streaming, and tools docs for the full request and response shapes, and pricing for plan details — Solo, Team, and Scale all start with a free trial via signup.
Questions
Is there an official Anthropic SDK for Node.js? Yes, it's published as @anthropic-ai/sdk on npm, maintained by Anthropic, and supports both JavaScript and TypeScript with full type definitions.
Does the Node.js SDK support streaming and tool use? Yes. Use anthropic.messages.stream() for token-by-token streaming, and pass a tools array with JSON schemas to enable function calling via tool_use content blocks.
Can I use the same request format with a gateway instead of Anthropic directly? Yes. Services like SubToAPI expose a compatible /v1/messages endpoint, so you can keep your existing Node.js request code and just change the base URL and API key.