Como usar Server Actions do Next.js para consultar CPF via API

Aprenda a usar Server Actions do Next.js para consultar CPF via API sem criar Route Handlers, com validação e feedback.

Redação CPFHub.io
Redação CPFHub.io
··8 min de leitura
Como usar Server Actions do Next.js para consultar CPF via API

Server Actions são funções assíncronas do Next.js executadas no servidor e chamadas diretamente de componentes React, eliminando a necessidade de Route Handlers ou endpoints de API manuais. Com elas, a chave de API fica protegida no servidor, o código fica mais conciso e a integração com a API de CPF da CPFHub.io se reduz a poucas linhas. Esta abordagem é ideal para validação de CPF em formulários de cadastro, checkout e onboarding digital.

Introdução

Server Actions são uma funcionalidade do Next.js que permite executar código no servidor diretamente a partir de componentes React, sem a necessidade de criar Route Handlers ou endpoints de API manualmente. Essa abordagem simplifica a integração com APIs externas como o CPFHub.io, mantendo a chave de API segura e reduzindo a quantidade de código necessário.

O que são Server Actions

Server Actions são funções assíncronas executadas no servidor que podem ser chamadas diretamente de componentes React. Elas são marcadas com a diretiva 'use server'.

// actions/cpf-actions.js
'use server';

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

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

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

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

    const dados = await response.json();

    if (!dados.success) {
    return { success: false, error: 'CPF não encontrado na base' };
    }

    return {
    success: true,
    data: {
    cpf: dados.data.cpf,
    nome: dados.data.name,
    nomeUpper: dados.data.nameUpper,
    genero: dados.data.gender,
    dataNascimento: dados.data.birthDate,
    dia: dados.data.day,
    mes: dados.data.month,
    ano: dados.data.year,
    },
    };
}
CaracterísticaServer ActionsRoute Handlers
Arquivo separadoNão obrigatórioSim (route.js)
Chamada do clienteDireta (como função)Via fetch
Segurança da API KeySim (servidor)Sim (servidor)
SerializaçãoAutomáticaManual (JSON)
Formulários nativosSuporte totalNão aplicável
Código necessárioMenosMais

Server Action com validação completa

Crie uma Server Action que realiza validação algorítmica antes de consultar a API:

// actions/cpf-actions.js
'use server';

function validarDigitosCpf(cpf) {
    const digitos = cpf.split('').map(Number);
    if (new Set(digitos).size === 1) return false;

    let soma = 0;
    for (let i = 0; i < 9; i++) soma += digitos[i] * (10 - i);
    const d1 = soma % 11 < 2 ? 0 : 11 - (soma % 11);

    soma = 0;
    for (let i = 0; i < 10; i++) soma += digitos[i] * (11 - i);
    const d2 = soma % 11 < 2 ? 0 : 11 - (soma % 11);

    return digitos[9] === d1 && digitos[10] === d2;
}

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

    if (cpfLimpo.length !== 11) {
    return {
    success: false,
    etapa: 'formato',
    error: 'CPF deve conter 11 dígitos',
    };
    }

    if (!validarDigitosCpf(cpfLimpo)) {
    return {
    success: false,
    etapa: 'digitos',
    error: 'Dígitos verificadores inválidos',
    };
    }

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

    if (!response.ok) {
    return {
    success: true,
    etapa: 'api',
    formatoValido: true,
    encontrado: false,
    message: 'CPF válido, porém não encontrado na base',
    };
    }

    const dados = await response.json();

    return {
    success: true,
    etapa: 'completa',
    formatoValido: true,
    encontrado: dados.success,
    data: dados.success ? dados.data : null,
    };
    } catch {
    return {
    success: false,
    etapa: 'api',
    error: 'Erro ao consultar API externa',
    };
    }
}

Usando Server Actions com useActionState

O hook useActionState do React permite gerenciar o estado de Server Actions de forma elegante:

// components/CpfConsultaForm.jsx
'use client';

import { useActionState } from 'react';
import { validarEConsultarCpf } from '@/actions/cpf-actions';

const initialState = { success: null, data: null, error: null };

export default function CpfConsultaForm() {
    const [state, formAction, isPending] = useActionState(
    validarEConsultarCpf,
    initialState
    );

    return (
    <div className="max-w-lg mx-auto p-6">
    <h2 className="text-xl font-bold mb-4">Consulta de CPF</h2>

    <form action={formAction} className="space-y-4">
    <div>
    <label htmlFor="cpf" className="block text-sm font-medium mb-1">
    CPF
    </label>
    <input
    id="cpf"
    name="cpf"
    type="text"
    maxLength={14}
    placeholder="000.000.000-00"
    required
    className="w-full p-3 border rounded"
    />
    </div>

    <button
    type="submit"
    disabled={isPending}
    className="w-full p-3 bg-blue-600 text-white rounded disabled:opacity-50"
    >
    {isPending ? 'Consultando...' : 'Consultar CPF'}
    </button>
    </form>

    {state.success === true && state.data && (
    <div className="mt-6 p-4 bg-green-50 border border-green-200 rounded">
    <h3 className="font-bold mb-2">Dados encontrados</h3>
    <p><strong>Nome:</strong> {state.data.name}</p>
    <p><strong>CPF:</strong> {state.data.cpf}</p>
    <p><strong>Nascimento:</strong> {state.data.birthDate}</p>
    <p><strong>Genero:</strong> {state.data.gender}</p>
    </div>
    )}

    {state.success === true && !state.encontrado && (
    <div className="mt-6 p-4 bg-yellow-50 border border-yellow-200 rounded">
    <p>{state.message}</p>
    </div>
    )}

    {state.success === false && (
    <div className="mt-6 p-4 bg-red-50 border border-red-200 rounded">
    <p className="text-red-700">{state.error}</p>
    </div>
    )}
    </div>
    );
}

Server Action para processamento em lote

Crie uma Server Action que processa múltiplos CPFs:

// actions/cpf-lote-actions.js
'use server';

export async function processarLoteCpf(formData) {
    const cpfsTexto = formData.get('cpfs');
    const cpfs = cpfsTexto
    .split('\n')
    .map((l) => l.trim().replace(/\D/g, ''))
    .filter((l) => l.length === 11);

    if (cpfs.length === 0) {
    return { success: false, error: 'Nenhum CPF válido encontrado' };
    }

    if (cpfs.length > 20) {
    return { success: false, error: 'Máximo de 20 CPFs por lote' };
    }

    const resultados = await Promise.allSettled(
    cpfs.map(async (cpf) => {
    const response = await fetch(
    `${process.env.CPFHUB_BASE_URL}/cpf/${cpf}`,
    {
    headers: { 'x-api-key': process.env.CPFHUB_API_KEY },
    }
    );

    if (!response.ok) {
    return { cpf, encontrado: false };
    }

    const dados = await response.json();
    return {
    cpf,
    encontrado: dados.success,
    nome: dados.success ? dados.data.name : null,
    dataNascimento: dados.success ? dados.data.birthDate : null,
    };
    })
    );

    return {
    success: true,
    total: cpfs.length,
    resultados: resultados.map((r) =>
    r.status === 'fulfilled'
    ? r.value
    : { cpf: 'desconhecido', encontrado: false, erro: 'Falha na consulta' }
    ),
    };
}

Página completa com Server Actions

Monte a página que integra todos os componentes:

// app/consulta/page.jsx

import CpfConsultaForm from '@/components/CpfConsultaForm';

export const metadata = {
    title: 'Consulta de CPF | Minha Aplicação',
    description: 'Consulte dados de CPF de forma rápida e segura',
};

export default function ConsultaPage() {
    return (
    <main className="min-h-screen bg-gray-50 py-12">
    <div className="container mx-auto">
    <h1 className="text-3xl font-bold text-center mb-8">
    Consulta de CPF
    </h1>
    <CpfConsultaForm />
    </div>
    </main>
    );
}

Perguntas frequentes

O que são Server Actions no Next.js e como diferem de Route Handlers?

Server Actions são funções assíncronas marcadas com 'use server' que executam no servidor e podem ser chamadas diretamente de componentes React — inclusive em atributos action de formulários nativos. Diferente de Route Handlers (arquivos route.js), não exigem um endpoint HTTP separado: o Next.js serializa automaticamente a chamada, reduzindo boilerplate e mantendo a API key fora do bundle do cliente.

Como proteger a chave de API da CPFHub.io ao usar Server Actions?

Armazene a chave em variáveis de ambiente sem o prefixo NEXT_PUBLIC_ (por exemplo, CPFHUB_API_KEY). O Next.js nunca inclui variáveis sem esse prefixo no bundle do cliente. Como a Server Action executa apenas no servidor, a chave nunca é exposta ao navegador — mesmo que o componente que chama a action seja renderizado no cliente.

A API da CPFHub.io pode retornar erro 429 se eu ultrapassar o limite do plano gratuito?

Não. A API da CPFHub.io não retorna HTTP 429 nem bloqueia requisições ao atingir a cota do plano gratuito (50 consultas/mês). Consultas excedentes são cobradas automaticamente a R$0,15 cada. Para acompanhar o consumo e gerenciar o faturamento, acesse app.cpfhub.io/settings/billing.

Como usar useActionState com Server Actions para feedback visual?

Importe useActionState de 'react' e passe sua Server Action como primeiro argumento, seguido do estado inicial. O hook retorna [state, formAction, isPending]: state contém o retorno da última execução, formAction é passado ao atributo action do formulário e isPending indica se a action está em andamento — ideal para desabilitar o botão de submit durante a consulta. A documentação oficial do Next.js cobre o padrão completo com exemplos.


Conclusão

Server Actions do Next.js simplificam drasticamente a integração com APIs externas. Sem necessidade de Route Handlers, o código fica mais conciso e a chave de API permanece segura no servidor. A integração com useActionState proporciona gerenciamento de estado elegante e feedback visual automático durante o processamento.

Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a usar Server Actions com validação de CPF em minutos, sem configurar nenhum endpoint de API.

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