API Routes no Next.js: como criar endpoints do zero

API Routes no Next.js: como criar endpoints do zero - hero

API Routes no Next.js: como criar endpoints do zero

Índice

Se você trabalha ou está começando com Next.js, em algum momento vai precisar que sua aplicação converse com algum banco de dados, consuma um serviço externo ou devolva dados em formato JSON para o front-end. É exatamente para isso que existem as API Routes: pequenos blocos de código que rodam no servidor e respondem a requisições HTTP, tudo dentro do mesmo projeto em que você já está desenvolvendo as páginas.

A grande vantagem é que você não precisa levantar um servidor Express, configurar rotas em outro projeto nem se preocupar com CORS (mecanismo de segurança que controla quais sites podem chamar sua API) em vários cenários. Com Next.js, você cria um arquivo, exporta uma função e pronto: já tem um endpoint funcionando.

Neste guia, você vai entender o que são API Routes, como o mecanismo de roteamento do Next.js lida com elas, quais métodos HTTP você pode usar e como criar sua primeira rota tanto em JavaScript quanto em TypeScript. Também vamos falar sobre boas práticas, limitações e quando vale a pena considerar outras alternativas.

O que são API Routes no Next.js

O que são API Routes no Next.js - imagem ilustrativa
O que são API Routes no Next.js

API Routes é o recurso do framework Next.js que transforma arquivos dentro da pasta pages/api (no Pages Router, o roteador tradicional do Next.js) ou arquivos route.ts (no App Router, o roteador mais novo baseado em React Server Components) em endpoints HTTP prontos para receber requisições. Cada arquivo vira uma URL e exporta uma função que recebe a requisição e devolve a resposta.

A ideia central é simples: em vez de ter um backend separado, você usa o próprio servidor do Next.js para responder chamadas de API. Isso facilita a vida em projetos menores, MVPs (produto mínimo viável, a versão mais simples de um produto para validar uma ideia) ou quando a lógica de backend é simples o suficiente para caber junto com o front-end.

Como o Next.js cuida do roteamento e do servidor de arquivos estáticos, as API Routes herdam essa mesma filosofia de "convenção sobre configuração": você segue um padrão de pastas e nomes, e o framework faz o resto.

Como o Next.js roteia as requisições

Quando alguém acessa https://seusite.com/api/usuarios, o Next.js procura dentro de pages/api/usuarios.js (ou app/api/usuarios/route.ts, dependendo do roteador) e executa a função exportada. Você não precisa registrar nada em lugar nenhum, basta o arquivo existir.

Esse mesmo mecanismo funciona para arquivos dinâmicos, como [id].js ou [slug].ts, que capturam partes da URL e tornam acessíveis dentro da função. Por exemplo, uma rota em pages/api/produtos/[id].js aceita URLs como /api/produtos/42.

Por que usar API Routes em vez de um backend separado

Há cenários em que essa abordagem brilha:

  • Projetos pequenos e médios em que manter dois códigos separados aumenta a complexidade sem ganho real.
  • Endpoints usados exclusivamente pelo front-end do mesmo projeto.
  • como rotas de autenticação internas.
  • webhooks de provedores de pagamento ou proxies que escondem chaves de API.
  • Protótipos e provas de conceito em que velocidade de entrega importa mais do que escalabilidade extrema.

Por outro lado, quando sua aplicação começa a crescer em complexidade, com integrações múltiplas, regras de negócio pesadas ou necessidade de fila e processamento assíncrono, um backend dedicado em Node.js, NestJS, Python ou outra linguagem costuma ser a melhor escolha.

Diferença entre Pages Router e App Router

É importante entender que existem dois sistemas de roteamento principais no Next.js, e cada um trata as API Routes de um jeito diferente. Pages Router: usa a pasta pages/api/ e arquivos que exportam funções nomeadas como default, recebendo os objetos req (requisição) e res (resposta) do Node.js. App Router: usa a pasta app/api/ e arquivos route.ts (ou route.js) que exportam funções nomeadas pelos métodos HTTP, como GET, POST, PUT, DELETE.

A partir do Next.js 13, o App Router se tornou o padrão recomendado, mas o Pages Router continua funcionando e tem bastante conteúdo na web. Vamos ver como criar sua primeira rota nos dois modelos.

Criando sua primeira API Route no Pages Router

Criando sua primeira API Route no Pages Router - imagem ilustrativa
Criando sua primeira API Route no Pages Router

Vamos começar pelo Pages Router por ser mais simples e didático. A lógica é basicamente: criar um arquivo, exportar uma função e devolver uma resposta.

Estrutura básica de uma rota

Imagine que você quer criar um endpoint que devolve uma lista de usuários em JSON. O arquivo ficaria assim, salvo como pages/api/usuarios.js:

export default function handler(req, res) {
  const usuarios = [
    { id: 1, nome: "Ana" },
    { id: 2, nome: "Bruno" }
  ];

  res.status(200).json(usuarios);
}

Pronto. Ao acessar /api/usuarios, você recebe um JSON com a lista. O objeto req traz informações da requisição (método, cabeçalhos, corpo, parâmetros de URL), e o res é o que você usa para devolver a resposta, definindo o status HTTP e os dados retornados.

Lidando com métodos HTTP diferentes

Em uma API real, você raramente quer que o mesmo endpoint aceite qualquer método sem tratamento. O mais comum é filtrar por método:

export default function handler(req, res) {
  if (req.method === "GET") {
    return res.status(200).json({ mensagem: "Lista de usuários" });
  }

  if (req.method === "POST") {
    const { nome, email } = req.body;
    return res.status(201).json({ id: 3, nome, email });
  }

  res.setHeader("Allow", "GET, POST");
  return res.status(405).json({ erro: "Método não permitido" });
}

Note o status 405 (Method Not Allowed), que é o código HTTP correto para indicar que o método existe no servidor, mas não é aceito naquele recurso. Também definimos o cabeçalho Allow para informar quais métodos são válidos.

Rotas dinâmicas

Se você precisa tratar, por exemplo, a busca de um produto pelo identificador, usa arquivos com colchetes no nome. Crie pages/api/produtos/[id].js:

export default function handler(req, res) {
  const { id } = req.query;

  res.status(200).json({
    id,
    nome: `Produto ${id}`,
    preco: 99.9
  });
}

Agora GET /api/produtos/10 devolve os dados do produto com identificador 10.

Middleware e helpers comuns

Algumas bibliotecas foram pensadas para facilitar a vida com API Routes, especialmente a integração com o Parse Server. As mais conhecidas:

  • next-connect: permite organizar handlers (funções intermediárias que processam requisições antes de chegar ao destino) por método HTTP de forma mais limpa.
  • cors: configura cabeçalhos de CORS quando sua API é chamada por outros domínios.
  • helmet: adiciona cabeçalhos de segurança automáticos.

Um exemplo com next-connect:

import nc from "next-connect";
import cors from "cors";

const handler = nc();
handler.use(cors()).get((req, res) => {
  res.status(200).json({ ok: true });
});

export default handler;

Esse padrão ajuda a manter o arquivo organizado quando você tem vários métodos e middlewares.

Criando API Routes no App Router

Criando API Routes no App Router - imagem ilustrativa
Criando API Routes no App Router

O App Router é o modelo recomendado a partir do Next.js 13 e usa uma abordagem diferente, baseada em convenções do React Server Components.

Estrutura básica com route.ts

Para criar o equivalente da rota /api/usuarios que vimos antes, você cria o arquivo app/api/usuarios/route.ts (ou route.js, se estiver usando JavaScript puro):

import { NextResponse } from "next/server";

export async function GET() {
  const usuarios = [
    { id: 1, nome: "Ana" },
    { id: 2, nome: "Bruno" }
  ];

  return NextResponse.json(usuarios);
}

Perceba que cada método HTTP vira uma função nomeada, e o retorno é direto, sem precisar manipular req e res. Essa abordagem é mais declarativa e fica fácil de ler.

Aceitando requisições POST

Para criar um produto novo a partir de um JSON enviado no corpo da requisição:

import { NextResponse } from "next/server";

export async function POST(request: Request) {
  const corpo = await request.json();
  const { nome, preco } = corpo;

  if (!nome || !preco) {
    return NextResponse.json(
      { erro: "Nome e preço são obrigatórios" },
      { status: 400 }
    );
  }

  return NextResponse.json(
    { id: 10, nome, preco },
    { status: 201 }
  );
}

Aqui usamos o objeto Request padrão da Fetch API (a interface moderna do navegador para requisições HTTP, também disponível no servidor) e NextResponse.json para devolver a resposta.

Rotas dinâmicas no App Router

O princípio é o mesmo, mas os colchetes ficam no nome da pasta. Estrutura app/api/produtos/[id]/route.ts:

export async function GET(
  request: Request,
  { params }: { params: { id: string } }
) {
  return Response.json({
    id: params.id,
    nome: `Produto ${params.id}`,
    preco: 99.9
  });
}

Agora GET /api/produtos/10 devolve os dados do produto com identificador 10.

Middleware nativo do Next.js

Para interceptar requisições antes que cheguem às rotas, o Next.js oferece o arquivo middleware.ts na raiz do projeto. Ele é útil para checagem de autenticação, redirecionamentos e cabeçalhos globais.

Exemplo simples:

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const token = request.cookies.get("token");

  if (!token && request.nextUrl.pathname.startsWith("/api/")) {
    return NextResponse.json(
      { erro: "Não autorizado" },
      { status: 401 }
    );
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/api/:path*"]
};

Esse middleware bloqueia qualquer chamada a /api/* quando não existe o cookie token, devolvendo 401 (Não Autorizado). É um ótimo ponto de partida para proteção de rotas internas.

Métodos HTTP suportados e como usá-los

Métodos HTTP suportados e como usá-los - imagem ilustrativa
Métodos HTTP suportados e como usá-los

Independentemente do roteador escolhido, o conjunto de métodos HTTP disponíveis para API Routes é o mesmo, e cada um tem um papel claro na construção da API. Os mais comuns são:

  • GET: buscar dados (idempotente.
  • ou seja.
  • executa várias vezes produzindo o mesmo resultado).
  • POST: criar um recurso novo.
  • PUT: substituir um recurso existente por completo.
  • PATCH: atualizar parcialmente um recurso.
  • DELETE: remover um recurso.
  • OPTIONS: usado pelo navegador para checar permissões de CORS antes de uma requisição real.

A tabela a seguir resume o uso e os status HTTP esperados em cada caso.

Método Uso comum Status de sucesso Status de erro típico
GET Ler dados 200 404
POST Criar recurso 201 400, 409
PUT Substituir recurso 200 ou 204 400, 404
PATCH Atualização parcial 200 400, 404
DELETE Remover recurso 204 404
OPTIONS Pré-voo de CORS 204 405

Dominar esse vocabulário ajuda a construir APIs previsíveis e fáceis de consumir por outros sistemas.

Boas práticas para API Routes

Criar uma rota que funciona é fácil. Criar uma rota que funciona bem em produção exige atenção a alguns detalhes.

Valide entradas

Nunca confie no que chega pela requisição. Use uma biblioteca como Zod, Yup ou Valibot para validar o corpo (body), os parâmetros de URL (query) e os cabeçalhos. Isso evita que dados malformados cheguem ao seu banco e quebrem a aplicação.

Exemplo com Zod:

import { z } from "zod";

const schema = z.object({
  nome: z.string().min(2),
  email: z.string().email()
});

export async function POST(request: Request) {
  const dados = schema.safeParse(await request.json());

  if (!dados.success) {
    return Response.json(
      { erro: "Dados inválidos", detalhes: dados.error.flatten() },
      { status: 400 }
    );
  }

  return Response.json({ id: 1...dados.data }, { status: 201 });
}

Padronize as respostas de erro

Defina um formato único para erros e use-o em todas as rotas. Por exemplo:

{
  "erro": "Mensagem amigável",
  "codigo": "USUARIO_NAO_ENCONTRADO",
  "detalhes": {}
}

Isso facilita a vida de quem consome a API e simplifica a implementação de logs (registros de eventos) e monitoramento.

Não exponha segredos

Variáveis de ambiente com prefixo NEXT_PUBLIC_ ficam disponíveis no front-end. Para segredos como chaves de banco e tokens de integração, use o prefixo padrão (sem NEXT_PUBLIC_) e mantenha o acesso restrito às API Routes e a outros arquivos de servidor.

Limite tamanho do corpo

Requisições muito grandes podem causar lentidão ou até negação de serviço (ataques em que o invasor sobrecarrega o servidor enviando requisições enormes ou em grande volume). O Next.js aplica limites por padrão, mas vale revisar a documentação ao trabalhar com upload de arquivos ou JSONs pesados.

Use cache quando fizer sentido

Para endpoints que devolvem dados que mudam pouco, é possível usar o cabeçalho Cache-Control ou revalidar rotas com revalidatePath no App Router. Isso reduz a carga no banco e melhora a experiência do usuário.

Exemplos práticos para o dia a dia

A teoria ajuda, mas o que fixa o conteúdo são exemplos reais. Vamos ver três situações comuns que aparecem em praticamente qualquer projeto.

Exemplo 1: endpoint de contato

Recebe dados de um formulário enviado pelo front-end, valida o conteúdo e devolve confirmação.

export async function POST(request: Request) {
  const { nome, email, mensagem } = await request.json();

  if (!nome || !email || !mensagem) {
    return Response.json(
      { erro: "Preencha todos os campos" },
      { status: 400 }
    );
  }

  // Aqui entra o envio de e-mail ou persistência em banco
  console.log("Novo contato", { nome, email, mensagem });

  return Response.json({ ok: true }, { status: 201 });
}

Salvar como app/api/contato/route.ts.

Exemplo 2: proxy para API externa

Às vezes você quer esconder a chave de API de um serviço externo ou aplicar regras próprias antes de responder ao front-end. Crie um proxy (intermediário que repassa e adapta requisições) no Next.js que recebe a chamada, adiciona a chave e repassa.

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const cidade = searchParams.get("cidade");

  const resposta = await fetch(
    `https://api.exemplo.com/clima?cidade=${cidade}&key=${process.env.CHAVE_API}`
  );

  const dados = await resposta.json();

  return Response.json(dados);
}

A chave nunca é exposta ao navegador porque só roda no servidor.

Exemplo 3: integração com banco de dados

Conectando a um banco PostgreSQL usando o Prisma:

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export async function GET() {
  const usuarios = await prisma.usuario.findMany();
  return Response.json(usuarios);
}

Em produção, vale criar uma única instância do Prisma para evitar reabrir conexão a cada requisição. O Next.js oferece um padrão recomendado para isso chamado "singleton" (instância única compartilhada).

Limitações e quando considerar alternativas

API Routes resolvem bem a maioria dos casos comuns, mas é justo listar onde elas começam a engessar. Funções serverless (executadas sob demanda em plataformas de nuvem, em vez de em servidores fixos) têm tempo limite de execução. Na Vercel, o limite padrão para planos gratuitos é 10 segundos no plano Hobby e 60 segundos no plano Pro para API Routes no Pages Router. Para o App Router, os limites são parecidos. Tarefas longas precisam rodar fora. Em plataformas como Vercel, Cold Start (primeira execução após período ocioso) pode adicionar latência nas primeiras requisições após muito tempo sem uso. Streaming de respostas (envio de dados em pedaços, em vez de tudo de uma vez) é mais limitado do que em servidores Express ou Fastify. Para envio de dados em tempo real ou downloads longos, considere outras soluções. Tarefas pesadas com uso intenso de CPU podem exigir ajuste de plano ou mudança para uma plataforma com runtime (ambiente de execução) mais robusto.

Se você esbarrar nesses limites, opções a considerar incluem Express, Fastify, NestJS, Hono, ou mesmo workers em Python, Ruby ou Go, integrados via API separada.

Como testar API Routes

Testar é parte essencial do trabalho. Existem três camadas principais que você pode usar.

Testes manuais com curl ou ferramentas visuais

Para checagens rápidas, basta usar curl no terminal ou ferramentas como Postman e Insomnia. Exemplo:

curl http://localhost:3000/api/usuarios

Testes automatizados com Jest e Supertest

Para projetos maiores, vale criar testes que simulam requisições. Bibliotecas como Jest, Vitest, Supertest ou node-mock-http facilitam isso.

Logs estruturados

Adicionar logs (registros de eventos do sistema) em pontos-chave da rota ajuda a investigar bugs. Bibliotecas como pino e winston produzem logs estruturados em JSON, fáceis de enviar para serviços como Datadog ou Sentry.

Perguntas Frequentes (FAQ)

API Routes substituem um backend tradicional?

Elas substituem em projetos pequenos e médios, onde a maioria das chamadas é feita pelo próprio front-end do Next.js. Para sistemas com regras de negócio complexas, integrações com vários sistemas ou necessidade de filas e processamento assíncrono, um backend dedicado ainda é a melhor escolha.

Qual a diferença entre Pages Router e App Router para API Routes?

No Pages Router, você cria arquivos em pages/api/ que exportam uma função padrão recebendo req e res. No App Router, você cria arquivos route.ts em app/api/ que exportam funções nomeadas pelo método HTTP, como GET e POST, retornando objetos Response ou NextResponse.

Posso usar TypeScript nas API Routes?

Sim. Tanto no Pages Router quanto no App Router, basta criar arquivos com extensão .ts ou .tsx e configurar o tsconfig.json. No App Router, a tipagem dos parâmetros e do retorno tende a ser mais ergonômica por usar os padrões da Web, como Request e Response.

Como proteger API Routes contra acessos não autorizados?

As opções mais comuns incluem checar tokens JWT (token assinado que carrega informações de autenticação) ou de sessão no cabeçalho da requisição, validar a origem via cabeçalhos CORS, usar o middleware.ts para bloquear rotas e aplicar rate limit (limite de requisições por intervalo de tempo) via bibliotecas como Upstash Ratelimit.

Existe limite de tamanho para o corpo da requisição?

Sim. Por padrão, o Next.js aplica limites razoáveis para evitar abuse. Para upload de arquivos grandes, é comum configurar tamanho específico ou enviar o arquivo diretamente para um serviço de storage como S3, Cloudflare R2 ou Supabase Storage, recebendo apenas a URL no corpo da requisição.

Conclusão

API Routes são um dos recursos mais democráticos do Next.js. Com pouco código, você coloca um endpoint no ar, recebe dados, conecta a bancos e integra com serviços externos, tudo dentro do mesmo projeto em que está construindo as páginas. Para produtos digitais em validação, sites institucionais, MVPs e painéis administrativos internos, essa abordagem economiza tempo e reduz a superfície de manutenção.

Agora, vale destacar que, apesar da simplicidade aparente, existem decisões que pesam no resultado: escolher entre Pages Router e App Router, validar entradas, proteger rotas e estruturar respostas de erro são detalhes que evitam dor de cabeça quando o projeto cresce.

Se você precisa de ajuda para colocar isso em prática ou quer construir uma aplicação mais robusta usando Next.js, a Baita Site tem uma equipe especializada em sites, e-commerce, sistemas e inteligência artificial, com domínio total de WordPress e do ecossistema JavaScript moderno. Fale com a gente e veja como podemos acelerar o seu projeto.

Este conteúdo tem caráter informativo. Decisões técnicas devem ser tomadas com profissional especializado.

Referências consultadas, Documentação oficial do Next.js sobre API Routes no Pages Router

https://nextjs.org/docs/pages/building-your-application/routing/api-routes, Documentação oficial do Next.js sobre Route Handlers no App Router: https://nextjs.org/docs/app/building-your-application/routing/route-handlers, Documentação do Next.js sobre Middleware: https://nextjs.org/docs/app/building-your-application/routing/middleware, Repositório da biblioteca next-connect no GitHub: https://github.com/hoangvvo/next-connect, Artigo sobre boas práticas em APIs REST na documentação do MDN Web Docs: https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Methods

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.

WhatsApp (47) 99905-6989  |  WhatsApp (47) 99198-5289

Veja tambem

Perguntas Frequentes (FAQ)

1. API Routes substituem um backend tradicional?

Elas substituem em projetos pequenos e médios, onde a maioria das chamadas é feitas pelo próprio front-end do Next.js. Para sistemas com regras de negócio complexas, várias integrações ou necessidade de filas e processamento assíncrono, um backend dedicado ainda é a melhor escolha.

2. Qual a diferença entre Pages Router e App Router para API Routes?

No Pages Router, você cria arquivos em pages/api/ que exportam uma função padrão recebendo req e res. No App Router, você cria arquivos route.ts em app/api/ que exportam funções nomeadas pelo método HTTP, como GET e POST, retornando objetos Response ou NextResponse.

3. Posso usar TypeScript nas API Routes?

Sim. Tanto no Pages Router quanto no App Router, basta criar arquivos com extensão .ts ou .tsx e configurar o tsconfig.json. No App Router, a tipagem tende a ser mais ergonômica por usar os padrões da Web, como Request e Response.

4. Como proteger API Routes contra acessos não autorizados?

As opções mais comuns incluem checar tokens JWT ou de sessão no cabeçalho da requisição, validar a origem via cabeçalhos CORS, usar o middleware.ts para bloquear rotas e aplicar rate limit por meio de bibliotecas como Upstash Ratelimit.

5. Existe limite de tamanho para o corpo da requisição?

Sim. Por padrão, o Next.js aplica limites razoáveis para evitar abuso. Para upload de arquivos grandes, é comum configurar tamanho específico ou enviar o arquivo diretamente para um serviço de storage como S3, Cloudflare R2 ou Supabase Storage, recebendo apenas a URL no corpo da requisição.

Gostaria de receber mais novidades?

Nossas publicações serão sempre voltadas ao mundo do marketing digital, design e criação de sites. Você não será importunado com assuntos que não são do seu interesse!

Compartilhe com seus familiáres e amigos!

Baita Site

Desenvolvemos soluções completas em Marketing Digital para o seu o seu negócio.

Contate-nos, solicite um orçamento, teremos o maior prazer em lhe ajudar!

baitasite@baitasite.com.br
+55 (47) 3360-7843
CNPJ 22.130.607/0001-29

Porque nos escolher?

É algo muito simples! Temos anos e uma vasta experiência com internet, nosso preço é justo e nosso trabalho profissional.

São anos de estudo e dedicação para adquirir o conhecimento necessário para executar projetos com qualidade e eficiência

Onde Estamos

Estamos localizados em um aconchegante home office em Itapema, litoral de Santa Catarina. Você está longe? Não tem problema!

Somos feras em atendimento e suporte a distância, por WhatsApp e pela internet!

Copyright 2020 - Baita Site - Criação de Sites em Itapema. Site feito com amor por nós mesmos!