open33 API

TutoriaisAtualizado em 4 min de leitura

API do Claude com TypeScript e Node.js: guia prático

Este tutorial mostra como usar a API do Claude em TypeScript e Node.js com o SDK oficial da Anthropic. Os exemplos usam o Claude Opus 5 (claude-opus-5) e funcionam com a API da open33 trocando só a URL base e a chave.

Instalação

npm install @anthropic-ai/sdk

Configuração

O SDK lê ANTHROPIC_BASE_URL e ANTHROPIC_API_KEY do ambiente:

export ANTHROPIC_BASE_URL="https://api.open33.tech"
export ANTHROPIC_API_KEY="SUA_CHAVE"

Se preferir deixar a URL explícita no código, passe baseURL ao criar o cliente e mantenha a chave em variável de ambiente:

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

const client = new Anthropic({
  baseURL: "https://api.open33.tech",
  apiKey: process.env.ANTHROPIC_API_KEY,
});

A primeira chamada

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

const client = new Anthropic();

const resposta = await client.messages.create({
  model: "claude-opus-5",
  max_tokens: 16000,
  messages: [{ role: "user", content: "Crie um schema Zod para um cadastro com nome, e-mail e CPF." }],
});

for (const bloco of resposta.content) {
  if (bloco.type === "text") console.log(bloco.text);
}
console.log(resposta.usage);

resposta.content é uma lista de blocos de tipos diferentes. O TypeScript obriga a checar bloco.type antes de ler bloco.text, e isso é bom: o Claude Opus 5 pode devolver outros blocos antes do texto.

Conversa com histórico

A API não guarda estado. Envie o histórico inteiro a cada chamada, usando os tipos do próprio SDK:

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

const client = new Anthropic();
const historico: Anthropic.MessageParam[] = [];

async function perguntar(texto: string): Promise<string> {
  historico.push({ role: "user", content: texto });
  const resposta = await client.messages.create({
    model: "claude-opus-5",
    max_tokens: 16000,
    system: "Você é um assistente de programação. Responda em português.",
    messages: historico,
  });
  historico.push({ role: "assistant", content: resposta.content });
  return resposta.content
    .filter((b): b is Anthropic.TextBlock => b.type === "text")
    .map((b) => b.text)
    .join("");
}

console.log(await perguntar("Estou criando uma API em Express."));
console.log(await perguntar("Como adiciono validação de entrada nela?"));

Streaming em uma rota de API

Para mostrar a resposta enquanto ela é gerada, use client.messages.stream. Um exemplo de rota que envia o texto aos pedaços para o navegador (Node 18+, com qualquer framework que aceite um Response de streaming):

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

const client = new Anthropic();

export async function POST(req: Request) {
  const { pergunta } = await req.json();

  const stream = client.messages.stream({
    model: "claude-opus-5",
    max_tokens: 64000,
    messages: [{ role: "user", content: pergunta }],
  });

  const encoder = new TextEncoder();
  const corpo = new ReadableStream({
    async start(controller) {
      for await (const evento of stream) {
        if (evento.type === "content_block_delta" && evento.delta.type === "text_delta") {
          controller.enqueue(encoder.encode(evento.delta.text));
        }
      }
      controller.close();
    },
  });

  return new Response(corpo, { headers: { "content-type": "text/plain; charset=utf-8" } });
}

A chave fica no servidor. Nunca chame a API direto do navegador com a sua chave: qualquer visitante conseguiria copiá-la. Mais detalhes no guia de streaming.

Tratando erros

O SDK repete sozinho, por padrão duas vezes, as falhas de conexão, os 429 e os 5xx. Para o resto, use as classes de erro do SDK:

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

try {
  await client.messages.create({
    model: "claude-opus-5",
    max_tokens: 16000,
    messages: [{ role: "user", content: "Olá!" }],
  });
} catch (err) {
  if (err instanceof Anthropic.AuthenticationError) {
    console.error("Chave inválida: confira ANTHROPIC_API_KEY.");
  } else if (err instanceof Anthropic.NotFoundError) {
    console.error("Endpoint ou modelo não encontrado: confira a URL base e o modelo.");
  } else if (err instanceof Anthropic.RateLimitError) {
    console.error("Limite atingido (429): aguarde a próxima janela do plano.");
  } else if (err instanceof Anthropic.APIConnectionError) {
    console.error("Falha de rede: confira sua conexão.");
  } else if (err instanceof Anthropic.APIError) {
    console.error(`Erro da API (${err.status}): ${err.message}`);
  } else {
    throw err;
  }
}

Próximos passos

Perguntas frequentes

Funciona com JavaScript puro?

Sim. O pacote @anthropic-ai/sdk funciona em JavaScript e TypeScript. Os exemplos em TypeScript funcionam em JavaScript sem as anotações de tipo.

Posso usar no navegador?

Não com a sua chave. Faça as chamadas no servidor (Node, uma rota de API ou uma função serverless) e envie só a resposta para o navegador.

Qual a diferença entre messages.create e messages.stream?

create espera a resposta inteira e devolve tudo de uma vez. stream entrega a resposta aos pedaços, enquanto ela é gerada, e é o indicado para respostas longas e para interfaces de chat.

Qual o timeout padrão do SDK?

Dez minutos por requisição. No SDK de TypeScript, o valor é informado em milissegundos na opção timeout.

Continue lendo