Como Validar CPF em Tempo Real Usando Java e APIs REST

Aprenda a validar CPF em tempo real usando Java com APIs REST, combinando validação algorítmica e consulta via API para máxima segurança.

Redação CPFHub.io
Redação CPFHub.io
··7 min de leitura
Como Validar CPF em Tempo Real Usando Java e APIs REST

Para validar CPF em tempo real com Java, combine a validação algorítmica local (verificação dos dígitos verificadores, instantânea) com uma chamada GET à API REST da CPFHub.io usando o HttpClient nativo ou um serviço Spring. A validação algorítmica filtra CPFs com formato inválido antes que qualquer chamada de rede seja feita; a consulta via API confirma a existência real do documento e retorna nome, data de nascimento e gênero em ~900ms.

Introdução

A validação de CPF em tempo real é um requisito comum em aplicações de cadastro, checkout e onboarding. A abordagem mais robusta combina validação algorítmica local, que é instantânea, com consulta via API REST para verificar a existência real do CPF. Em Java, essa combinação pode ser implementada de forma eficiente e thread-safe, atendendo a cenários de alta concorrência.


Validação algorítmica local

A validação algorítmica verifica os dígitos verificadores do CPF sem necessidade de chamada externa.

public class CpfValidator {

    private CpfValidator() {}

    public static boolean validarAlgoritmo(String cpf) {
    String cpfLimpo = cpf.replaceAll("\\D", "");

    if (cpfLimpo.length() != 11) {
    return false;
    }

    // Verificar se todos os dígitos são iguais
    if (cpfLimpo.chars().distinct().count() == 1) {
    return false;
    }

    // Validar primeiro dígito verificador
    int soma = 0;
    for (int i = 0; i < 9; i++) {
    soma += Character.getNumericValue(cpfLimpo.charAt(i))
    * (10 - i);
    }
    int resto = (soma * 10) % 11;
    if (resto == 10) resto = 0;
    if (resto != Character.getNumericValue(cpfLimpo.charAt(9))) {
    return false;
    }

    // Validar segundo dígito verificador
    soma = 0;
    for (int i = 0; i < 10; i++) {
    soma += Character.getNumericValue(cpfLimpo.charAt(i))
    * (11 - i);
    }
    resto = (soma * 10) % 11;
    if (resto == 10) resto = 0;

    return resto == Character.getNumericValue(cpfLimpo.charAt(10));
    }

    public static String formatar(String cpf) {
    String limpo = cpf.replaceAll("\\D", "");
    return String.format("%s.%s.%s-%s",
    limpo.substring(0, 3),
    limpo.substring(3, 6),
    limpo.substring(6, 9),
    limpo.substring(9, 11));
    }
}
ValidaçãoTempoCobertura
Formato (11 dígitos)< 0.001msErros de digitação
Dígitos iguais< 0.001msCPFs triviais (111.111.111-11)
Dígitos verificadores< 0.01msCPFs com números inventados
Consulta via API100-500msExistência real do CPF

Serviço de validação em tempo real

O serviço combina validação local e consulta via API com cache para otimizar performance.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class CpfValidationService {

    private final HttpClient httpClient;
    private final String apiKey;
    private final ObjectMapper mapper;
    private final Map<String, ValidationResult> cache;

    public CpfValidationService(String apiKey) {
    this.httpClient = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(5))
    .build();
    this.apiKey = apiKey;
    this.mapper = new ObjectMapper();
    this.cache = new ConcurrentHashMap<>();
    }

    public ValidationResult validarTempoReal(String cpf) {
    String cpfLimpo = cpf.replaceAll("\\D", "");

    // Etapa 1: Validação algorítmica
    if (!CpfValidator.validarAlgoritmo(cpfLimpo)) {
    return new ValidationResult(
    false, "algoritmo", "CPF invalido", null
    );
    }

    // Etapa 2: Verificar cache
    ValidationResult cached = cache.get(cpfLimpo);
    if (cached != null) {
    return new ValidationResult(
    cached.valido(), "cache",
    cached.mensagem(), cached.dados()
    );
    }

    // Etapa 3: Consulta via API
    try {
    HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(
    "https://api.cpfhub.io/cpf/" + cpfLimpo
    ))
    .header("x-api-key", apiKey)
    .timeout(Duration.ofSeconds(5))
    .GET()
    .build();

    HttpResponse<String> response = httpClient.send(
    request,
    HttpResponse.BodyHandlers.ofString()
    );

    JsonNode root = mapper.readTree(response.body());

    if (root.get("success").asBoolean()) {
    JsonNode data = root.get("data");
    Map<String, String> dados = Map.of(
    "nome", data.get("name").asText(),
    "genero", data.get("gender").asText(),
    "nascimento", data.get("birthDate").asText()
    );

    ValidationResult result = new ValidationResult(
    true, "api", "CPF valido", dados
    );
    cache.put(cpfLimpo, result);
    return result;
    }

    return new ValidationResult(
    false, "api", "CPF nao encontrado", null
    );

    } catch (Exception e) {
    // Fallback: se a API falhar, aceitar com base
    // na validação algorítmica
    return new ValidationResult(
    true, "fallback",
    "Validado localmente (API indisponivel)",
    null
    );
    }
    }
}

public record ValidationResult(
    boolean valido,
    String fonte,
    String mensagem,
    Map<String, String> dados
) {}

Endpoint REST para validação em tempo real

Exponha o serviço como endpoint REST para consumo por frontends ou outros serviços.

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/validar")
public class CpfValidationController {

    private final CpfValidationService validationService;

    public CpfValidationController(
    CpfValidationService validationService) {
    this.validationService = validationService;
    }

    @GetMapping("/cpf/{cpf}")
    public ResponseEntity<ValidationResult> validar(
    @PathVariable String cpf) {
    ValidationResult resultado =
    validationService.validarTempoReal(cpf);
    return ResponseEntity.ok(resultado);
    }

    @PostMapping("/cpf/lote")
    public ResponseEntity<Map<String, Object>> validarLote(
    @RequestBody List<String> cpfs) {

    List<ValidationResult> resultados = cpfs.stream()
    .map(validationService::validarTempoReal)
    .toList();

    long validos = resultados.stream()
    .filter(ValidationResult::valido)
    .count();

    return ResponseEntity.ok(Map.of(
    "total", cpfs.size(),
    "validos", validos,
    "invalidos", cpfs.size() - validos,
    "resultados", resultados
    ));
    }
}
EndpointMétodoDescrição
/api/validar/cpf/{cpf}GETValidação individual em tempo real
/api/validar/cpf/lotePOSTValidação de múltiplos CPFs

Bean Validation customizado

Crie uma anotação customizada para validar CPF em DTOs automaticamente.

// CpfValido.java
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CpfValidoValidator.class)
public @interface CpfValido {
    String message() default "CPF invalido";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

// CpfValidoValidator.java
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

public class CpfValidoValidator
    implements ConstraintValidator<CpfValido, String> {

    @Override
    public boolean isValid(String cpf,
    ConstraintValidatorContext context) {
    if (cpf == null || cpf.isBlank()) {
    return false;
    }
    return CpfValidator.validarAlgoritmo(cpf);
    }
}

// Uso em DTO
public class CadastroRequest {

    @CpfValido(message = "CPF informado e invalido")
    private String cpf;

    private String nome;

    // Getters e setters
    public String getCpf() { return cpf; }
    public void setCpf(String cpf) { this.cpf = cpf; }
    public String getNome() { return nome; }
    public void setNome(String nome) { this.nome = nome; }
}

Métricas de performance

Monitore a performance da validação em tempo real com Micrometer.

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;

@Service
public class CpfValidationServiceMetricas {

    private final Timer validacaoTimer;
    private final CpfValidationService validationService;

    public CpfValidationServiceMetricas(
    MeterRegistry registry,
    CpfValidationService validationService) {
    this.validationService = validationService;
    this.validacaoTimer = Timer.builder("cpf.validacao")
    .description("Tempo de validacao de CPF")
    .register(registry);
    }

    public ValidationResult validar(String cpf) {
    return validacaoTimer.record(
    () -> validationService.validarTempoReal(cpf)
    );
    }
}

Perguntas frequentes

Por que combinar validação algorítmica e consulta via API em Java?

A validação algorítmica é instantânea (sub-millisegundo) e elimina CPFs com formato inválido ou dígitos verificadores errados antes de qualquer chamada de rede. A consulta via API confirma a existência real do CPF e retorna dados como nome e data de nascimento. Juntas, as duas camadas reduzem tanto o volume de chamadas externas quanto a taxa de falsos positivos no cadastro.

Como implementar cache thread-safe para a validação de CPF em Java?

Use ConcurrentHashMap para armazenar resultados recentes. A chave é o CPF sanitizado (apenas dígitos) e o valor é o ValidationResult. Em ambientes com alta concorrência, considere adicionar TTL com Caffeine ou Guava Cache para evitar servir dados desatualizados. O cache é especialmente útil em validações em lote onde o mesmo CPF pode aparecer múltiplas vezes.

Como configurar timeout adequado para a API de CPF em Java?

Configure timeout de conexão em 5 segundos e timeout de leitura em 10 segundos. A API da CPFHub.io tem latência de ~900ms em condições normais, portanto timeouts muito curtos podem gerar falsos negativos. Com HttpClient nativo, use .timeout(Duration.ofSeconds(10)) no HttpRequest; com Spring RestTemplate, configure via RestTemplateBuilder.setReadTimeout().

O que fazer quando a API de CPF retorna erro ou fica indisponível?

Implemente um fallback que retorna o resultado da validação algorítmica com fonte = "fallback", indicando que o CPF passou apenas pela verificação local. Registre o evento para monitoramento. A API da CPFHub.io não bloqueia consultas ao atingir o limite do plano — ela cobra R$0,15 por consulta excedente e continua respondendo normalmente, então erros de disponibilidade são raros e geralmente transitórios.


Conclusão

A validação de CPF em tempo real em Java combina a velocidade da validação algorítmica local com a precisão da consulta via API REST. O uso de cache thread-safe com ConcurrentHashMap, fallback para cenários de indisponibilidade e Bean Validation customizada para DTOs cria um sistema robusto e reutilizável. As métricas com Micrometer permitem monitorar a performance e identificar gargalos em produção.

Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre a validação de CPF em tempo real na sua aplicação Java 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.

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