Para consumir a API de CPF da CPFHub.io em Go, use a biblioteca padrão net/http com context.WithTimeout, deserialize o JSON de resposta em structs tipadas e trate erros com variáveis sentinela. Nenhuma dependência externa é necessária — o código completo abaixo cobre autenticação via header x-api-key, timeout configurável e processamento em lote com controle de rate limit.
Introdução
A linguagem Go (Golang) é reconhecida pela sua simplicidade, performance e excelente suporte nativo para operações de rede. A biblioteca padrão net/http é suficiente para consumir APIs REST sem necessidade de dependências externas, o que a torna uma escolha popular para microserviços, CLIs e ferramentas de automação.
Para aplicações que operam no mercado brasileiro, a validação de CPF via API é um requisito frequente. A CPFHub.io fornece um endpoint simples e bem documentado que se integra naturalmente ao estilo idiomático de Go.
Pré-requisitos
- Go 1.21+ -- Instalado e configurado.
- Conta na CPFHub.io -- Para obter a chave de API. O plano gratuito oferece 50 consultas/mês.
Inicializando o módulo
mkdir cpfhub-go && cd cpfhub-go
go mod init cpfhub-go
Modelando a resposta da API
Defina as structs que representam o JSON retornado:
package main
type CpfResponse struct {
Success bool `json:"success"`
Data CpfData `json:"data"`
}
type CpfData struct {
Cpf string `json:"cpf"`
Name string `json:"name"`
NameUpper string `json:"nameUpper"`
Gender string `json:"gender"`
BirthDate string `json:"birthDate"`
Day int `json:"day"`
Month int `json:"month"`
Year int `json:"year"`
}
Resposta esperada da API:
{
"success": true,
"data": {
"cpf": "12345678900",
"name": "João da Silva",
"nameUpper": "JOÃO DA SILVA",
"gender": "M",
"birthDate": "15/06/1990",
"day": 15,
"month": 6,
"year": 1990
}
}
Implementação com net/http
Abaixo está a implementação completa com tratamento de erros, timeout e validação:
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"regexp"
"time"
)
var (
ErrCpfInvalido = fmt.Errorf("CPF inválido: informe 11 dígitos numéricos")
ErrCpfNaoEncontrado = fmt.Errorf("CPF não encontrado na base de dados")
ErrTimeout = fmt.Errorf("a requisição excedeu o tempo limite")
)
type CpfClient struct {
httpClient *http.Client
apiKey string
baseURL string
}
func NewCpfClient(apiKey string) *CpfClient {
return &CpfClient{
httpClient: &http.Client{
Timeout: 10 * time.Second,
},
apiKey: apiKey,
baseURL: "https://api.cpfhub.io",
}
}
func (c *CpfClient) ConsultarCpf(ctx context.Context, cpf string) (*CpfData, error) {
re := regexp.MustCompile(`\D`)
cpfLimpo := re.ReplaceAllString(cpf, "")
if len(cpfLimpo) != 11 {
return nil, ErrCpfInvalido
}
url := fmt.Sprintf("%s/cpf/%s", c.baseURL, cpfLimpo)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("erro ao criar requisição: %w", err)
}
req.Header.Set("x-api-key", c.apiKey)
req.Header.Set("Accept", "application/json")
resp, err := c.httpClient.Do(req)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
return nil, ErrTimeout
}
return nil, fmt.Errorf("erro na requisição HTTP: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("erro ao ler resposta: %w", err)
}
switch resp.StatusCode {
case http.StatusOK:
// Continua processamento abaixo
case http.StatusBadRequest:
return nil, ErrCpfInvalido
case http.StatusUnauthorized:
return nil, fmt.Errorf("chave de API inválida ou ausente")
default:
return nil, fmt.Errorf("erro HTTP %d: %s", resp.StatusCode, string(body))
}
var cpfResp CpfResponse
if err := json.Unmarshal(body, &cpfResp); err != nil {
return nil, fmt.Errorf("erro ao decodificar JSON: %w", err)
}
if !cpfResp.Success {
return nil, ErrCpfNaoEncontrado
}
return &cpfResp.Data, nil
}
func main() {
apiKey := os.Getenv("CPFHUB_API_KEY")
if apiKey == "" {
apiKey = "SUA_CHAVE_DE_API"
}
client := NewCpfClient(apiKey)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
dados, err := client.ConsultarCpf(ctx, "12345678900")
if err != nil {
fmt.Fprintf(os.Stderr, "Erro: %v\n", err)
os.Exit(1)
}
fmt.Printf("Nome: %s\n", dados.Name)
fmt.Printf("CPF: %s\n", dados.Cpf)
fmt.Printf("Nascimento: %s\n", dados.BirthDate)
fmt.Printf("Gênero: %s\n", dados.Gender)
}
Tratamento de erros idiomático em Go
Em Go, o tratamento de erros é explícito e faz parte do fluxo normal do programa. A abordagem utilizada neste exemplo segue as melhores práticas descritas no Effective Go:
-
Erros sentinela --
ErrCpfInvalidoeErrTimeoutsão variáveis de erro pré-definidas que facilitam a comparação comerrors.Is(). -
Wrapping de erros --
fmt.Errorf("... %w", err)preserva o erro original, permitindo unwrapping em camadas superiores. -
Context com timeout -- O
context.WithTimeoutgarante que a requisição não ultrapasse o tempo limite, independentemente do timeout do HTTP client.
Verificando tipos de erro no chamador
import "errors"
dados, err := client.ConsultarCpf(ctx, cpf)
if err != nil {
if errors.Is(err, ErrCpfInvalido) {
// Tratar CPF inválido — retornar erro de validação ao usuário
} else if errors.Is(err, ErrTimeout) {
// Notificar timeout — considerar retry com backoff
} else {
// Erro genérico — logar e retornar erro interno
}
}
Processamento em lote com goroutines
Para validar múltiplos CPFs com controle de concorrência e respeito ao rate limit:
func validarLote(client *CpfClient, cpfs []string) []CpfData {
var resultados []CpfData
for _, cpf := range cpfs {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
dados, err := client.ConsultarCpf(ctx, cpf)
cancel()
if err != nil {
fmt.Fprintf(os.Stderr, "CPF %s: %v\n", cpf, err)
continue
}
resultados = append(resultados, *dados)
// Respeitar rate limit (plano gratuito: 1 req/2s)
time.Sleep(2 * time.Second)
}
return resultados
}
Testando com cURL
curl -X GET https://api.cpfhub.io/cpf/12345678900 \
-H "x-api-key: SUA_CHAVE_DE_API" \
-H "Accept: application/json" \
--max-time 10
Boas práticas
-
Context -- Sempre passe
context.Contextpara funções que fazem I/O, permitindo cancelamento e timeout. -
Timeout duplo -- Configure timeout tanto no
http.Clientquanto nocontext.WithTimeoutpara redundância. -
Variáveis de ambiente -- Armazene a chave de API em variáveis de ambiente (
CPFHUB_API_KEY), não no código. -
Rate limit -- No plano gratuito, 1 requisição a cada 2 segundos e 50 consultas/mês. O plano Pro oferece 1 req/s e 1.000 consultas por R$149/mês; ao ultrapassar o limite, o serviço continua ativo e cobra R$0,15 por consulta extra.
-
Sem dependências externas -- A biblioteca padrão
net/httpé suficiente para a maioria dos casos de uso.
Perguntas frequentes
Por que usar net/http em vez de um cliente HTTP de terceiros em Go?
A biblioteca padrão net/http do Go é madura, bem documentada e não adiciona dependências externas ao módulo. Para consumir um endpoint simples como o da CPFHub.io — uma única chamada GET com header de autenticação — ela oferece controle total sobre timeout, context e tratamento de erros sem overhead desnecessário.
Como lidar com o limite de consultas do plano gratuito em Go?
No plano gratuito, a CPFHub.io permite 1 req a cada 2 segundos e 50 consultas por mês. No processamento em lote, adicione time.Sleep(2 * time.Second) entre chamadas. Ao ultrapassar as 50 consultas mensais, a API não bloqueia — no plano Pro, o excedente é cobrado automaticamente a R$0,15 por consulta.
Como o context.WithTimeout interage com o Timeout do http.Client?
Os dois timeouts são independentes e complementares. O http.Client.Timeout cobre toda a vida da requisição (DNS, conexão, leitura). O context.WithTimeout permite cancelar a operação a partir de qualquer camada acima — útil quando a função de consulta faz parte de um pipeline maior com prazo global definido.
Como adaptar este código para uso em microserviços Go com Gin?
Encapsule o CpfClient como dependência injetada no handler do Gin, reutilizando a mesma instância entre requisições (o http.Client é thread-safe). Passe o c.Request.Context() do Gin diretamente para ConsultarCpf() para que o cancelamento da requisição HTTP propague corretamente pelo pipeline.
Conclusão
Consumir a API de consulta de CPF da CPFHub.io em Go é direto e idiomático: structs tipadas para deserializar o JSON, erros sentinela para tratamento granular e context.WithTimeout para controle de prazo. A biblioteca padrão net/http é tudo que você precisa para uma integração robusta 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 ao seu serviço Go em menos de 30 minutos com o código deste guia.
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.



