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.

Redação CPFHub.io
Redação CPFHub.io
··7 min de leitura
Como integrar a API de CPF em uma aplicação Next.js (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:

// .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ávelLadoAcessível no Browser
CPFHUB_API_KEYServidorNão
CPFHUB_BASE_URLServidorNão
NEXT_PUBLIC_*ClienteSim

Criando o Route Handler

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

// 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:

// 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:

// 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:

// 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 para detalhes sobre Route Handlers e boas práticas de uso.


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 — 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.

CPFHub.io

Pronto para integrar a API?

50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.

Redação CPFHub.io

Sobre a redação

Redação CPFHub.io

Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.

WhatsAppFale conosco via WhatsApp