Tips & Tricks

Criando uma REST API com Claude Code | Guia Prático para Iniciantes

Aprenda os fundamentos de REST API com Claude Code. Um guia prático cobrindo design de endpoints, validação e tratamento de erros — com código pronto para copiar.

“Não sei por onde começar com REST APIs” — eu também me sentia assim no começo.

Ler a documentação parecia muito abstrato. Eu não conseguia entender o que exatamente devia construir. Foi quando comecei a usar o Claude Code e percebi que “construir algo que funcione primeiro, aprender enquanto vai” é a abordagem mais rápida.

Neste guia, vamos do zero conhecimento de REST API até uma API totalmente funcional — passo a passo, junto com o Claude Code. Todos os trechos de código estão prontos para copiar e colar.


O que é uma REST API? (Em 3 Linhas)

Uma REST API é uma convenção para manipular recursos (dados) na web via HTTP.

Navegador/App  →  Requisição HTTP  →  Servidor (API)
               ←  Resposta JSON   ←

Para uma API de gerenciamento de usuários, fica assim:

ObjetivoMétodo HTTPURL
Buscar todos os usuáriosGET/users
Buscar um usuário específicoGET/users/123
Criar um usuárioPOST/users
Atualizar um usuárioPUT/users/123
Deletar um usuárioDELETE/users/123

Com isso entendido, você já está pronto para começar a construir com o Claude Code.


Configuração do Ambiente

Vamos usar o Hono — um framework web TypeScript leve. É mais type-safe que o Express e funciona muito bem com o Claude Code.

mkdir my-first-api
cd my-first-api
npm init -y
npm install hono
npm install -D typescript @types/node ts-node
npx tsc --init

Crie src/index.ts e pergunte ao Claude Code:

claude -p "
Crie um boilerplate de REST API usando Hono em src/index.ts.
- Inicie o servidor na porta 3000
- Adicione um endpoint GET /health para health check
- Retorne respostas em JSON
Comando de execução: npx ts-node src/index.ts
"

O Claude Code vai gerar algo assim:

// src/index.ts
import { Hono } from "hono";
import { serve } from "@hono/node-server";

const app = new Hono();

app.get("/health", (c) => {
  return c.json({ status: "ok", timestamp: new Date().toISOString() });
});

serve({ fetch: app.fetch, port: 3000 }, () => {
  console.log("Server running at http://localhost:3000");
});
npx ts-node src/index.ts
# → Server running at http://localhost:3000

curl http://localhost:3000/health
# → {"status":"ok","timestamp":"2026-04-27T07:30:00.000Z"}

Funcionou? Esse é seu ponto de partida para REST APIs.


Step 1: Criar CRUD Básico

A seguir, vamos construir uma API para gerenciar uma lista de Todos. Peça ao Claude Code:

claude -p "
Adicione endpoints CRUD de Todo em src/index.ts.
- GET  /todos         — Listar todos os todos
- GET  /todos/:id     — Buscar um todo
- POST /todos         — Criar (title: string obrigatório)
- PUT  /todos/:id     — Atualizar (title: string)
- DELETE /todos/:id   — Deletar

Gerenciar dados em um array na memória.
Tipo Todo: { id: string, title: string, done: boolean, createdAt: string }
Gerar id com crypto.randomUUID()
"

Código gerado:

import { Hono } from "hono";
import { serve } from "@hono/node-server";

const app = new Hono();

// Armazenamento de dados na memória
type Todo = { id: string; title: string; done: boolean; createdAt: string };
let todos: Todo[] = [];

// Listar todos
app.get("/todos", (c) => c.json(todos));

// Buscar um todo
app.get("/todos/:id", (c) => {
  const todo = todos.find((t) => t.id === c.req.param("id"));
  if (!todo) return c.json({ error: "Not found" }, 404);
  return c.json(todo);
});

// Criar
app.post("/todos", async (c) => {
  const body = await c.req.json();
  if (!body.title) return c.json({ error: "title is required" }, 400);
  const todo: Todo = {
    id: crypto.randomUUID(),
    title: body.title,
    done: false,
    createdAt: new Date().toISOString(),
  };
  todos.push(todo);
  return c.json(todo, 201);
});

// Atualizar
app.put("/todos/:id", async (c) => {
  const idx = todos.findIndex((t) => t.id === c.req.param("id"));
  if (idx === -1) return c.json({ error: "Not found" }, 404);
  const body = await c.req.json();
  todos[idx] = { ...todos[idx], ...body };
  return c.json(todos[idx]);
});

// Deletar
app.delete("/todos/:id", (c) => {
  const idx = todos.findIndex((t) => t.id === c.req.param("id"));
  if (idx === -1) return c.json({ error: "Not found" }, 404);
  todos.splice(idx, 1);
  return c.json({ message: "Deleted" });
});

serve({ fetch: app.fetch, port: 3000 }, () => {
  console.log("Server running at http://localhost:3000");
});

Experimente:

# Criar um Todo
curl -X POST http://localhost:3000/todos \
  -H "Content-Type: application/json" \
  -d '{"title": "Testar o Claude Code"}'

# Listar todos
curl http://localhost:3000/todos

# Deletar (use o id retornado acima)
curl -X DELETE http://localhost:3000/todos/<id>

Step 2: Adicionar Validação

“Um título vazio ainda consegue ser criado” ou “Qualquer string funciona como ID” — a validação previne esses problemas. Peça ao Claude Code:

claude -p "
Adicione validação com zod para POST /todos e PUT /todos/:id.
- title: string, 1-100 caracteres
- done: (somente PUT) boolean
Retorne erro 400 com mensagem de erro específica quando a validação falhar
"
npm install zod

O Claude Code adiciona schemas zod:

import { z } from "zod";

const CreateTodoSchema = z.object({
  title: z.string().min(1, "O título deve ter pelo menos 1 caractere").max(100, "O título não pode ter mais de 100 caracteres"),
});

const UpdateTodoSchema = z.object({
  title: z.string().min(1).max(100).optional(),
  done: z.boolean().optional(),
});

// POST /todos (com validação)
app.post("/todos", async (c) => {
  const body = await c.req.json().catch(() => ({}));
  const result = CreateTodoSchema.safeParse(body);
  if (!result.success) {
    return c.json({ error: result.error.flatten().fieldErrors }, 400);
  }
  const todo: Todo = {
    id: crypto.randomUUID(),
    title: result.data.title,
    done: false,
    createdAt: new Date().toISOString(),
  };
  todos.push(todo);
  return c.json(todo, 201);
});

Verificar erros de validação:

# Criar sem título → deve dar erro
curl -X POST http://localhost:3000/todos \
  -H "Content-Type: application/json" \
  -d '{}'
# → {"error":{"title":["O título deve ter pelo menos 1 caractere"]}}

Step 3: Unificar o Tratamento de Erros

Atualmente, cada endpoint retorna erros em formatos diferentes. Deixe o Claude Code padronizar:

claude -p "
Unifique o tratamento de erros.
- Formato de resposta de erro comum: { error: { code: string, message: string } }
- 404: NOT_FOUND
- 400: VALIDATION_ERROR
- 500: INTERNAL_SERVER_ERROR
Implemente um handler de erro global usando o onError do Hono
"
// Definição do tipo de erro
class AppError extends Error {
  constructor(
    public code: string,
    public message: string,
    public statusCode: number = 400
  ) {
    super(message);
  }
}

// Handler de erro global
app.onError((err, c) => {
  if (err instanceof AppError) {
    return c.json(
      { error: { code: err.code, message: err.message } },
      err.statusCode as any
    );
  }
  console.error(err);
  return c.json(
    { error: { code: "INTERNAL_SERVER_ERROR", message: "Ocorreu um erro inesperado" } },
    500
  );
});

// Uso
app.get("/todos/:id", (c) => {
  const todo = todos.find((t) => t.id === c.req.param("id"));
  if (!todo) throw new AppError("NOT_FOUND", "Todo não encontrado", 404);
  return c.json(todo);
});

Step 4: Gerar Documentação Swagger UI Automaticamente

Depois de construir a API, você precisa de documentação. O Claude Code configura tudo em minutos:

claude -p "
Use @hono/swagger-ui e @hono/zod-openapi para
adicionar Swagger UI em /docs.
Adicione schemas OpenAPI aos endpoints existentes.
"
npm install @hono/swagger-ui @hono/zod-openapi

Depois, acesse http://localhost:3000/docs para ver a documentação da sua API.


O Fluxo de Desenvolvimento de API com Claude Code (Resumo)

Este é o fluxo que uso no dia a dia:

1. Dizer ao Claude Code "Preciso de uma API que faça X"
    ↓
2. Revisar e testar o código gerado
    ↓
3. Iterar: "Corrija isso", "Adicione validação", etc.
    ↓
4. git commit quando os testes passam

Meu primeiro tropeço (experiência real)

Quando construí minha primeira API, pulei o tratamento de erros completamente e tive que adicionar tudo depois — o que levou uma eternidade. Agora simplesmente adiciono “inclua tratamento de erros” no prompt desde o início, e o código já sai sólido de cara. O truque com o Claude Code é dar todos os requisitos de uma vez desde o começo.


3 Armadilhas Comuns

Armadilha 1: Ignorar erros de parsing de JSON

// ❌ Erros aqui passam despercebidos
const body = await c.req.json();

// ✅ Capturar falhas de parsing
const body = await c.req.json().catch(() => null);
if (!body) return c.json({ error: "Invalid JSON" }, 400);

Armadilha 2: Confundir 404 com 400

400: A própria requisição está errada (erro de validação, campo obrigatório faltando)
404: O recurso não existe (ID não encontrado)
422: Formato da requisição correto mas não pode ser processado

Pergunte ao Claude Code “devo retornar 404 ou 400 aqui?” e ele vai dar a resposta certa.

Armadilha 3: Guardar tudo na memória

O código neste guia usa um array na memória para fins de demonstração. Os dados somem quando você reinicia o servidor. Em produção você vai precisar de um banco de dados como PostgreSQL ou MongoDB. Simplesmente diga ao Claude Code “salve isso no SQLite em vez da memória” e ele cuidará da migração.


Próximos Passos

Depois de dominar os fundamentos de REST API, experimente:

PassoO que Fazer
Banco de dadosSQLite → PostgreSQL (com Prisma)
AutenticaçãoAdicionar autenticação com JWT
TestesEscrever testes de API com vitest
DeployPublicar no Vercel / Cloudflare Workers

Para tudo isso, basta dizer ao Claude Code “adicione X” e a base estará pronta em minutos. Construa algo que funcione primeiro — esse é o caminho mais rápido.

Artigos Relacionados

#claude-code #rest-api #beginner #typescript #backend #tutorial

Leve seu fluxo no Claude Code a outro nível

50 modelos de prompt testados em campo, prontos para colar direto no Claude Code.

Grátis

PDF gratuito: Cheatsheet do Claude Code em 5 minutos

Basta informar seu e-mail e enviamos na hora o cheatsheet em uma página A4.

Cuidamos dos seus dados pessoais e nunca enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro apaixonado por Claude Code. Mantém o claudecode-lab.com, uma mídia tech em 10 idiomas com mais de 2.000 páginas.