API Routes no Next.js: como criar endpoints profissionais
Índice
ToggleSe você já precisou buscar dados de um banco, validar um formulário ou enviar um e-mail a partir de uma aplicação Next.js, em algum momento precisou de um endpoint de backend. Antigamente, isso significava subir um servidor Express separado, configurar CORS, lidar com deploy em dois lugares diferentes e rezar para que tudo ficasse em sincronia. Com a evolução do Next.js, tudo isso ficou mais simples: agora dá para criar rotas de API dentro do próprio projeto, com a mesma DX (experiência de desenvolvedor) que você já tem no front-end. É exatamente isso que vamos explorar aqui, com calma, do básico ao intermediário.
O que são API Routes no Next.js

API Routes são, em resumo, pequenos trechos de código que respondem a requisições HTTP (GET, POST, PUT, DELETE, PATCH) sem que você precise sair do seu projeto Next.js. Em vez de subir um servidor Node à parte, você cria arquivos dentro do seu próprio app e o Next.js se encarrega de transformá-los em endpoints reais, prontos para receber requisições via fetch, axios, curl ou qualquer cliente HTTP.
Esse modelo ganhou força principalmente por dois motivos: primeiro, porque elimina a complexidade de manter dois repositórios ou dois serviços em sincronia; segundo, porque o Next.js cuida de detalhes chatos, como parsing de JSON, suporte a TypeScript, hot reload durante o desenvolvimento e integração nativa com o front-end. Para um time pequeno, uma startup ou um freelancer, isso é ouro.
Vale destacar também que, antes da versão 13, as API Routes eram criadas dentro da pasta pages/api. A partir do Next.js 13, com a chegada do App Router (pasta app), a recomendação oficial passou a ser criar os endpoints dentro de app/api, usando Route Handlers (arquivos route.ts ou route.js). O modelo antigo continua funcionando, mas é considerado legado. Ao longo deste artigo, vamos focar no modelo atual, com exemplos práticos nos dois formatos quando fizer sentido.
Criando sua primeira API Route com App Router

Vamos colocar a mão na massa. Para criar uma API Route no App Router, você precisa apenas de um arquivo chamado route.ts (TypeScript) ou route.js (JavaScript) dentro de uma pasta api. Essa pasta pode ficar diretamente em app/api ou em qualquer subdiretório que você queira, e o caminho do arquivo vira o caminho do endpoint.
Por exemplo, um arquivo em app/api/hello/route.ts será acessível em /api/hello quando o servidor estiver rodando. A estrutura básica de uma rota responde a um verbo HTTP exportando uma função nomeada. Veja um exemplo simples:
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({ mensagem: "Olá, mundo das API Routes!" });
}
Esse pequeno trecho já cria um endpoint funcional que, ao receber uma requisição GET em /api/hello, devolve um JSON com a mensagem. Para testar, basta rodar npm run dev no terminal, abrir o navegador em http://localhost:3000/api/hello ou usar ferramentas como Postman, Insomnia ou o próprio curl no terminal.
O NextResponse.json() é um helper do Next.js que cuida da formatação correta da resposta, definindo automaticamente o header Content-Type como application/json e convertendo o objeto em uma string JSON válida. Existe também o NextRequest, que estende o objeto Request padrão da Fetch API com informações úteis, como os cookies e os headers da requisição.
Respondendo a diferentes verbos HTTP

Na prática, uma API Route raramente responde apenas a GET. Você geralmente precisa lidar com POST para criar dados, PUT ou PATCH para atualizar, DELETE para remover. Cada verbo HTTP é uma função exportada diferente dentro do mesmo arquivo route.ts. O Next.js cuida de rotear a requisição para a função correta com base no método.
Veja um exemplo completo de CRUD básico (Create, Read, Update, Delete) em memória, usando um array simples como base de dados temporária:
import { NextRequest, NextResponse } from "next/server";
type Produto = { id: number; nome: string; preco: number };
const produtos: Produto[] = [
{ id: 1, nome: "Café", preco: 12.5 },
{ id: 2, nome: "Pão de queijo", preco: 6 },
];
export async function GET() {
return NextResponse.json(produtos);
}
export async function POST(req: NextRequest) {
const corpo = await req.json();
const novoProduto: Produto = {
id: Date.now(),
nome: corpo.nome,
preco: Number(corpo.preco),
};
produtos.push(novoProduto);
return NextResponse.json(novoProduto, { status: 201 });
}
Perceba alguns detalhes importantes:
- A função recebe um parâmetro
req: NextRequest. - que dá acesso ao corpo.
- headers.
- cookies e URL.
- O
await req.json()faz o parsing do corpo da requisição (esperando um JSON válido). - O segundo argumento de
NextResponse.jsonaceita um objeto de opções. - incluindo o
status. - que segue o padrão HTTP (201 para Created.
- 204 para No Content.
- e assim por diante).
Para PUT e DELETE, a lógica segue o mesmo princípio: você lê o corpo ou os parâmetros, aplica a transformação e devolve a resposta adequada.
Parâmetros dinâmicos e captura de query strings

Em quase toda API real, você vai precisar lidar com parâmetros dinâmicos, como o ID de um produto em uma URL do tipo /api/produtos/123. No App Router, isso é resolvido com segmentos dinâmicos, da mesma forma que você faz com páginas. Basta criar uma pasta com o nome entre colchetes.
Por exemplo, para criar o endpoint /api/produtos/[id], você cria o arquivo app/api/produtos/[id]/route.ts. Dentro dele, o parâmetro dinâmico é acessado como o segundo argumento da função handler:
import { NextRequest, NextResponse } from "next/server";
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
return NextResponse.json({ idRecebido: id, encontrado: true });
}
Atenção a um detalhe que pega muita gente desavisada: a partir das versões mais recentes do Next.js (13.4 em diante, com o novo App Router estável), params virou uma Promise. Por isso, é necessário usar await params antes de acessar as propriedades. Se você está começando um projeto novo, isso já vai vir assim por padrão. Em projetos legados, você pode encontrar a versão síncrona.
Para capturar query strings (parâmetros depois do ? na URL), como /api/produtos?categoria=bebidas, basta usar req.nextUrl.searchParams, que é uma instância de URLSearchParams:
export async function GET(req: NextRequest) {
const categoria = req.nextUrl.searchParams.get("categoria");
return NextResponse.json({ categoriaRecebida: categoria });
}
Esse padrão é muito útil para filtros, ordenações e paginação sem precisar criar rotas adicionais.
Middleware e validação de dados
Uma API profissional não confia em dados que chegam do cliente. Por isso, validação e autenticação são itens obrigatórios. No App Router, você tem duas grandes ferramentas para isso: o middleware.ts (executado antes da requisição chegar ao endpoint) e a validação dentro do próprio handler.
O middleware.ts fica na raiz do projeto (ou em src/, se você usa essa estrutura) e permite interceptar requisições em rotas específicas, ideal para checagens de autenticação, rate limiting e redirecionamentos. Veja um exemplo simples que bloqueia chamadas a /api/admin sem um token:
import { NextRequest, NextResponse } from "next/server";
export function middleware(req: NextRequest) {
const token = req.headers.get("authorization");
if (!token) {
return NextResponse.json({ erro: "Não autorizado" }, { status: 401 });
}
return NextResponse.next();
}
export const config = {
matcher: "/api/admin/:path*",
};
Para validação do corpo da requisição, bibliotecas como Zod, Yup ou Valibot resolvem bem. Zod é provavelmente a mais popular no momento, por ser leve, ter inferência de tipos excelente e uma sintaxe muito clara:
import { z } from "zod";
const schemaProduto = z.object({
nome: z.string().min(2),
preco: z.number().positive(),
});
export async function POST(req: NextRequest) {
const corpo = await req.json();
const validacao = schemaProduto.safeParse(corpo);
if (!validacao.success) {
return NextResponse.json(
{ erro: "Dados inválidos", detalhes: validacao.error.flatten() },
{ status: 400 }
);
}
// continua o fluxo com validacao.data...
}
Esse padrão de retornar 400 (Bad Request) com uma mensagem clara é o que separa uma API amadora de uma API profissional. Em sistemas maiores, vale considerar também retornos profissionais e padronizados para 401, 403, 404, 409, 422 e 500.
Headers, cookies e respostas customizadas
Nem toda resposta precisa ser JSON. Às vezes você quer devolver um arquivo, um texto simples ou configurar headers específicos, como cookies de sessão. O NextResponse permite fazer tudo isso de forma simples.
Para definir cookies:
export async function POST() {
const resposta = NextResponse.json({ ok: true });
resposta.cookies.set("sessao", "abc123", {
httpOnly: true,
secure: true,
sameSite: "lax",
path: "/",
});
return resposta;
}
Para ler cookies que vieram na requisição, você usa req.cookies.get("nome"). Para headers customizados, basta usar res.headers.set("X-Meu-Header", "valor"). Esses recursos são especialmente úteis em fluxos de autenticação, quando você precisa criar e validar tokens JWT, por exemplo.
Outro detalhe importante: o tempo de execução das rotas. No Next.js, especialmente quando você usa Vercel, o tempo de execução padrão é o Node.js, mas você pode trocar para Edge Runtime em rotas que precisam de baixa latência global. Para isso, basta exportar uma constante runtime:
export const runtime = "edge";
Vale lembrar que o Edge Runtime tem algumas limitações (acesso ao sistema de arquivos, por exemplo), então use com critério.
API Routes vs Pages Router: comparativo rápido
Mesmo com a chegada do App Router, muita gente ainda mantém código legado no Pages Router. Para quem está migrando ou decidindo qual modelo usar, vale a pena comparar os dois formatos lado a lado.
| Aspecto | Pages Router (legado) | App Router (atual) |
|---|---|---|
| Pasta das rotas | pages/api |
app/api |
| Nome do arquivo | Qualquer nome (produtos.ts) |
Sempre route.ts ou route.js |
| Métodos HTTP | Export default de um handler | Exports nomeadas (GET, POST, etc.) |
| Resposta | res.status(200).json(...) |
NextResponse.json(...) |
| Suporte a Streaming | Limitado | Nativo (Web Streams) |
| Server Actions | Não | Sim |
| Recomendação oficial | Legado | Atual |
Se você está começando um projeto novo em 2026, vá direto para o App Router. Se está mantendo um projeto antigo, dá para migrar aos poucos, pois os dois modelos convivem bem no mesmo repositório.
Casos de uso comuns para API Routes no Next.js
Saber criar uma rota é importante, mas saber quando criar é igualmente relevante. Nem sempre você precisa de uma API Route tradicional. Listar quatro situações em que ela brilha:
- Formulários de contato e captação de leads: você recebe os dados.
- valida.
- salva em um banco ou envia por e-mail.
- sem expor a lógica para o cliente.
- Webhooks: integrações com Stripe.
- Hotmart.
- Mercado Pago.
- GitHub e outros serviços geralmente usam webhooks.
- que são.
- na prática.
- endpoints HTTP esperando dados.
- Autenticação customizada: login com e-mail e senha.
- geração de tokens JWT.
- refresh tokens.
- logout.
- tudo isso pode ser feito em API Routes quando você não quer (ou não pode) usar uma solução como NextAuth ou Clerk.
- Proxy entre front-end e serviços externos: em vez de expor a chave de uma API externa para o navegador.
- você cria um endpoint no Next.js que faz a chamada e devolve apenas os dados necessários.
Por outro lado, em fluxos puramente internos (mudanças de banco a partir de formulários, por exemplo), as Server Actions podem ser uma alternativa ainda melhor, com menos código e mais segurança de tipos.
Boas práticas e armadilhas comuns
Criar API Routes funciona até melhor em qualquer parte. Mas existem armadilhas que aparecem quando o sistema começa a crescer. Listar quatro pontos de atenção que fazem diferença em produção:
- Sempre valide entradas. Nunca confie no corpo da requisição.
- nos headers ou nos cookies. Use Zod ou similar.
- Não coloque segredos no código. Use variáveis de ambiente (
process.env) e configure corretamente no seu provedor de hospedagem. - Cuidado com CORS. Se a sua API for chamada por outro domínio.
- configure os headers adequados.
- preferencialmente dentro de um middleware central.
- Pense em rate limiting. Endpoints públicos.
- sem limite de chamadas.
- são alvo fácil para abuso. Bibliotecas como Upstash Ratelimit ou soluções em nível de CDN resolvem bem.
Além desses pontos, outra boa prática é manter os handlers magros (com pouca lógica de negócio), delegando o trabalho pesado para funções em camadas separadas (services, repositories). Isso facilita testes, manutenção e troca de banco de dados no futuro.
Diferença entre API Routes e Server Actions
Muita gente confunde os dois conceitos, então vale separar com clareza. API Routes são endpoints HTTP que podem ser consumidos por qualquer cliente: navegador, app mobile, outra API. Server Actions são funções do servidor invocadas diretamente pelo front-end Next.js, sem a necessidade de uma chamada HTTP explícita.
Em 2026, com o App Router maduro, a recomendação geral é:
- Use Server Actions quando a chamada é exclusiva do front-end Next.js e envolve mutações de dados (formulários.
- botões.
- etc.).
- Use API Routes quando você precisa expor um endpoint para clientes externos ou quando quer manter compatibilidade com integrações já existentes.
As duas abordagens convivem no mesmo projeto e podem ser usadas conforme o contexto.
Leitura complementar
Para quem quer se aprofundar no tema, vale explorar alguns caminhos:
- A documentação oficial do Next.js.
- sempre a fonte mais confiável e detalhada.
- O blog do oficial Next.js.
- com anúncios de novas funcionalidades e exemplos da equipe.
- Repositórios no GitHub com projetos open source que usam Next.js.
- que são ótimos para ver padrões reais em produção.
- Comunidades como o Reddit.
- o Stack Overflow e o Discord do Next.js.
- onde dúvidas específicas costumam ser respondidas rapidamente.
Esse conjunto de fontes é uma base sólida para continuar evoluindo, mesmo depois de ler este guia.
Perguntas Frequentes (FAQ)
O que são API Routes no Next.js?
São arquivos especiais dentro do projeto Next.js que viram endpoints HTTP automaticamente. Você cria um arquivo route.ts na pasta app/api e ele já responde a requisições em /api/..., sem precisar de um servidor separado.
Qual a diferença entre Pages Router e App Router para API Routes?
No Pages Router, os arquivos ficam em pages/api e exportam um handler default. No App Router, ficam em app/api com nome route.ts e exportam funções nomeadas por verbo HTTP (GET, POST, etc.). O App Router é o modelo atual e recomendado.
Posso usar TypeScript nas API Routes?
Sim, e é o padrão recomendado. Basta criar o arquivo com extensão .ts ou .tsx e usar a tipagem do Next.js (NextRequest, NextResponse) para ter autocomplete e segurança de tipos.
API Routes funcionam com banco de dados?
Sim. Dentro do handler, você pode usar qualquer cliente de banco, como Prisma, Drizzle, Supabase ou o driver nativo do PostgreSQL, MySQL ou MongoDB. Basta instanciar a conexão dentro ou fora da função (preferencialmente fora, para reaproveitar a conexão).
Quando usar Server Actions em vez de API Routes?
Use Server Actions quando a chamada vier exclusivamente do front-end Next.js (formulários, botões, mutações internas). Use API Routes quando o endpoint precisa ser consumido por outros clientes, como apps mobile, integrações externas ou webhooks.
Conclusão
API Routes no Next.js são uma das funcionalidades mais úteis e, ao mesmo tempo, mais subestimadas do framework. Para quem vem do mundo de front-end, é a porta de entrada para o back-end sem precisar aprender um framework novo. Para quem já é do back-end, é uma forma de unificar a stack e reduzir o overhead de manter dois serviços.
O ponto-chave é começar pequeno: crie uma rota simples, faça um GET retornar um JSON, depois evolua para POST com validação, em seguida adicione autenticação, e assim por diante. Com o tempo, você naturalmente vai formando uma arquitetura sólida, com handlers magros, validação rigorosa e separação clara de responsabilidades.
Se você precisa de ajuda para colocar isso em prática em um projeto real, a Baita Site tem uma equipe especializada em sites, e-commerce, sistemas e inteligência artificial, com domínio total de WordPress e Next.js. Fale com a gente e veja como podemos acelerar o seu projeto.
Referências consultadas, Documentação oficial do Next.js sobre Route Handlers
https://nextjs.org/docs/app/building-your-application/routing/route-handlers, Documentação oficial do Next.js sobre Middleware: https://nextjs.org/docs/app/building-your-application/routing/middleware, Blog do oficial Next.js: https://nextjs.org/blog, Guia da Vercel sobre Edge Runtime: https://vercel.com/docs/functions/edge-functions, Documentação da biblioteca Zod para validação de dados: https://zod.dev
Quer ajuda para colocar isso em pratica?
A Baita Site trabalha com sites, e-commerce, sistemas e IA. Quem prefere resolver com acompanhamento, sem ter que virar especialista em tudo, costuma procurar esse tipo de suporte.
Perguntas Frequentes (FAQ)
1. O que são API Routes no Next.js?
São arquivos especiais dentro do projeto Next.js que viram endpoints HTTP automaticamente. Basta criar um arquivo route.ts na pasta app/api e ele já responde a requisições em /api/… sem precisar de um servidor separado.
2. Qual a diferença entre Pages Router e App Router para API Routes?
No Pages Router, os arquivos ficam em pages/api e exportam um handler default. No App Router, ficam em app/api com nome route.ts e exportam funções nomeadas por verbo HTTP (GET, POST, etc.). O App Router é o modelo atual e recomendado.
3. Posso usar TypeScript nas API Routes?
Sim, e é o padrão recomendado. Basta criar o arquivo com extensão .ts e usar a tipagem do Next.js (NextRequest, NextResponse) para ter autocomplete e segurança de tipos em todo o código.
4. API Routes funcionam com banco de dados?
Sim. Dentro do handler, você pode usar qualquer cliente de banco, como Prisma, Drizzle, Supabase ou o driver nativo do PostgreSQL, MySQL ou MongoDB, bastando inicializar a conexão uma vez e reutilizar.
5. Quando usar Server Actions em vez de API Routes?
Use Server Actions quando a chamada vier exclusivamente do front-end Next.js (formulários, botões, mutações internas). Use API Routes quando o endpoint precisa ser consumido por outros clientes, como apps mobile, integrações externas ou webhooks.