Consumindo a API SmartCPF em Java com Spring Boot
Tutorial prático de integração da API SmartCPF v2 em aplicações Spring Boot com autenticação X-API-KEY e tratamento de erros.

Validar e consultar CPFs é uma necessidade recorrente em sistemas brasileiros — desde cadastros de usuários até processos de KYC e compliance. A API SmartCPF resolve isso expondo um endpoint REST simples que retorna dados cadastrais, situação cadastral, e-mails, telefones e endereços associados a um CPF. Este artigo mostra como integrar a API v2 em uma aplicação Spring Boot de forma robusta, cobrindo autenticação, configuração, chamada HTTP e tratamento de respostas e erros.
A integração direta via RestClient (Spring Boot 3.2+) ou WebClient evita dependências extras e mantém o controle total sobre headers, timeouts e serialização. O foco aqui é uma implementação pronta para produção, com injeção de configuração, logs estruturados e mapeamento de erros da API para exceções de domínio.
Autenticação e endpoint da API SmartCPF
A SmartCPF v2 exige autenticação exclusivamente via header X-API-KEY — não use Authorization: Bearer, query string api_key nem nenhum outro método. O endpoint de consulta individual é:
GET https://api.smartcpf.com.br/v2/individuals/{cpf}?package={pacote}
O parâmetro package define o nível de detalhe do retorno (ex: basic, complete). O CPF na URL deve conter apenas dígitos (sem pontos ou traço). A resposta inclui metadados da consulta (consultId, balance, executionTimeMs) e o objeto result com os dados do titular.
Vantagens da integração nativa com Spring Boot
1. Controle total de headers e timeoutsRestClient e WebClient permitem configurar o header X-API-KEY globalmente via DefaultClientConfigurer ou ExchangeFilterFunction, evitando repetição em cada chamada.
2. Serialização tipada com Jackson
Mapeamento direto do JSON para records Java elimina parsing manual e garante validação de estrutura no compile-time.
3. Tratamento de erros HTTP mapeado a exceções de domínio
Códigos 401, 403, 404, 422 e 5xx podem ser convertidos em SmartCpfException hierárquica, facilitando ControllerAdvice global.
4. Configuração externalizada via application.yml
Base URL, API key, timeouts e pacote padrão ficam fora do código, suportando perfis dev, staging, prod.
5. Observabilidade nativa com Micrometer
Tempo de latência, taxa de erro e contagem de chamadas expostos automaticamente para Prometheus/Grafana sem instrumentação manual.
6. Testes de contrato com MockWebServer ou WireMock
Simulação de respostas da SmartCPF (sucesso, saldo insuficiente, CPF inválido) garante regressão zero em CI/CD.
Desafios e considerações antes de integrar
1. Gerenciamento seguro da API Key
Nunca commite a chave no repositório. Use variáveis de ambiente, Vault, AWS Secrets Manager ou Spring Cloud Config. Em desenvolvimento local, .env com spring.config.import resolve.
2. Rate limiting e retentativas
A API aplica limites por plano. Implemente Retry com backoff exponencial (ex: Resilience4j) apenas para erros 5xx e 429; não retente 4xx — são erros de requisição.
3. Formatação do CPF na requisição
O endpoint espera apenas dígitos. Remova máscara (replaceAll("\\D", "")) antes de montar a URL; a API rejeita CPF formatado com 400.
4. Saldo de créditos (balance)
O campo meta.balance indica créditos restantes. Monitore e alerte quando baixo; consultas falham com 402/403 quando zera.
5. LGPD e armazenamento de dados sensíveis
O retorno inclui nome, data de nascimento, e-mails, telefones. Armazene apenas o necessário, com criptografia em repouso e logs sem PII.
Como implementar com a SmartCPF
Abaixo, uma implementação completa usando RestClient (Spring Boot 3.2+), com configuração tipada, cliente imutável, mapeamento de resposta e exceções personalizadas. O exemplo assume Java 21+ (records, pattern matching) e Jackson no classpath.
package br.com.smartcpf.client;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.client.RestClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestClientException;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
/**
* Cliente tipado para a API SmartCPF v2.
*
* Autenticação: header X-API-KEY obrigatório em todas as requisições.
* Endpoint: GET /v2/individuals/{cpf}?package={package}
*/
@Configuration
@ConfigurationProperties(prefix = "smartcpf")
public class SmartCpfClient {
private String baseUrl = "https://api.smartcpf.com.br";
private String apiKey;
private String defaultPackage = "complete";
private int connectTimeoutMs = 3000;
private int readTimeoutMs = 10000;
// Getters e setters para binding do Spring
public String getBaseUrl() { return baseUrl; }
public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
public String getApiKey() { return apiKey; }
public void setApiKey(String apiKey) { this.apiKey = apiKey; }
public String getDefaultPackage() { return defaultPackage; }
public void setDefaultPackage(String defaultPackage) { this.defaultPackage = defaultPackage; }
public int getConnectTimeoutMs() { return connectTimeoutMs; }
public void setConnectTimeoutMs(int connectTimeoutMs) { this.connectTimeoutMs = connectTimeoutMs; }
public int getReadTimeoutMs() { return readTimeoutMs; }
public void setReadTimeoutMs(int readTimeoutMs) { this.readTimeoutMs = readTimeoutMs; }
/**
* Bean RestClient configurado com base URL, timeouts e header X-API-KEY global.
*/
@Bean
public RestClient restClient(RestClientBuilder builder) {
return builder
.baseUrl(baseUrl)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader("X-API-KEY", apiKey) // Autenticação obrigatória
.requestFactory(requestFactory -> {
requestFactory.setConnectTimeout(connectTimeoutMs);
requestFactory.setReadTimeout(readTimeoutMs);
})
.defaultStatusHandler(
HttpStatusCode::is4xxClientError,
(request, response) -> handleClientError(response)
)
.defaultStatusHandler(
HttpStatusCode::is5xxServerError,
(request, response) -> handleServerError(response)
)
.build();
}
/**
* Consulta um CPF na SmartCPF.
*
* @param cpf CPF apenas com dígitos (11 caracteres)
* @param pkg Pacote de dados (opcional, usa defaultPackage se null)
* @return Resposta tipada com metadados e resultado
* @throws SmartCpfException em erros de autenticação, CPF não encontrado, saldo insuficiente, etc.
*/
public SmartCpfResponse consultarCpf(String cpf, String pkg) {
String cleanCpf = cpf.replaceAll("\\D", "");
if (cleanCpf.length() != 11) {
throw new SmartCpfException.InvalidCpfFormat("CPF deve conter 11 dígitos numéricos: " + cpf);
}
String pacote = pkg != null ? pkg : defaultPackage;
return restClient.get()
.uri(uriBuilder -> uriBuilder
.path("/v2/individuals/{cpf}")
.queryParam("package", pacote)
.build(cleanCpf))
.retrieve()
.body(SmartCpfResponse.class);
}
/** Sobrecarga conveniente usando pacote padrão. */
public SmartCpfResponse consultarCpf(String cpf) {
return consultarCpf(cpf, null);
}
private void handleClientError(org.springframework.http.client.ClientHttpResponse response) {
HttpStatusCode status = response.getStatusCode();
String body = readBody(response);
switch (status.value()) {
case 401 -> throw new SmartCpfException.Unauthorized("API Key inválida ou ausente: " + body);
case 403 -> throw new SmartCpfException.Forbidden("Acesso negado ou saldo insuficiente: " + body);
case 404 -> throw new SmartCpfException.NotFound("CPF não encontrado na base: " + body);
case 422 -> throw new SmartCpfException.UnprocessableEntity("CPF inválido ou parâmetros incorretos: " + body);
default -> throw new SmartCpfException.ClientError("Erro cliente HTTP " + status + ": " + body);
}
}
private void handleServerError(org.springframework.http.client.ClientHttpResponse response) {
String body = readBody(response);
throw new SmartCpfException.ServerError("Erro servidor SmartCPF " + response.getStatusCode() + ": " + body);
}
private String readBody(org.springframework.http.client.ClientHttpResponse response) {
try (var is = response.getBody()) {
return new String(is.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
} catch (Exception e) {
return "<sem corpo>";
}
}
/* ==================== MODELOS DE RESPOSTA ==================== */
@JsonIgnoreProperties(ignoreUnknown = true)
public record SmartCpfResponse(
Meta meta,
Result result,
boolean success,
List<String> errors
) {}
@JsonIgnoreProperties(ignoreUnknown = true)
public record Meta(
@JsonProperty("searchType") String searchType,
@JsonProperty("consultId") UUID consultId,
String user,
String message,
String ip,
boolean success,
@JsonProperty("apiVersion") String apiVersion,
@JsonProperty("date") Instant date,
@JsonProperty("executionTimeMs") Double executionTimeMs,
Double balance
) {}
@JsonIgnoreProperties(ignoreUnknown = true)
public record Result(
String cpf,
String name,
@JsonProperty("birthDate") String birthDate,
Integer age,
@JsonProperty("motherName") String motherName,
String gender,
String status,
List<String> emails,
List<Phone> phones,
List<Address> addresses
) {}
@JsonIgnoreProperties(ignoreUnknown = true)
public record Phone(
String number,
@JsonProperty("blockedTelemarketing") boolean blockedTelemarketing,
String operator,
String type,
boolean whatsapp
) {}
@JsonIgnoreProperties(ignoreUnknown = true)
public record Address(
String zipCode,
String street,
String number,
String complement,
String neighborhood,
String city,
String state,
String country
) {}
/* ==================== HIERARQUIA DE EXCEÇÕES ==================== */
public static class SmartCpfException extends RuntimeException {
public SmartCpfException(String message) { super(message); }
public static class InvalidCpfFormat extends SmartCpfException {
public InvalidCpfFormat(String msg) { super(msg); }
}
public static class Unauthorized extends SmartCpfException {
public Unauthorized(String msg) { super(msg); }
}
public static class Forbidden extends SmartCpfException {
public Forbidden(String msg) { super(msg); }
}
public static class NotFound extends SmartCpfException {
public NotFound(String msg) { super(msg); }
}
public static class UnprocessableEntity extends SmartCpfException {
public UnprocessableEntity(String msg) { super(msg); }
}
public static class ClientError extends SmartCpfException {
public ClientError(String msg) { super(msg); }
}
public static class ServerError extends SmartCpfException {
public ServerError(String msg) { super(msg); }
}
}
}
Resposta da API
{
"meta": {
"searchType": "CPF G",
"consultId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user": "Fulano de Tal",
"message": "CPF encontrado com sucesso",
"ip": "127.0.0.1",
"success": true,
"apiVersion": "v2",
"date": "2026-08-17T14:32:10.123Z",
"executionTimeMs": 74.1,
"balance": 9.77
},
"result": {
"cpf": "111.111.111-11",
"name": "João da Silva",
"birthDate": "10/09/1992",
"age": 33,
"motherName": "Maria da Silva",
"gender": "M",
"status": "Regular",
"emails": ["[email protected]"],
"phones": [
{
"number": "(55) 99999-9999",
"blockedTelemarketing": false,
"operator": "VIVO",
"type": "CELULAR",
"whatsapp": false
}
],
"addresses": []
},
"success": true,
"errors": []
}
O fluxo demonstrado resolve na prática:
- Autenticação transparente: header
X-API-KEYinjetado uma única vez noRestClient, sem repetição em chamadas. - Rastreabilidade:
meta.consultId(UUID) permite correlacionar logs da sua aplicação com logs da SmartCPF em suporte. - Controle de custos:
meta.balanceexpõe créditos restantes; monitore e alerte antes de zerar. - Validação precoce: formatação do CPF (apenas dígitos) e verificação de 11 caracteres evitam 400 desnecessários.
- Tratamento semântico de erros: 401 →
Unauthorized(chave inválida), 403 →Forbidden(saldo/permissão), 404 →NotFound(CPF inexistente), 422 →UnprocessableEntity(CPF malformado), 5xx →ServerError(retry com backoff). - Dados estruturados: records imutáveis mapeiam
result(nome, idade, status, e-mails, telefones com operadora/tipo/WhatsApp, endereços) prontos para uso em regras de negócio.
Por que usar a SmartCPF
- Latência baixa consistente:
executionTimeMstípico abaixo de 100 ms em produção, com SLA publicado. - Integração sem SDK proprietário: REST padrão + JSON, funciona em qualquer stack (Java, Kotlin, Node, Go, Python).
- Modelo de créditos previsível: pague por consulta, sem mensalidade mínima;
balanceem tempo real na resposta. - Escalabilidade horizontal: arquitetura stateless suporta picos de Black Friday, onboarding em massa, batch noturno.
- Conformidade LGPD nativa: dados sensíveis retornados sob demanda, sem armazenamento persistente no lado da API além do log de auditoria (
consultId, IP, timestamp).
Conclusão
Integrar a SmartCPF em Spring Boot exige poucas linhas de código quando se usa RestClient com configuração centralizada, records para mapeamento e hierarquia de exceções para erros HTTP. O resultado é um cliente tipado, testável, observável e pronto para produção — sem dependências extras além do próprio Spring Web. Crie sua conta na SmartCPF e faça sua primeira consulta em minutos.
Sobre a redação
Redação Smart CPF
Autor do blog
Mais artigos

Validação de CPF em Ruby on Rails: guia completo de integração
Como validar e consultar CPF em Rails usando a API SmartCPF v2 com autenticação X-API-KEY, tratamento de erros e exemplos práticos.

SmartCPF vs Consulta Manual na Receita Federal: Tempo e Confiabilidade
Comparativo técnico entre consulta automatizada via API SmartCPF e processo manual no e-CAC: latência, disponibilidade e integração

Validação de CPF em Rust com Axum: exemplo prático com SmartCPF
Aprenda a validar CPF em Rust usando Axum e a API SmartCPF v2. Código completo com autenticação X-API-KEY, tratamento de erros e parsing da resposta.

Validação de CPF em plugin WordPress: passo a passo com a API SmartCPF
Tutorial completo de como validar CPF em plugins WordPress usando a API SmartCPF v2, com exemplos PHP práticos e tratamento de erros.
Pronto para validar CPFs em segundos?
Consultas gratuitas para testar agora. Acesso imediato à documentação.