Para integrar validação de CPF em Laravel, use o HTTP Client nativo (disponível desde a versão 7) para chamar GET https://api.cpfhub.io/cpf/{CPF} com o header x-api-key. Encapsule a chamada em uma Service Class, registre-a como singleton no container e reutilize em controllers, Form Requests e Custom Validation Rules. A resposta chega em ~900ms com nome, data de nascimento e gênero do titular.
Introdução
O Laravel é o framework PHP mais popular do mundo, amplamente adotado por desenvolvedores brasileiros para construir desde aplicações simples até plataformas complexas de fintechs e e-commerces. Uma necessidade recorrente nesses projetos é a validação de CPF durante o cadastro de clientes, checkout de compras ou processos de onboarding.
A partir da versão 7, o Laravel passou a incluir um HTTP Client nativo baseado no Guzzle, que simplifica drasticamente a forma como fazemos requisições HTTP.
1. Configuração inicial
Obtendo a chave de API
Antes de tudo, cadastre-se gratuitamente em CPFHub.io para obter sua chave de API. O plano gratuito oferece 50 consultas mensais sem cartão de crédito.
Adicionando a chave ao .env
Adicione sua chave de API ao arquivo .env do projeto Laravel:
CPFHUB_API_KEY=SUA_CHAVE_DE_API
Em seguida, crie uma entrada no arquivo config/services.php para centralizar a configuração:
// config/services.php
return [
// ... outras configurações
'cpfhub' => [
'api_key' => env('CPFHUB_API_KEY'),
'base_url' => 'https://api.cpfhub.io',
'timeout' => 30,
],
];
2. Criando o Service Class
A melhor prática no Laravel é encapsular integrações externas em uma Service Class. Isso mantém o código organizado, testável e reutilizável.
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class CpfHubService
{
private string $apiKey;
private string $baseUrl;
private int $timeout;
public function __construct()
{
$this->apiKey = config('services.cpfhub.api_key');
$this->baseUrl = config('services.cpfhub.base_url');
$this->timeout = config('services.cpfhub.timeout', 30);
}
public function consultar(string $cpf): ?array
{
$cpfLimpo = preg_replace('/\D/', '', $cpf);
try {
$response = Http::withHeaders([
'x-api-key' => $this->apiKey,
'Accept' => 'application/json',
])
->timeout($this->timeout)
->get("{$this->baseUrl}/cpf/{$cpfLimpo}");
if ($response->successful() && $response->json('success')) {
return $response->json('data');
}
Log::warning('CPFHub: Consulta sem sucesso', [
'cpf' => $cpfLimpo,
'status' => $response->status(),
'body' => $response->body(),
]);
return null;
} catch (\Exception $e) {
Log::error('CPFHub: Erro na requisição', [
'cpf' => $cpfLimpo,
'message' => $e->getMessage(),
]);
return null;
}
}
public function validarIdentidade(string $cpf, string $nome): bool
{
$dados = $this->consultar($cpf);
if (!$dados) {
return false;
}
$nomeApi = mb_strtoupper($dados['nameUpper']);
$nomeInput = mb_strtoupper(trim($nome));
return str_contains($nomeApi, $nomeInput) || str_contains($nomeInput, $nomeApi);
}
}
Registrando o Service no container
No AppServiceProvider, registre o service como singleton:
<?php
namespace App\Providers;
use App\Services\CpfHubService;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(CpfHubService::class, function () {
return new CpfHubService();
});
}
}
3. Usando em Controllers
Com o Service registrado, a injeção de dependência do Laravel facilita o uso em qualquer controller:
<?php
namespace App\Http\Controllers;
use App\Services\CpfHubService;
use Illuminate\Http\Request;
class CadastroController extends Controller
{
public function verificarCpf(Request $request, CpfHubService $cpfHub)
{
$request->validate([
'cpf' => 'required|string|size:11',
]);
$dados = $cpfHub->consultar($request->cpf);
if (!$dados) {
return response()->json([
'message' => 'Não foi possível validar o CPF informado.',
], 422);
}
return response()->json([
'nome' => $dados['name'],
'genero' => $dados['gender'],
'nascimento' => $dados['birthDate'],
]);
}
}
4. Criando uma Custom Validation Rule
O Laravel permite criar regras de validação personalizadas. Vamos criar uma rule que valida se o CPF existe e está ativo via API:
<?php
namespace App\Rules;
use App\Services\CpfHubService;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class CpfValido implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$cpfLimpo = preg_replace('/\D/', '', $value);
if (strlen($cpfLimpo) !== 11) {
$fail('O :attribute deve conter exatamente 11 dígitos.');
return;
}
$service = app(CpfHubService::class);
$dados = $service->consultar($cpfLimpo);
if (!$dados) {
$fail('O :attribute informado não é válido ou não foi encontrado.');
}
}
}
Uso no Form Request:
<?php
namespace App\Http\Requests;
use App\Rules\CpfValido;
use Illuminate\Foundation\Http\FormRequest;
class CadastroRequest extends FormRequest
{
public function rules(): array
{
return [
'cpf' => ['required', 'string', new CpfValido],
'nome' => ['required', 'string', 'max:255'],
'email' => ['required', 'email'],
];
}
}
5. Exemplo de resposta da API
A API da CPFHub.io retorna o seguinte JSON:
{
"success": true,
"data": {
"cpf": "12345678900",
"name": "Joao da Silva",
"nameUpper": "JOAO DA SILVA",
"gender": "M",
"birthDate": "15/06/1990",
"day": 15,
"month": 6,
"year": 1990
}
}
- success — Indica se a consulta foi bem-sucedida.
- name / nameUpper — Nome completo do titular em formato normal e maiúsculas.
- gender — Gênero do titular (M ou F).
- birthDate — Data de nascimento completa.
- day, month, year — Componentes da data de nascimento separados, úteis para cálculos de idade.
6. Implementando cache para otimizar consultas
Para reduzir o consumo de consultas da API, implemente cache usando o sistema nativo do Laravel:
public function consultar(string $cpf): ?array
{
$cpfLimpo = preg_replace('/\D/', '', $cpf);
$cacheKey = "cpfhub:{$cpfLimpo}";
return cache()->remember($cacheKey, now()->addHours(24), function () use ($cpfLimpo) {
$response = Http::withHeaders([
'x-api-key' => $this->apiKey,
'Accept' => 'application/json',
])
->timeout($this->timeout)
->get("{$this->baseUrl}/cpf/{$cpfLimpo}");
if ($response->successful() && $response->json('success')) {
return $response->json('data');
}
return null;
});
}
Essa abordagem é especialmente útil no plano gratuito, onde você dispõe de 50 consultas mensais. Com cache de 24 horas, consultas repetidas ao mesmo CPF não consomem sua cota.
7. Tratamento de erros e resiliência
A CPFHub.io não retorna HTTP 429 ao atingir o limite do plano — ao ultrapassar a cota, cada consulta adicional é cobrada a R$0,15, sem bloqueio do serviço. Ainda assim, implemente retry para erros transitórios como timeouts e erros 5xx:
$response = Http::withHeaders([
'x-api-key' => $this->apiKey,
'Accept' => 'application/json',
])
->timeout($this->timeout)
->retry(3, 2000, function ($exception, $request) {
// Retry apenas em erros de conexão ou erros 5xx
return $exception instanceof \Illuminate\Http\Client\ConnectionException
|| ($exception instanceof \Illuminate\Http\Client\RequestException
&& $exception->response->status() >= 500);
})
->get("{$this->baseUrl}/cpf/{$cpfLimpo}");
O método retry tentará a requisição até 3 vezes, aguardando 2 segundos entre cada tentativa, apenas para falhas de conectividade ou erros de servidor.
Perguntas frequentes
Como testar a integração com Laravel sem consumir consultas reais?
Utilize o método Http::fake() do Laravel para simular respostas da API nos testes automatizados. Defina um fixture com a estrutura de resposta da CPFHub.io e injete no service durante os testes. Isso garante cobertura completa dos fluxos de sucesso e erro sem gastar cota do plano gratuito.
O Service Class funciona com injeção de dependência em jobs e commands?
Sim. Como o CpfHubService é registrado como singleton no container do Laravel, ele pode ser injetado normalmente em qualquer classe resolvida pelo container — incluindo jobs, commands artisan, listeners e middlewares. O timeout configurado em services.cpfhub.timeout se aplica a todas essas chamadas.
Qual timeout configurar para o HTTP Client em Laravel?
Recomenda-se 10 segundos para chamadas síncronas em fluxos de cadastro (onde o usuário aguarda). Para processamento em batch ou jobs assíncronos, 30 segundos é aceitável. A CPFHub.io responde em ~900ms em condições normais, então timeouts abaixo de 5 segundos podem gerar falsos negativos em momentos de latência de rede.
Como o cache de 24 horas afeta a conformidade com a LGPD?
Armazenar o resultado da consulta por 24 horas é aceitável para fins de validação de cadastro, pois dados cadastrais do CPF raramente mudam nesse período. A ANPD orienta que o armazenamento deve ser proporcional à finalidade declarada. Para dados sensíveis, considere armazenar apenas um hash ou token de validação em vez dos dados completos, eliminando a necessidade de reter informações pessoais.
Conclusão
Integrar a validação de CPF em Laravel com o HTTP Client nativo é um processo elegante e produtivo. A combinação de Service Class, Custom Validation Rules e cache permite construir uma integração robusta, testável e eficiente, pronta para ambientes de produção.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e tenha a validação de CPF funcionando no seu projeto Laravel em menos de 30 minutos.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
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.



