Advanced Claude

Best Practices & Safety

Build reliable, safe, and cost-effective applications with the Claude API.

Production Best Practices

Error Handling

Always wrap API calls in try-catch. The API can return:

  • 400 — Invalid request (bad parameters)
  • 401 — Authentication error (invalid API key)
  • 403 — Permission denied
  • 429 — Rate limit exceeded
  • 500 — Internal server error (retry with backoff)

Retry Logic

Implement exponential backoff for 429 and 500 errors.

Cost Optimization

  • Use the cheapest model that works for your task
  • Cache responses where possible
  • Monitor token usage with response.usage
  • Use max_tokens to limit output length
  • Be concise in your system prompts

Security

  • Never expose your API key in client-side code
  • Always validate/sanitize user input before sending to Claude
  • Use server-side API calls (Next.js API routes, Edge Functions)
  • Implement rate limiting on your own endpoints

Safety & Responsible Use

Claude has built-in safety features, but you should:

  • Monitor responses for inappropriate content
  • Implement feedback mechanisms
  • Test edge cases and adversarial inputs
  • Follow Anthropic's usage policies

Example

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

const client = new Anthropic();

// Robust wrapper with retry logic
async function callClaude(
  messages: Anthropic.MessageParam[],
  retries = 3
): Promise<string> {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try {
      const response = await client.messages.create({
        model: "claude-haiku-3-5", // cheapest model
        max_tokens: 1024,
        messages,
      });

      return response.content[0].type === "text"
        ? response.content[0].text
        : "";
    } catch (error) {
      if (error instanceof Anthropic.RateLimitError) {
        if (attempt === retries) throw error;
        // Exponential backoff: 1s, 2s, 4s
        await new Promise(r => setTimeout(r, 1000 * 2 ** (attempt - 1)));
        continue;
      }
      if (error instanceof Anthropic.APIError) {
        console.error(`API Error ${error.status}: ${error.message}`);
      }
      throw error;
    }
  }
  throw new Error("Max retries exceeded");
}

// Simple input validation
function sanitizeUserInput(input: string): string {
  return input
    .slice(0, 10000)      // limit length
    .replace(/<[^>]*>/g, "") // strip HTML
    .trim();
}

// Cost tracking
const COSTS = {
  "claude-haiku-3-5": { input: 0.0008, output: 0.004 },
  "claude-opus-4-5": { input: 0.003, output: 0.015 },
};

function estimateCost(model: string, usage: Anthropic.Usage): number {
  const rates = COSTS[model as keyof typeof COSTS];
  if (!rates) return 0;
  return (
    (usage.input_tokens / 1000) * rates.input +
    (usage.output_tokens / 1000) * rates.output
  );
}
Try it yourself — TYPESCRIPT