Validação de CPF em Go: exemplo prático com net/http
Aprenda a validar e consultar CPF em Go usando a API SmartCPF v2 com net/http padrão, autenticação X-API-KEY e tratamento de erros robusto.

Validar CPF em aplicações Go vai além de verificar o dígito verificador: em produção, você precisa confirmar se o documento existe na base da Receita Federal, obter dados cadastrais atualizados e tratar casos de CPF suspenso, cancelado ou nulo. A API SmartCPF resolve isso com uma chamada HTTP única que retorna situação cadastral, dados pessoais, e-mails, telefones e endereços — tudo com autenticação por header X-API-KEY e modelo de créditos previsível.
Este artigo mostra como consumir o endpoint GET /v2/individuals/{cpf} usando apenas a biblioteca padrão net/http, sem dependências externas, cobrindo montagem da requisição, leitura do corpo, parsing JSON e tratamento de códigos de status HTTP comuns (401, 404, 422, 429).
Como a consulta de CPF funciona na SmartCPF
A API expõe o recurso individuals onde o CPF (apenas números ou formatado) é passado no path e o pacote de dados desejado vem via query string package. Os pacotes disponíveis — basic, person, contact, address, score e complete — controlam quais campos voltam no result, permitindo otimizar custo e latência. A resposta sempre traz o envelope meta com consultId (rastreabilidade), balance (créditos restantes), executionTimeMs e success, além do array errors vazio em sucesso.
Vantagens de usar a API SmartCPF em Go
1. Zero dependências externas
O exemplo usa só net/http, encoding/json e io — compila em binário único, ideal para containers leves e serverless.
2. Controle total do ciclo de vida da requisição
Timeouts, retries, circuit breaker e logging ficam no seu código, não escondidos em SDKs.
3. Autenticação simples e segura
Header X-API-KEY evita vazamento de segredos em logs de proxy ou URL; rotação de chave é imediata no painel.
4. Modelo de créditos previsível
Cada resposta traz meta.balance; você monitora consumo em tempo real sem faturas surpresa.
5. Dados enriquecidos em uma chamada
Pacote complete retorna nome, data de nascimento, idade, nome da mãe, sexo, situação cadastral, e-mails, telefones com operadora/tipo/WhatsApp e endereços — dispensando múltiplas integrações.
6. Resposta padronizada e versionadameta.apiVersion garante compatibilidade; campos novos entram sem breaking changes.
Desafios e o que considerar antes de integrar
1. Rate limiting por IP e chave
Exceder o limite retorna 429 com Retry-After; implemente backoff exponencial e jitter.
2. CPF inválido ou não encontrado
400 para formato inválido; 404 para CPF inexistente na base — trate ambos como "não elegível" no seu fluxo.
3. Saldo insuficiente
402 quando balance zera; sua aplicação deve alertar o time financeiro ou bloquear consultas não essenciais.
4. Latência de rede variávelmeta.executionTimeMs médio ~70 ms, mas picos ocorrem; defina timeouts realistas (ex.: 5 s total, 2 s dial).
5. Dados sensíveis na resposta
Nome, e-mail, telefone e endereço são PII; garanta TLS em trânsito, logs sem corpo da resposta e retenção mínima.
Como implementar com a SmartCPF
Abaixo, uma função ConsultarCPF completa: monta a URL, injeta o header X-API-KEY, faz a requisição com timeout, checa status code, decodifica JSON e retorna struct tipada ou erro descritivo. O main demonstra uso real com variável de ambiente para a chave.
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"time"
)
// Meta contém metadados da resposta da API
type Meta struct {
SearchType string `json:"searchType"`
ConsultID string `json:"consultId"`
User string `json:"user"`
Message string `json:"message"`
IP string `json:"ip"`
Success bool `json:"success"`
APIVersion string `json:"apiVersion"`
Date string `json:"date"`
ExecutionTimeMs float64 `json:"executionTimeMs"`
Balance float64 `json:"balance"`
}
// Phone representa um telefone retornado pela API
type Phone struct {
Number string `json:"number"`
BlockedTelemarketing bool `json:"blockedTelemarketing"`
Operator string `json:"operator"`
Type string `json:"type"`
WhatsApp bool `json:"whatsapp"`
}
// Result contém os dados do CPF consultado
type Result struct {
CPF string `json:"cpf"`
Name string `json:"name"`
BirthDate string `json:"birthDate"`
Age int `json:"age"`
MotherName string `json:"motherName"`
Gender string `json:"gender"`
Status string `json:"status"`
Emails []string `json:"emails"`
Phones []Phone `json:"phones"`
Addresses []string `json:"addresses"`
}
// APIResponse é o envelope completo da resposta
type APIResponse struct {
Meta Meta `json:"meta"`
Result Result `json:"result"`
Success bool `json:"success"`
Errors []string `json:"errors"`
}
// ConsultarCPF realiza a consulta de CPF na SmartCPF v2.
// cpf: apenas números (ex.: "11111111111").
// apiKey: sua chave obtida no painel SmartCPF.
// pkg: pacote de dados (basic, person, contact, address, score, complete).
// Retorna *APIResponse ou erro com detalhes do status HTTP.
func ConsultarCPF(ctx context.Context, cpf, apiKey, pkg string) (*APIResponse, error) {
if apiKey == "" {
return nil, errors.New("X-API-KEY não informada")
}
// Limpa formatação do CPF (remove pontos e traço)
cleanCPF := ""
for _, r := range cpf {
if r >= '0' && r <= '9' {
cleanCPF += string(r)
}
}
if len(cleanCPF) != 11 {
return nil, fmt.Errorf("CPF deve ter 11 dígitos, recebeu %d", len(cleanCPF))
}
baseURL := "https://api.smartcpf.com.br/v2/individuals/" + cleanCPF
u, _ := url.Parse(baseURL)
q := u.Query()
q.Set("package", pkg)
u.RawQuery = q.Encode()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return nil, fmt.Errorf("criar request: %w", err)
}
// Autenticação obrigatória via header X-API-KEY
req.Header.Set("X-API-KEY", apiKey)
req.Header.Set("Accept", "application/json")
req.Header.Set("User-Agent", "smartcpf-go-example/1.0")
client := &http.Client{
Timeout: 5 * time.Second, // timeout total (dial + TLS + response)
}
resp, err := client.Do(req)
if err != nil {
// Erro de rede, DNS, timeout, TLS
return nil, fmt.Errorf("executar request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("ler body: %w", err)
}
// Tratamento por status code
switch resp.StatusCode {
case http.StatusOK: // 200
var data APIResponse
if err := json.Unmarshal(body, &data); err != nil {
return nil, fmt.Errorf("decode JSON: %w", err)
}
if !data.Success || len(data.Errors) > 0 {
return nil, fmt.Errorf("API retornou erro: %v", data.Errors)
}
return &data, nil
case http.StatusBadRequest: // 400 - CPF mal formatado
return nil, errors.New("CPF inválido (formato)")
case http.StatusUnauthorized: // 401 - X-API-KEY ausente ou inválida
return nil, errors.New("autenticação falhou: X-API-KEY inválida")
case http.StatusPaymentRequired: // 402 - saldo zerado
return nil, errors.New("saldo de créditos insuficiente")
case http.StatusNotFound: // 404 - CPF não encontrado na base
return nil, errors.New("CPF não encontrado na base da Receita Federal")
case http.StatusUnprocessableEntity: // 422 - regra de negócio
return nil, errors.New("entidade não processável (regras de negócio)")
case http.StatusTooManyRequests: // 429 - rate limit
retryAfter := resp.Header.Get("Retry-After")
return nil, fmt.Errorf("rate limit excedido, tente novamente em %s segundos", retryAfter)
default:
return nil, fmt.Errorf("status inesperado %d: %s", resp.StatusCode, string(body))
}
}
func main() {
// Em produção, use variável de ambiente ou secret manager
apiKey := os.Getenv("SMARTCP_API_KEY")
if apiKey == "" {
fmt.Println("ERRO: defina a variável de ambiente SMARTCP_API_KEY")
os.Exit(1)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cpf := "11111111111" // apenas números
pkg := "complete" // pacote mais completo
resp, err := ConsultarCPF(ctx, cpf, apiKey, pkg)
if err != nil {
fmt.Printf("Erro na consulta: %v\n", err)
os.Exit(1)
}
// Exemplo de uso dos campos retornados
fmt.Printf("Consulta ID: %s\n", resp.Meta.ConsultID)
fmt.Printf("Saldo restante: %.2f créditos\n", resp.Meta.Balance)
fmt.Printf("Tempo de execução: %.1f ms\n", resp.Meta.ExecutionTimeMs)
fmt.Printf("CPF: %s\n", resp.Result.CPF)
fmt.Printf("Nome: %s\n", resp.Result.Name)
fmt.Printf("Situação: %s\n", resp.Result.Status)
fmt.Printf("Idade: %d anos\n", resp.Result.Age)
fmt.Printf("E-mails: %v\n", resp.Result.Emails)
for _, ph := range resp.Result.Phones {
fmt.Printf("Telefone: %s (%s, %s, WhatsApp: %v)\n",
ph.Number, ph.Operator, ph.Type, ph.WhatsApp)
}
}
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-21T14:30:45.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 acima resolve na prática:
- Rastreabilidade total:
meta.consultIdpermite auditar cada consulta no painel ou suporte. - Controle de custo em tempo real:
meta.balance(ex.: 9.77) mostra créditos restantes após a chamada. - Observabilidade de latência:
meta.executionTimeMs(74.1 ms) alimenta dashboards de SLA. - Decisão de negócio imediata:
result.status("Regular", "Suspenso", "Cancelado", "Nulo") direciona onboarding, crédito ou compliance. - Dados de contato prontos para uso:
result.emails,result.phones(com operadora, tipo e flag WhatsApp) eresult.addresseseliminam necessidade de APIs separadas.
Por que usar a SmartCPF
- Integração em minutos: apenas
net/http+ headerX-API-KEY; sem SDK, sem OAuth, sem fluxo de token. - Latência consistente: média sub-100 ms com SLA de 99,9% de disponibilidade.
- Modelo pay-as-you-go: créditos não expiram; você recarrega quando precisar, sem assinatura mensal.
- Dados oficiais e atualizados: fonte direta da Receita Federal e bureaus parceiros, com cobertura nacional.
- Escalabilidade nativa: a mesma chave atende de dezenas a milhões de consultas/dia sem mudança de código.
Conclusão
Validar CPF em Go com a SmartCPF reduz a complexidade a uma única chamada HTTP autenticada por X-API-KEY, retornando dados cadastrais completos, metadados de auditoria e controle de saldo embutidos. O exemplo com net/http demonstra que não há necessidade de dependências pesadas — o padrão da linguagem já cobre timeouts, contextos, streaming de body e parsing JSON de forma idiomática. 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

Integrando a SmartCPF em runtime Bun: guia rápido
Como consumir a API SmartCPF v2 com Bun nativo: autenticação X-API-KEY, tratamento de erro e parsing de resposta.

Como validar CPF com Node.js e a API SmartCPF
Tutorial prático de validação de CPF em Node.js usando a API SmartCPF v2 com autenticação X-API-KEY.

Como funciona o dígito verificador do CPF: o algoritmo explicado
Entenda o cálculo dos dígitos verificadores do CPF, sua validação matemática e como a API SmartCPF automatiza esse processo.

Verificação de identidade no cadastro de pacientes em clínicas médicas
Como a SmartCPF automatiza a validação de CPF no onboarding de pacientes, reduzindo fraudes e erros manuais em clínicas.
Pronto para validar CPFs em segundos?
Consultas gratuitas para testar agora. Acesso imediato à documentação.