Como Integrar a API de CPF em uma Aplicação Spring Boot

Aprenda a integrar a API de CPF em uma aplicação Spring Boot com RestTemplate, service layer, validação e tratamento de erros completo.

Redação CPFHub.io
Redação CPFHub.io
··8 min de leitura
Como Integrar a API de CPF em uma Aplicação Spring Boot

Para integrar a API de CPF em uma aplicação Spring Boot, configure o RestTemplate com os timeouts e o header x-api-key, crie um service que encapsula a chamada para GET https://api.cpfhub.io/cpf/{CPF} e trate as exceções por tipo de resposta. A estrutura completa inclui propriedades externalizadas via application.yml, DTOs tipados e um @RestControllerAdvice para tratamento centralizado de erros.

Introdução

O Spring Boot é o framework mais utilizado para desenvolvimento de aplicações Java empresariais, e integrar APIs externas é uma das tarefas mais comuns nesse ecossistema.

Configuração do projeto

Comece configurando as dependências e propriedades da aplicação.

// pom.xml (dependências relevantes)
// spring-boot-starter-web
// spring-boot-starter-validation
// jackson-databind
// lombok (opcional)

// application.yml
// cpfhub:
// api-key: ${CPFHUB_API_KEY}
// base-url: https://api.cpfhub.io
// timeout:
// connect: 5000
// read: 10000
// CpfHubProperties.java
package com.exemplo.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "cpfhub")
public class CpfHubProperties {

    private String apiKey;
    private String baseUrl = "https://api.cpfhub.io";
    private Timeout timeout = new Timeout();

    public static class Timeout {
    private int connect = 5000;
    private int read = 10000;

    // Getters e setters
    public int getConnect() { return connect; }
    public void setConnect(int connect) { this.connect = connect; }
    public int getRead() { return read; }
    public void setRead(int read) { this.read = read; }
    }

    // Getters e setters
    public String getApiKey() { return apiKey; }
    public void setApiKey(String apiKey) { this.apiKey = apiKey; }
    public String getBaseUrl() { return baseUrl; }
    public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
    public Timeout getTimeout() { return timeout; }
    public void setTimeout(Timeout timeout) { this.timeout = timeout; }
}
PropriedadeValor PadrãoDescrição
cpfhub.api-key(variável de ambiente)Chave de autenticação da API
cpfhub.base-urlhttps://api.cpfhub.ioURL base da API
cpfhub.timeout.connect5000msTimeout de conexão
cpfhub.timeout.read10000msTimeout de leitura

Modelos de dados

Defina os DTOs para a comunicação com a API.

// CpfResponse.java
package com.exemplo.dto;

import com.fasterxml.jackson.annotation.JsonProperty;

public class CpfResponse {

    private boolean success;
    private CpfData data;

    // Getters e setters
    public boolean isSuccess() { return success; }
    public void setSuccess(boolean success) { this.success = success; }
    public CpfData getData() { return data; }
    public void setData(CpfData data) { this.data = data; }
}

// CpfData.java
public class CpfData {

    private String cpf;
    private String name;
    private String nameUpper;
    private String gender;
    private String birthDate;
    private int day;
    private int month;
    private int year;

    // Getters e setters
    public String getCpf() { return cpf; }
    public void setCpf(String cpf) { this.cpf = cpf; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getNameUpper() { return nameUpper; }
    public void setNameUpper(String nameUpper) { this.nameUpper = nameUpper; }
    public String getGender() { return gender; }
    public void setGender(String gender) { this.gender = gender; }
    public String getBirthDate() { return birthDate; }
    public void setBirthDate(String birthDate) { this.birthDate = birthDate; }
    public int getDay() { return day; }
    public void setDay(int day) { this.day = day; }
    public int getMonth() { return month; }
    public void setMonth(int month) { this.month = month; }
    public int getYear() { return year; }
    public void setYear(int year) { this.year = year; }
}

Service layer

O service encapsula a lógica de chamada à API e tratamento de erros.

// CpfService.java
package com.exemplo.service;

import com.exemplo.config.CpfHubProperties;
import com.exemplo.dto.CpfData;
import com.exemplo.dto.CpfResponse;
import com.exemplo.exception.CpfNaoEncontradoException;
import com.exemplo.exception.CpfHubApiException;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;

@Service
public class CpfService {

    private final RestTemplate restTemplate;
    private final CpfHubProperties properties;

    public CpfService(
    RestTemplateBuilder builder,
    CpfHubProperties properties) {
    this.properties = properties;
    this.restTemplate = builder
    .setConnectTimeout(Duration.ofMillis(
    properties.getTimeout().getConnect()))
    .setReadTimeout(Duration.ofMillis(
    properties.getTimeout().getRead()))
    .build();
    }

    public CpfData consultar(String cpf) {
    String cpfLimpo = cpf.replaceAll("\\D", "");
    validarFormatoCpf(cpfLimpo);

    HttpHeaders headers = new HttpHeaders();
    headers.set("x-api-key", properties.getApiKey());

    HttpEntity<Void> entity = new HttpEntity<>(headers);

    try {
    ResponseEntity<CpfResponse> response = restTemplate.exchange(
    properties.getBaseUrl() + "/cpf/" + cpfLimpo,
    HttpMethod.GET,
    entity,
    CpfResponse.class
    );

    CpfResponse body = response.getBody();
    if (body != null && body.isSuccess()) {
    return body.getData();
    }

    throw new CpfNaoEncontradoException(
    "CPF " + cpfLimpo + " nao encontrado"
    );
    } catch (HttpClientErrorException.Unauthorized e) {
    throw new CpfHubApiException("API key invalida");
    } catch (HttpClientErrorException e) {
    throw new CpfHubApiException(
    "Erro na API: " + e.getStatusCode()
    );
    }
    }

    private void validarFormatoCpf(String cpf) {
    if (cpf == null || !cpf.matches("\\d{11}")) {
    throw new IllegalArgumentException(
    "CPF deve conter 11 digitos"
    );
    }
    }
}

Controller REST

O controller expõe o endpoint para consulta de CPF.

// CpfController.java
package com.exemplo.controller;

import com.exemplo.dto.CpfData;
import com.exemplo.service.CpfService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/api/cpf")
public class CpfController {

    private final CpfService cpfService;

    public CpfController(CpfService cpfService) {
    this.cpfService = cpfService;
    }

    @GetMapping("/{cpf}")
    public ResponseEntity<Map<String, Object>> consultar(
    @PathVariable String cpf) {
    CpfData dados = cpfService.consultar(cpf);
    return ResponseEntity.ok(Map.of(
    "sucesso", true,
    "dados", dados
    ));
    }
}

// GlobalExceptionHandler.java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(CpfNaoEncontradoException.class)
    public ResponseEntity<Map<String, String>> handleCpfNaoEncontrado(
    CpfNaoEncontradoException ex) {
    return ResponseEntity.status(404).body(Map.of(
    "erro", ex.getMessage()
    ));
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<Map<String, String>> handleArgumentoInvalido(
    IllegalArgumentException ex) {
    return ResponseEntity.badRequest().body(Map.of(
    "erro", ex.getMessage()
    ));
    }

    @ExceptionHandler(CpfHubApiException.class)
    public ResponseEntity<Map<String, String>> handleApiException(
    CpfHubApiException ex) {
    return ResponseEntity.status(502).body(Map.of(
    "erro", ex.getMessage()
    ));
    }
}
EndpointMétodoDescrição
/api/cpf/{cpf}GETConsulta um CPF via API
Resposta 200-CPF encontrado com dados
Resposta 400-CPF em formato inválido
Resposta 404-CPF não encontrado
Resposta 502-Erro na comunicação com a API

Testes

Escreva testes unitários e de integração para garantir a qualidade.

// CpfServiceTest.java
@SpringBootTest
class CpfServiceTest {

    @MockBean
    private RestTemplate restTemplate;

    @Autowired
    private CpfService cpfService;

    @Test
    void deveRetornarDadosQuandoCpfEncontrado() {
    CpfResponse response = new CpfResponse();
    response.setSuccess(true);
    CpfData data = new CpfData();
    data.setCpf("12345678901");
    data.setName("Joao da Silva");
    data.setGender("M");
    response.setData(data);

    // Configurar mock...

    CpfData resultado = cpfService.consultar("12345678901");
    assertEquals("Joao da Silva", resultado.getName());
    }

    @Test
    void deveLancarExcecaoQuandoCpfInvalido() {
    assertThrows(
    IllegalArgumentException.class,
    () -> cpfService.consultar("123")
    );
    }
}

Perguntas frequentes

Por que usar um @ConfigurationProperties para as configurações da API de CPF no Spring Boot?

Externalizar as configurações via @ConfigurationProperties permite alterar a API key, a URL base e os timeouts sem recompilar a aplicação — basta atualizar variáveis de ambiente ou o application.yml. Isso é essencial para ambientes distintos (dev, staging, prod) e para rotação segura de chaves de autenticação seguindo as boas práticas da OWASP.

Qual a diferença entre RestTemplate e WebClient para consumir a API de CPF no Spring Boot?

O RestTemplate é síncrono e bloqueante — adequado para aplicações Spring MVC tradicionais. O WebClient é não bloqueante e faz parte do Spring WebFlux — indicado para aplicações reativas. Para a maioria dos cenários de validação de CPF em cadastro ou checkout, o RestTemplate com timeout configurável é suficiente e mais simples de testar.

Como tratar o caso em que o CPF não é encontrado na API?

Quando success: false na resposta, lance uma exceção tipada (ex.: CpfNaoEncontradoException) e capture-a no @RestControllerAdvice para retornar HTTP 404 com mensagem clara ao cliente da sua API. Não trate como erro de sistema — é um resultado de negócio esperado que deve ser comunicado de forma limpa.

A API de CPF pode bloquear minha aplicação por volume de chamadas?

Não. A API CPFHub.io não bloqueia por volume — quando o limite do plano é ultrapassado, cada consulta extra é cobrada a R$0,15 sem interrupção do serviço. Planeje o dimensionamento pelo custo, não por disponibilidade. Para volumes elevados, o plano Pro oferece 1.000 consultas mensais por R$149 com a mesma política de excedente.


Conclusão

Integrar a API de CPF em uma aplicação Spring Boot segue as melhores práticas do ecossistema Spring: configuração externalizada, injeção de dependência, service layer e tratamento centralizado de exceções. Essa abordagem garante que a integração seja testável, manutenível e resiliente. O uso de RestTemplate com timeout configurável e headers de autenticação torna a comunicação com a API segura e eficiente.

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