Claude Code API Client TypeScript Guide (2026)
Building a TypeScript client for interacting with Claude Code opens up powerful automation possibilities. Whether you’re integrating Claude into your CI/CD pipeline, building a custom dashboard, or composing multiple skills programmatically, understanding the API client patterns in TypeScript will accelerate your development workflow.
Setting Up Your TypeScript Project
Before diving into API interactions, set up a TypeScript project with proper dependencies. You’ll need the Anthropic SDK and type definitions:
npm init -y
npm install @anthropic-ai/sdk typescript @types/node
npx tsc --init
Create a client configuration file that handles authentication and base settings:
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
maxRetries: 3,
timeout: 60000,
});
export default client;
This basic setup gives you access to the Claude Messages API, which serves as the foundation for all skill interactions.
Working with Claude Skills in TypeScript
Claude skills extend the base API with specialized prompts and tool configurations. When building a TypeScript client, you can invoke skills directly or compose multiple skills for complex workflows.
Invoking a Single Skill
The Messages API accepts a system parameter where you can inject skill content:
async function invokeSkill(skillContent: string, userMessage: string) {
const response = await client.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 4096,
system: skillContent,
messages: [{ role: 'user', content: userMessage }],
});
return response.content[0].type === 'text'
? response.content[0].text
: null;
}
This pattern works well for skills like the pdf skill when you need to process documents programmatically, or the tdd skill for generating test suites from your TypeScript code.
Composing Multiple Skills
For more complex workflows, chain multiple skill invocations:
async function composeWorkflow(skills: string[], input: string) {
let currentInput = input;
for (const skill of skills) {
const result = await invokeSkill(skill, currentInput);
currentInput = result || currentInput;
}
return currentInput;
}
This approach shines when combining the frontend-design skill for UI generation with the pdf skill for documentation, or using supermemory to retrieve context before processing.
Authentication and Environment Configuration
Production implementations require secure authentication handling. Never hardcode API keys in your source code. Instead, use environment variables with validation:
import { z } from 'zod';
const envSchema = z.object({
ANTHROPIC_API_KEY: z.string().min(1),
CLAUDE_MODEL: z.enum(['claude-sonnet-4-20250514', 'claude-opus-4-20250514']).default('claude-sonnet-4-20250514'),
MAX_TOKENS: z.number().default(4096),
});
function loadConfig() {
const result = envSchema.safeParse(process.env);
if (!result.success) {
throw new Error(`Environment validation failed: ${result.error.format()}`);
}
return result.data;
}
export const config = loadConfig();
This validation prevents runtime errors from missing configuration and provides clear error messages during development.
Handling Tool Calls and Responses
Claude skills often involve tool use. Your TypeScript client needs to handle the message deltas that include tool invocations:
interface ToolResult {
type: 'tool_use';
id: string;
name: string;
input: Record<string, unknown>;
}
async function executeWithTools(
systemPrompt: string,
userMessage: string,
availableTools: any[]
) {
const stream = await client.messages.stream({
model: config.CLAUDE_MODEL,
max_tokens: config.MAX_TOKENS,
system: systemPrompt,
messages: [{ role: 'user', content: userMessage }],
tools: availableTools,
});
let fullResponse = '';
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta') {
fullResponse += chunk.delta.text;
}
}
return fullResponse;
}
The mcp-builder skill provides excellent patterns for creating custom MCP servers that your TypeScript client can interact with, extending Claude’s capabilities beyond built-in tools.
Error Handling and Retry Logic
Network failures and rate limits require solid error handling. Implement exponential backoff for reliability:
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries: number = 3
): Promise<T> {
let lastError: Error | null = null;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
This retry logic handles transient failures gracefully, which is essential when integrating with Claude’s API in production environments.
Type-Safe Skill Definitions
Use TypeScript’s type system to create type-safe skill definitions:
interface SkillDefinition<TInput, TOutput> {
name: string;
systemPrompt: string;
parseOutput: (raw: string) => TOutput;
transformInput: (input: TInput) => string;
}
const tddSkill: SkillDefinition<string, string[]> = {
name: 'tdd',
systemPrompt: 'Generate unit tests following TDD principles...',
parseOutput: (raw) => raw.split('\n').filter(line => line.includes('describe(')),
transformInput: (code) => `Generate tests for:\n${code}`,
};
async function runTdd(input: string): Promise<string[]> {
const prompt = tddSkill.transformInput(input);
const raw = await invokeSkill(tddSkill.systemPrompt, prompt);
return tddSkill.parseOutput(raw || '');
}
This pattern ensures type safety across your skill invocations and makes refactoring straightforward when skill prompts change.
Real-World Integration Example
Putting it all together, here’s a practical workflow that uses multiple skills:
async function processProjectDocumentation(projectPath: string) {
const fs = await import('fs/promises');
const code = await fs.readFile(projectPath, 'utf-8');
// Use tdd skill to generate tests
const tests = await invokeSkill(tddSkillPrompt, code);
// Use pdf skill to generate documentation
const docs = await invokeSkill(pdfSkillPrompt, tests);
// Use supermemory to store results
await storeInMemory('project-docs', { tests, docs });
return { tests, docs };
}
This workflow demonstrates how TypeScript clients can orchestrate multiple Claude skills for comprehensive project automation.
Building a TypeScript API client for Claude Code gives you programmatic control over AI-powered workflows. The patterns covered here, authentication, skill composition, tool handling, and error recovery, provide a solid foundation for both simple integrations and complex production systems.
Step-by-Step Guide: Building a Production TypeScript Client
Here is a concrete workflow for taking a TypeScript API client from prototype to production-ready integration.
Step 1. Scaffold the project with strict TypeScript settings. Start with npx tsc --init and enable strict, noImplicitAny, and exactOptionalPropertyTypes in your tsconfig. Claude Code generates a tsconfig.json tuned for Node.js API projects that catches common type errors at compile time rather than runtime.
Step 2. Create a centralized client factory. Rather than instantiating Anthropic directly in every module, create a singleton factory that validates configuration, sets defaults, and exposes the configured client. Claude Code generates this factory with Zod schema validation so misconfigured environments fail fast with descriptive errors.
Step 3. Define your skill registry. Create a TypeScript module that exports typed skill definitions mapping skill names to their system prompts, expected input shapes, and output parsers. This registry becomes the single source of truth, when skill prompts change, you update one file and the compiler flags every call site that needs attention.
Step 4. Add request/response logging middleware. Wrap the Anthropic client with a thin middleware layer that logs request parameters, token usage, latency, and error codes to your observability platform. Claude Code generates the wrapper using the decorator pattern, keeping logging concerns separate from business logic.
Step 5. Implement integration tests with recorded fixtures. Record real API responses using nock or msw and use them as fixtures in your test suite. Claude Code generates the fixture recording script and the test harness, so your CI pipeline runs without hitting the live API while still testing real response shapes.
Common Pitfalls
Not handling streaming responses correctly. When using client.messages.stream(), you must handle the async iterator properly. Forgetting to await the stream completion or not handling backpressure causes incomplete responses. Claude Code generates stream handlers with proper error boundaries and cancellation support.
Sharing client instances across async contexts without isolation. The Anthropic SDK client is stateless and safe to share, but per-request state like conversation history is not. Teams that attach message history to the shared client instance see conversation bleeding between unrelated requests. Claude Code generates a ConversationSession wrapper that keeps history isolated per session.
Hardcoding model identifiers. Model names change with new releases. Hardcoding claude-sonnet-4-20250514 throughout your codebase means a model upgrade requires a search-and-replace across dozens of files. Claude Code generates a constants module with version-aware model references and a migration guide for updating when new models ship.
Ignoring the stop_reason field. When stop_reason is max_tokens, the response is truncated. Code that treats all responses as complete misses this signal and presents partial output to users. Claude Code generates response validators that check stop_reason and either request continuation or surface a clear error.
Not implementing circuit breakers for downstream failures. If your TypeScript client is part of a larger service, unhandled API failures cascade into upstream timeouts. Claude Code generates a circuit breaker wrapper using the half-open pattern that stops sending requests when the API is degraded and resumes automatically when health is restored.
Best Practices
Version your skill definitions alongside your API version. When Anthropic releases a new model, your skill system prompts may need tuning. Keep skill definitions in a versioned directory structure (skills/v1/, skills/v2/) and use feature flags to control which version your client loads. Claude Code generates the versioning scaffold and the feature flag integration.
Use TypeScript discriminated unions for response handling. The Messages API returns different content block types. Instead of checking .type === 'text' everywhere, define a discriminated union and use exhaustive switch statements. The TypeScript compiler then flags unhandled content block types when new types are added.
Cache system prompts, not completions. Skill system prompts are static text that can reach thousands of tokens. Cache the compiled system prompt string in memory rather than rebuilding it from templates on every request. This saves CPU and reduces the risk of template rendering bugs affecting production traffic.
Test with realistic token budgets. Development testing with generous max_tokens values hides truncation bugs that surface in production when cost controls reduce the budget. Claude Code generates parameterized test suites that run the same prompts against multiple token budget configurations.
Integration Patterns
Next.js API routes. Expose your TypeScript Claude client through Next.js API routes with proper streaming support. Claude Code generates the route handler using Response.stream() with the Vercel AI SDK’s streaming helpers, enabling real-time token streaming to browser clients without buffering the full response server-side.
Nx monorepo shared libraries. In a monorepo, extract your Claude client into a shared library package that multiple applications import. Claude Code generates the Nx library scaffold with proper peer dependency declarations so the Anthropic SDK is not bundled multiple times.
OpenTelemetry tracing. Instrument your client with OpenTelemetry spans to track API latency, token usage, and error rates alongside your other services. Claude Code generates the instrumentation wrapper that creates spans for each API call and propagates trace context through the x-request-id header.
Advanced Patterns: Streaming and Long-Running Operations
For operations that take more than a few seconds, the synchronous request-response pattern produces a poor user experience. Streaming responses let you display partial results as they arrive rather than waiting for the complete response.
Claude Code generates the streaming client method using client.messages.stream() that returns an async generator. Your TypeScript calling code iterates the generator and passes each text delta to a state update function. The pattern integrates naturally with React’s concurrent rendering model. the stream updates state incrementally, and React batches the renders for smooth display.
For background jobs that run for minutes or hours, Claude Code generates the polling helper that initiates the job, stores the job ID, and polls a status endpoint with exponential backoff until the job completes or fails. The helper returns a typed result object and surfaces progress updates through a callback, giving users visibility into long-running operations without blocking the main thread.
Try it: Paste your error into our Error Diagnostic for an instant fix.
Related Reading
- What Is the Best Claude Skill for REST API Development?
- Claude Code Tutorials Hub
- Best Claude Skills for Developers in 2026
- Claude Code Guides Hub
- Building TypeScript APIs with Claude Code and Hono Framework
- How Context Window Size Drives Claude API Bills
- How to Use Vonage Voice API (2026)
- Claude Code For Openapi Zod — Complete Developer Guide
- Claude Max Subscription vs API for Agent Fleets
- Claude Code Keeps Using Deprecated API Methods
- How to Reduce Claude API Token Usage by 50%
- Model Routing by Task Cuts Claude API Bills
Built by theluckystrike. More at zovo.one
Estimate usage → Calculate your token consumption with our Token Estimator.
Configure MCP → Build your server config with our MCP Config Generator.