# Como integrar a API de CPF em uma aplicação Next.js (App Router)

> Aprenda a integrar a API de consulta de CPF em uma aplicação Next.js com App Router, Server Components e Route Handlers.

**Publicado:** 30/11/2024
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-integrar-api-cpf-nextjs-app-router

---


Para integrar a API de CPF da CPFHub.io em uma aplicação Next.js com App Router, crie um Route Handler que consulta o endpoint `GET https://api.cpfhub.io/cpf/{CPF}` com o header `x-api-key` diretamente no servidor, mantendo a chave de API protegida e fora do bundle do cliente. Server Components podem buscar dados sem expor credenciais, enquanto Client Components interagem via esse Route Handler interno.

## Introdução

O Next.js com App Router trouxe uma nova forma de construir aplicações React com Server Components, Route Handlers e streaming. Integrar a API de consulta de CPF do CPFHub.io nesse novo paradigma permite manter a chave de API segura no servidor enquanto oferece uma experiência de usuário fluida.

---

## Configurando o projeto

Crie um projeto Next.js e configure as variáveis de ambiente:

```javascript
// .env.local
CPFHUB_API_KEY=SUA_API_KEY
CPFHUB_BASE_URL=https://api.cpfhub.io
```

A chave de API ficará protegida no servidor, sem ser exposta ao navegador. Variáveis sem o prefixo `NEXT_PUBLIC_` são acessíveis apenas no lado do servidor.

| Variável | Lado | Acessível no Browser |
|---|---|---|
| `CPFHUB_API_KEY` | Servidor | Não |
| `CPFHUB_BASE_URL` | Servidor | Não |
| `NEXT_PUBLIC_*` | Cliente | Sim |

---

## Criando o Route Handler

O Route Handler substitui as antigas API Routes no App Router. Crie um endpoint para consulta de CPF:

```javascript
// app/api/cpf/[cpf]/route.js

export async function GET(request, { params }) {
 const { cpf } = await params;
 const cpfLimpo = cpf.replace(/\D/g, '');

 if (cpfLimpo.length !== 11) {
 return Response.json(
 { success: false, message: 'CPF deve conter 11 dígitos' },
 { status: 400 }
 );
 }

 try {
 const response = await fetch(
 `${process.env.CPFHUB_BASE_URL}/cpf/${cpfLimpo}`,
 {
 headers: {
 'x-api-key': process.env.CPFHUB_API_KEY,
 'Content-Type': 'application/json',
 },
 next: { revalidate: 600 },
 }
 );

 if (!response.ok) {
 return Response.json(
 { success: false, message: 'CPF não encontrado' },
 { status: response.status }
 );
 }

 const data = await response.json();
 return Response.json(data);
 } catch (error) {
 return Response.json(
 { success: false, message: 'Erro ao consultar API externa' },
 { status: 502 }
 );
 }
}
```

---

## Função de consulta no servidor

Crie uma função utilitária para consultar a API diretamente do servidor, sem passar pelo Route Handler:

```javascript
// lib/cpf-api.js

export async function consultarCpf(cpf) {
 const cpfLimpo = cpf.replace(/\D/g, '');

 const response = await fetch(
 `${process.env.CPFHUB_BASE_URL}/cpf/${cpfLimpo}`,
 {
 headers: {
 'x-api-key': process.env.CPFHUB_API_KEY,
 },
 next: { revalidate: 600 },
 }
 );

 if (!response.ok) {
 throw new Error(`Erro ${response.status}: CPF não encontrado`);
 }

 const resultado = await response.json();
 return resultado.data;
}

export function validarFormatoCpf(cpf) {
 const cpfLimpo = cpf.replace(/\D/g, '');

 if (cpfLimpo.length !== 11) return false;
 if (/^(\d)\1{10}$/.test(cpfLimpo)) return false;

 let soma = 0;
 for (let i = 0; i < 9; i++) {
 soma += parseInt(cpfLimpo[i]) * (10 - i);
 }
 let d1 = soma % 11 < 2 ? 0 : 11 - (soma % 11);

 soma = 0;
 for (let i = 0; i < 10; i++) {
 soma += parseInt(cpfLimpo[i]) * (11 - i);
 }
 let d2 = soma % 11 < 2 ? 0 : 11 - (soma % 11);

 return parseInt(cpfLimpo[9]) === d1 && parseInt(cpfLimpo[10]) === d2;
}
```

---

## Server Component para exibição

Crie um Server Component que busca e exibe os dados do CPF no servidor:

```jsx
// app/cpf/[cpf]/page.jsx

import { consultarCpf } from '@/lib/cpf-api';
import { notFound } from 'next/navigation';

export async function generateMetadata({ params }) {
 const { cpf } = await params;
 return {
 title: `Consulta CPF ${cpf} | CPFHub`,
 };
}

export default async function CpfPage({ params }) {
 const { cpf } = await params;

 let dados;
 try {
 dados = await consultarCpf(cpf);
 } catch (error) {
 notFound();
 }

 return (
 <div className="max-w-2xl mx-auto p-6">
 <h1 className="text-2xl font-bold mb-6">Resultado da Consulta</h1>

 <div className="bg-white shadow rounded-lg p-6">
 <dl className="grid grid-cols-2 gap-4">
 <div>
 <dt className="text-sm text-gray-500">Nome</dt>
 <dd className="text-lg font-medium">{dados.name}</dd>
 </div>
 <div>
 <dt className="text-sm text-gray-500">CPF</dt>
 <dd className="text-lg font-medium">{dados.cpf}</dd>
 </div>
 <div>
 <dt className="text-sm text-gray-500">Data de Nascimento</dt>
 <dd className="text-lg font-medium">{dados.birthDate}</dd>
 </div>
 <div>
 <dt className="text-sm text-gray-500">Genero</dt>
 <dd className="text-lg font-medium">{dados.gender}</dd>
 </div>
 </dl>
 </div>
 </div>
 );
}
```

---

## Client Component para busca interativa

Para interatividade, crie um Client Component que chama o Route Handler:

```jsx
// components/CpfSearch.jsx
'use client';

import { useState } from 'react';

export default function CpfSearch() {
 const [cpf, setCpf] = useState('');
 const [resultado, setResultado] = useState(null);
 const [loading, setLoading] = useState(false);
 const [erro, setErro] = useState(null);

 const handleSubmit = async (e) => {
 e.preventDefault();
 setLoading(true);
 setErro(null);
 setResultado(null);

 try {
 const response = await fetch(`/api/cpf/${cpf}`);
 const data = await response.json();

 if (data.success) {
 setResultado(data.data);
 } else {
 setErro(data.message);
 }
 } catch {
 setErro('Erro ao consultar CPF');
 } finally {
 setLoading(false);
 }
 };

 return (
 <div className="max-w-md mx-auto">
 <form onSubmit={handleSubmit} className="space-y-4">
 <input
 type="text"
 value={cpf}
 onChange={(e) => setCpf(e.target.value)}
 placeholder="Digite o CPF"
 maxLength={14}
 className="w-full p-3 border rounded"
 />
 <button
 type="submit"
 disabled={loading}
 className="w-full p-3 bg-blue-600 text-white rounded"
 >
 {loading ? 'Consultando...' : 'Consultar CPF'}
 </button>
 </form>

 {resultado && (
 <div className="mt-4 p-4 bg-green-50 rounded">
 <p><strong>Nome:</strong> {resultado.name}</p>
 <p><strong>CPF:</strong> {resultado.cpf}</p>
 <p><strong>Nascimento:</strong> {resultado.birthDate}</p>
 </div>
 )}

 {erro && (
 <div className="mt-4 p-4 bg-red-50 text-red-700 rounded">{erro}</div>
 )}
 </div>
 );
}
```

---

## Perguntas frequentes

### Por que usar um Route Handler em vez de chamar a API de CPF diretamente do Client Component?

Chamar a API de CPF diretamente do cliente exigiria expor a `x-api-key` no bundle JavaScript, tornando-a visível para qualquer usuário que inspecionasse o código. O Route Handler executa no servidor do Next.js, mantendo a chave de API em variável de ambiente protegida e nunca exposta ao navegador.

### O que é `next: { revalidate: 600 }` e por que usá-lo nas chamadas à API de CPF?

É a diretiva de revalidação do cache do Next.js: a resposta ficará em cache por 600 segundos (10 minutos) antes de ser buscada novamente. Como os dados cadastrais de CPF raramente mudam, o cache reduz o número de chamadas à API e melhora a performance — sem impactar a precisão dos dados para o usuário.

### Como lidar com erros quando a API de CPF retorna CPF não encontrado?

A API da CPFHub.io retorna `{ "success": false }` quando o CPF não é localizado na base. No Route Handler, verifique `response.ok` e o campo `success` antes de retornar os dados ao cliente. Nunca interprete um CPF não encontrado como erro fatal: apresente uma mensagem clara ao usuário e permita nova tentativa.

### A API da CPFHub.io bloqueia requisições ao atingir o limite do plano?

Não. A API da CPFHub.io nunca retorna erro 429 nem bloqueia requisições. Ao ultrapassar o limite mensal (50 consultas no plano gratuito ou 1.000 no Pro), as consultas extras são cobradas automaticamente a R$0,15 cada. Consulte [nextjs.org/docs/app/building-your-application/routing/route-handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) para detalhes sobre Route Handlers e boas práticas de uso.

### Leia também

- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [SLA de API de CPF: níveis de disponibilidade e o que exigir do seu provedor](https://cpfhub.io/blog/sla-api-cpf-niveis-disponibilidade)
- [API de CPF grátis para desenvolvedores: como começar em 5 minutos](https://cpfhub.io/blog/api-cpf-gratis-desenvolvedores-comecar-5-minutos)
- [10 erros mais comuns ao integrar uma API de CPF e como evitá-los](https://cpfhub.io/blog/10-erros-mais-comuns-ao-integrar-uma-api-de-cpf)

---

## Conclusão

O Next.js com App Router oferece a combinação ideal de segurança e performance para integrar a API de CPF. Server Components buscam dados sem expor chaves de API, Route Handlers criam endpoints seguros e Client Components fornecem interatividade. A integração completa — Route Handler, função utilitária e componente de busca — pode ser implementada em menos de 30 minutos.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/) — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a integrar consultas de CPF na sua aplicação Next.js com App Router hoje mesmo.

