# Como logar e auditar todas as consultas de CPF feitas via API

> Aprenda a implementar logging e auditoria completos para consultas de CPF via API. Exemplos com logs estruturados e conformidade LGPD.

**Publicado:** 19/03/2025
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-logar-e-auditar-todas-as-consultas-de-cpf-feitas-via-api

---


Para logar e auditar consultas de CPF via API, registre em cada requisição: timestamp em UTC, hash SHA-256 do CPF, ID do usuário solicitante, finalidade da consulta, status HTTP, tempo de resposta e IP de origem. Armazene esses registros em formato JSON estruturado, implemente controle de acesso e defina prazo de retenção conforme a LGPD.

## Introdução

Registrar e auditar todas as consultas de CPF realizadas pela sua aplicação é uma exigência tanto de segurança quanto de conformidade regulatória. A LGPD determina que as empresas devem ser capazes de demonstrar quais dados pessoais foram acessados, quando, por quem e com qual finalidade. Além disso, logs bem estruturados são ferramentas indispensáveis para debugging, monitoramento de consumo e investigação de incidentes.

---
## O que registrar em cada consulta

Um registro de auditoria completo deve conter informações suficientes para responder às perguntas: quem consultou, quando, qual CPF, qual o resultado e por quê.

### Campos recomendados para o log de auditoria

| Campo | Descrição | Exemplo |
| --- | --- | --- |
| timestamp | Data e hora da consulta (UTC) | 2025-03-19T14:30:00Z |
| cpf_hash | Hash do CPF (não armazene em texto puro) | sha256:a1b2c3... |
| usuario_id | ID do usuário ou sistema que solicitou | user_12345 |
| finalidade | Motivo da consulta | onboarding, antifraude |
| status_http | Código de resposta da API | 200, 404 |
| sucesso | Se a consulta retornou dados válidos | true/false |
| tempo_resposta_ms | Tempo de resposta da API em milissegundos | 892 |
| ip_origem | IP do cliente que originou a requisição | 192.168.1.100 |
| request_id | Identificador único da requisição | req_abc123 |

---

## Implementação em Python com logs estruturados

```python
import requests
import hashlib
import json
import logging
import time
import uuid
from datetime import datetime, timezone

# Configurar logger estruturado
logger = logging.getLogger("cpf_audit")
logger.setLevel(logging.INFO)
handler = logging.FileHandler("cpf_audit.log")
handler.setFormatter(logging.Formatter("%(message)s"))
logger.addHandler(handler)

def hash_cpf(cpf):
 """Gerar hash do CPF para não armazenar em texto puro"""
 return hashlib.sha256(cpf.encode()).hexdigest()

def consultar_cpf_auditado(cpf, usuario_id, finalidade, ip_origem=None):
 request_id = str(uuid.uuid4())
 inicio = time.time()

 url = f"https://api.cpfhub.io/cpf/{cpf}"
 headers = {
 "x-api-key": "SUA_CHAVE_DE_API",
 "Accept": "application/json"
 }

 registro_auditoria = {
 "timestamp": datetime.now(timezone.utc).isoformat(),
 "request_id": request_id,
 "cpf_hash": hash_cpf(cpf),
 "usuario_id": usuario_id,
 "finalidade": finalidade,
 "ip_origem": ip_origem,
 "status_http": None,
 "sucesso": False,
 "tempo_resposta_ms": None,
 "erro": None
 }

 try:
 response = requests.get(url, headers=headers, timeout=10)
 tempo_ms = round((time.time() - inicio) * 1000)

 registro_auditoria["status_http"] = response.status_code
 registro_auditoria["tempo_resposta_ms"] = tempo_ms

 if response.status_code == 200:
 dados = response.json()
 registro_auditoria["sucesso"] = dados.get("success", False)
 return dados
 else:
 registro_auditoria["erro"] = f"HTTP {response.status_code}"
 return {"erro": f"HTTP {response.status_code}"}

 except requests.exceptions.Timeout:
 tempo_ms = round((time.time() - inicio) * 1000)
 registro_auditoria["tempo_resposta_ms"] = tempo_ms
 registro_auditoria["erro"] = "timeout"
 return {"erro": "Timeout na consulta"}

 except Exception as e:
 registro_auditoria["erro"] = str(e)
 return {"erro": str(e)}

 finally:
 # Registrar SEMPRE, independentemente do resultado
 logger.info(json.dumps(registro_auditoria))

# Uso
resultado = consultar_cpf_auditado(
 cpf="12345678900",
 usuario_id="user_42",
 finalidade="onboarding",
 ip_origem="192.168.1.100"
)
```

---

## Implementação em JavaScript (Node.js)

```javascript
const crypto = require('crypto');
const fs = require('fs');

function hashCPF(cpf) {
 return crypto.createHash('sha256').update(cpf).digest('hex');
}

function registrarAuditoria(registro) {
 const linha = JSON.stringify(registro) + '\n';
 fs.appendFileSync('cpf_audit.log', linha);
}

async function consultarCPFAuditado(cpf, usuarioId, finalidade, ipOrigem) {
 const requestId = crypto.randomUUID();
 const inicio = Date.now();

 const registroAuditoria = {
 timestamp: new Date().toISOString(),
 requestId,
 cpfHash: hashCPF(cpf),
 usuarioId,
 finalidade,
 ipOrigem,
 statusHttp: null,
 sucesso: false,
 tempoRespostaMs: null,
 erro: null
 };

 const controller = new AbortController();
 const timeoutId = setTimeout(() => controller.abort(), 10000);

 try {
 const response = await fetch(
 `https://api.cpfhub.io/cpf/${cpf}`,
 {
 headers: {
 'x-api-key': 'SUA_CHAVE_DE_API',
 'Accept': 'application/json'
 },
 signal: controller.signal
 }
 );

 clearTimeout(timeoutId);

 registroAuditoria.statusHttp = response.status;
 registroAuditoria.tempoRespostaMs = Date.now() - inicio;

 if (response.ok) {
 const dados = await response.json();
 registroAuditoria.sucesso = dados.success || false;
 return dados;
 }

 registroAuditoria.erro = `HTTP ${response.status}`;
 return { erro: `HTTP ${response.status}` };

 } catch (error) {
 clearTimeout(timeoutId);
 registroAuditoria.tempoRespostaMs = Date.now() - inicio;
 registroAuditoria.erro = error.name === 'AbortError'
 ? 'timeout'
 : error.message;
 return { erro: registroAuditoria.erro };

 } finally {
 registrarAuditoria(registroAuditoria);
 }
}
```

---

## Proteção de dados no log (LGPD)

A LGPD exige cuidado especial com dados pessoais armazenados em logs:

* **Nunca registre o CPF em texto puro** -- Use hash SHA-256. Isso permite correlacionar consultas do mesmo CPF sem expor o número.

* **Não registre o nome retornado** -- O log de auditoria deve conter apenas metadados da consulta, não os dados pessoais retornados.

* **Defina período de retenção** -- Logs de auditoria devem ter prazo definido de armazenamento. A recomendação é de 1 a 5 anos, conforme a legislação aplicável ao seu setor.

* **Controle o acesso aos logs** -- Apenas pessoas autorizadas devem ter acesso aos registros de auditoria.

* **Criptografe os logs em repouso** -- Use criptografia de disco ou de arquivo para proteger os registros armazenados.

A [Autoridade Nacional de Proteção de Dados (ANPD)](https://www.gov.br/anpd) orienta que o controlador deve manter registros das operações de tratamento, especialmente quando o tratamento se basear em legítimo interesse ou quando envolver dados de crianças.

---

## Armazenamento de longo prazo

Para volumes elevados de consultas, considere usar um banco de dados ou serviço dedicado em vez de arquivos de texto:

| Opção | Vantagens | Quando usar |
| --- | --- | --- |
| Arquivo de log (JSON Lines) | Simples, sem dependência | Até ~10.000 consultas/mês |
| Banco relacional (PostgreSQL) | Consultas SQL, índices | 10.000-100.000 consultas/mês |
| Elasticsearch / OpenSearch | Busca full-text, dashboards | Acima de 100.000 consultas/mês |
| Serviço gerenciado (CloudWatch, Datadog) | Zero infra, alertas nativos | Qualquer volume |

---

## Gerando relatórios de auditoria

Com logs estruturados em JSON, é simples gerar relatórios para auditorias internas ou externas:

```python
import json
from collections import Counter
from datetime import datetime

def gerar_relatorio(arquivo_log, mes_referencia):
 consultas = []

 with open(arquivo_log, 'r') as f:
 for linha in f:
 registro = json.loads(linha.strip())
 data = datetime.fromisoformat(registro["timestamp"])
 if data.strftime("%Y-%m") == mes_referencia:
 consultas.append(registro)

 total = len(consultas)
 sucessos = sum(1 for c in consultas if c["sucesso"])
 falhas = total - sucessos

 finalidades = Counter(c["finalidade"] for c in consultas)
 tempos = [c["tempo_resposta_ms"] for c in consultas if c["tempo_resposta_ms"]]
 tempo_medio = sum(tempos) / len(tempos) if tempos else 0

 return {
 "mes": mes_referencia,
 "total_consultas": total,
 "sucessos": sucessos,
 "falhas": falhas,
 "taxa_sucesso": f"{(sucessos/total*100):.1f}%" if total > 0 else "N/A",
 "tempo_medio_ms": round(tempo_medio),
 "consultas_por_finalidade": dict(finalidades),
 "usuarios_unicos": len(set(c["usuario_id"] for c in consultas))
 }

relatorio = gerar_relatorio("cpf_audit.log", "2025-03")
print(json.dumps(relatorio, indent=2))
```

---

## Perguntas frequentes

### O que deve ser registrado no log de auditoria de consultas de CPF?
Registre sempre: timestamp em UTC, hash SHA-256 do CPF (nunca o número em texto puro), ID do usuário ou sistema solicitante, finalidade da consulta, código de status HTTP da resposta, tempo de resposta em milissegundos, IP de origem e um identificador único da requisição. Esses campos permitem rastrear cada acesso sem expor dados pessoais.

### Como a LGPD afeta o armazenamento de logs de consultas de CPF?
A LGPD exige que você documente quais dados foram acessados, quando e com qual finalidade — o log de auditoria cumpre exatamente essa função. O CPF não deve ser armazenado em texto puro nos logs; use hash SHA-256. Defina um prazo de retenção (tipicamente 1 a 5 anos conforme o setor) e restrinja o acesso aos registros a pessoas autorizadas.

### A API CPFHub.io retorna erro quando o limite de consultas é atingido?
Não. A CPFHub.io nunca bloqueia requisições nem retorna HTTP 429. Quando o limite do plano é ultrapassado, cada consulta adicional é cobrada a R$0,15. O plano gratuito inclui 50 consultas mensais sem cartão de crédito; o plano Pro oferece 1.000 consultas por R$149/mês.

### Quanto tempo leva para implementar um sistema de auditoria de consultas de CPF?
Uma implementação básica — hash do CPF, log em JSON e registro do status HTTP — leva menos de uma hora com os exemplos deste artigo. Para ambientes de produção com alto volume, adicione um banco de dados ou serviço de observabilidade dedicado como CloudWatch ou Datadog, o que pode levar entre meio dia e dois dias de trabalho.

### Leia também

- [LGPD: CPF é dado pessoal sensível ou não? Entenda a classificação correta](https://cpfhub.io/blog/lgpd-cpf-e-dado-pessoal-sensivel-ou-nao-entenda-a-classificacao-correta)
- [Retenção de dados de CPF: por quanto tempo é permitido armazenar](https://cpfhub.io/blog/retencao-de-dados-de-cpf-por-quanto-tempo-e-permitido-armazenar)
- [KYC no Brasil: quais setores são obrigados a validar CPF por lei](https://cpfhub.io/blog/kyc-no-brasil-quais-setores-sao-obrigados-a-validar-cpf-por-lei)
- [Anonimização e pseudonimização de CPF: técnicas e quando aplicar](https://cpfhub.io/blog/anonimizacao-e-pseudonimizacao-de-cpf-tecnicas-e-quando-aplicar)

---

## Conclusão

Logar e auditar consultas de CPF é uma prática obrigatória para conformidade com a LGPD e essencial para monitoramento operacional. Com logs estruturados em JSON, hashing do CPF e registros completos de cada consulta, sua aplicação estará preparada tanto para auditorias regulatórias quanto para investigação de incidentes.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/) — 50 consultas mensais gratuitas, sem cartão de crédito — e tenha todos os registros de auditoria integrados ao seu sistema de conformidade LGPD em minutos.

