Como usar validação de CPF para segmentar clientes por perfil de risco

Aprenda a usar validação de CPF via API para criar perfis de risco de clientes em e-commerce e tomar decisões antifraude inteligentes.

Redação CPFHub.io
Redação CPFHub.io
··12 min de leitura
Como usar validação de CPF para segmentar clientes por perfil de risco

Para segmentar clientes por perfil de risco usando CPF, consulte a API de validação no momento do cadastro ou da compra, cruzando nome, data de nascimento e histórico comportamental interno. A combinação desses dados permite classificar cada cliente em níveis de confiança (verde, amarelo, laranja, vermelho) e aplicar políticas diferenciadas de checkout e limite de crédito sem prejudicar clientes legítimos.

No e-commerce, nem todos os clientes representam o mesmo nível de risco. Um cliente recorrente que compra há anos e nunca contestou um pedido é fundamentalmente diferente de uma conta nova que faz uma compra de alto valor na primeira interação. Tratar todos da mesma forma — aplicando o mesmo nível de verificação a todos — resulta em excesso de fricção para bons clientes e segurança insuficiente para os suspeitos.

A segmentação por perfil de risco resolve esse dilema. Usando o CPF como chave, combinado com dados da API da CPFHub.io, é possível construir um score dinâmico que adapta o nível de verificação ao histórico e ao contexto de cada transação.


Os pilares da segmentação de risco

Dados de identidade

Os dados retornados pela API da CPFHub.io — nome completo, data de nascimento e gênero — formam a base da verificação de identidade. A correspondência entre o nome informado pelo cliente e o nome cadastrado no CPF é o primeiro filtro de confiança.

Histórico comportamental

O comportamento passado do cliente na plataforma é o preditor mais forte de risco futuro. Frequência de compras, valores, método de pagamento, taxa de devolução e histórico de disputas compõem um perfil comportamental rico.

Dados contextuais

Cada transação traz informações contextuais: dispositivo utilizado, localização geográfica, horário da compra, endereço de entrega. Esses dados, cruzados com o perfil do CPF, revelam anomalias.


Níveis de risco

O sistema opera com quatro níveis de risco, cada um com políticas específicas.

Nível verde — confiável

Clientes com CPF verificado, histórico longo na plataforma, sem disputas, padrão de compra consistente. Políticas: checkout simplificado, limites de crédito elevados, prioridade na entrega.

Nível amarelo — atenção

Clientes com CPF verificado mas pouco histórico, ou com histórico misto (algumas devoluções, compras irregulares). Políticas: checkout padrão, limites de crédito moderados, monitoramento de transações.

Nível laranja — alerta

Clientes com inconsistências nos dados, histórico recente de disputas, ou padrões atípicos de compra. Políticas: verificação adicional em compras acima de um limite, restrição em métodos de pagamento, revisão manual para pedidos de alto valor.

Nível vermelho — alto risco

Clientes com CPF não verificado ou com múltiplas inconsistências, histórico de chargebacks ou proximidade com CPFs banidos. Políticas: checkout restrito (apenas métodos pré-pagos), limites baixos, revisão manual obrigatória.


Implementação em Python

O exemplo a seguir demonstra um motor de segmentação de risco baseado em CPF.

import requests
import re
from datetime import datetime, timedelta
from typing import Optional
from dataclasses import dataclass, field
import json

CPFHUB_API_URL = "https://api.cpfhub.io/cpf"
CPFHUB_API_KEY = "SUA_CHAVE_DE_API"
REQUEST_TIMEOUT = 10 # segundos

@dataclass
class PerfilRisco:
    cpf: str
    nome: str
    nivel: str # VERDE, AMARELO, LARANJA, VERMELHO
    score: float # 0 a 100
    fatores_positivos: list = field(default_factory=list)
    fatores_negativos: list = field(default_factory=list)
    politicas: dict = field(default_factory=dict)
    calculado_em: str = ""

# Simulação de histórico interno
historicos = {
    "12345678909": {
    "total_compras": 47,
    "total_gasto": 23500.00,
    "membro_desde": "2022-03-15",
    "disputas": 0,
    "chargebacks": 0,
    "devolucoes": 2,
    "ultima_compra": "2026-04-01",
    "metodo_pagamento_principal": "CARTAO_CREDITO",
    "enderecos_distintos": 2,
    "dispositivos_distintos": 3,
    },
    "98765432100": {
    "total_compras": 1,
    "total_gasto": 3499.00,
    "membro_desde": "2026-04-03",
    "disputas": 0,
    "chargebacks": 0,
    "devolucoes": 0,
    "ultima_compra": "2026-04-03",
    "metodo_pagamento_principal": "PIX",
    "enderecos_distintos": 1,
    "dispositivos_distintos": 1,
    },
}

def consultar_cpf(cpf: str) -> Optional[dict]:
    """Consulta CPF na API CPFHub.io."""
    cpf_limpo = re.sub(r"\D", "", cpf)

    try:
    response = requests.get(
    f"{CPFHUB_API_URL}/{cpf_limpo}",
    headers={
    "x-api-key": CPFHUB_API_KEY,
    "Accept": "application/json",
    },
    timeout=REQUEST_TIMEOUT,
    )
    response.raise_for_status()
    dados = response.json()

    if dados.get("success"):
    return dados["data"]
    return None

    except requests.exceptions.Timeout:
    raise Exception("Timeout na consulta de CPF")
    except requests.exceptions.HTTPError as e:
    status = e.response.status_code
    if status == 404:
    return None
    if status == 401:
    raise Exception("API key inválida")
    raise Exception(f"Erro HTTP {status}")
    except requests.exceptions.RequestException:
    raise Exception("Erro de conexão")

def calcular_score_identidade(dados_cpf: dict, nome_informado: str) -> dict:
    """Calcula o score de identidade baseado nos dados da API."""

    score = 0
    fatores_pos = []
    fatores_neg = []

    # CPF encontrado na API
    if dados_cpf:
    score += 30
    fatores_pos.append("CPF válido e encontrado na base (+30)")

    # Correspondência de nome
    import unicodedata
    nome_api = unicodedata.normalize("NFKD", dados_cpf.get("name", ""))
    nome_api = nome_api.encode("ASCII", "ignore").decode("ASCII").upper()
    nome_info = unicodedata.normalize("NFKD", nome_informado)
    nome_info = nome_info.encode("ASCII", "ignore").decode("ASCII").upper()

    partes_api = nome_api.split()
    partes_info = nome_info.split()

    if partes_api and partes_info:
    if partes_api[0] == partes_info[0]:
    score += 10
    fatores_pos.append("Primeiro nome corresponde ao CPF (+10)")
    else:
    score -= 20
    fatores_neg.append("Primeiro nome difere do CPF (-20)")

    if partes_api[-1] == partes_info[-1]:
    score += 10
    fatores_pos.append("Último nome corresponde ao CPF (+10)")
    else:
    score -= 10
    fatores_neg.append("Último nome difere do CPF (-10)")

    # Idade
    ano_nasc = dados_cpf.get("year", 0)
    if ano_nasc:
    idade = datetime.now().year - ano_nasc
    if 25 <= idade <= 60:
    score += 5
    fatores_pos.append(f"Faixa etária comum ({idade} anos) (+5)")
    elif idade < 18:
    score -= 30
    fatores_neg.append(f"Menor de idade ({idade} anos) (-30)")
    else:
    score -= 40
    fatores_neg.append("CPF não encontrado na base (-40)")

    return {
    "score": score,
    "fatores_positivos": fatores_pos,
    "fatores_negativos": fatores_neg,
    }

def calcular_score_comportamental(historico: dict) -> dict:
    """Calcula o score baseado no histórico na plataforma."""

    score = 0
    fatores_pos = []
    fatores_neg = []

    if not historico:
    fatores_neg.append("Sem histórico na plataforma (0)")
    return {
    "score": score,
    "fatores_positivos": fatores_pos,
    "fatores_negativos": fatores_neg,
    }

    # Antiguidade da conta
    membro_desde = datetime.fromisoformat(historico["membro_desde"])
    dias_membro = (datetime.now() - membro_desde).days

    if dias_membro > 365:
    score += 20
    fatores_pos.append(f"Cliente há mais de 1 ano ({dias_membro} dias) (+20)")
    elif dias_membro > 180:
    score += 10
    fatores_pos.append(f"Cliente há mais de 6 meses (+10)")
    elif dias_membro < 7:
    score -= 10
    fatores_neg.append(f"Conta criada há menos de 7 dias (-10)")

    # Volume de compras
    total_compras = historico.get("total_compras", 0)
    if total_compras >= 20:
    score += 15
    fatores_pos.append(f"Cliente frequente ({total_compras} compras) (+15)")
    elif total_compras >= 5:
    score += 8
    fatores_pos.append(f"Cliente ativo ({total_compras} compras) (+8)")

    # Disputas e chargebacks
    disputas = historico.get("disputas", 0)
    chargebacks = historico.get("chargebacks", 0)

    if chargebacks > 0:
    score -= chargebacks * 25
    fatores_neg.append(f"{chargebacks} chargeback(s) (-{chargebacks * 25})")

    if disputas > 0 and total_compras > 0:
    taxa_disputa = disputas / total_compras
    if taxa_disputa > 0.1:
    score -= 20
    fatores_neg.append(f"Taxa de disputa alta ({taxa_disputa:.0%}) (-20)")
    elif taxa_disputa > 0.05:
    score -= 10
    fatores_neg.append(f"Taxa de disputa moderada ({taxa_disputa:.0%}) (-10)")
    elif disputas == 0 and total_compras >= 5:
    score += 10
    fatores_pos.append("Zero disputas com 5+ compras (+10)")

    # Devoluções
    devolucoes = historico.get("devolucoes", 0)
    if devolucoes > 0 and total_compras > 0:
    taxa_devolucao = devolucoes / total_compras
    if taxa_devolucao > 0.2:
    score -= 10
    fatores_neg.append(f"Taxa de devolução alta ({taxa_devolucao:.0%}) (-10)")

    # Endereços e dispositivos
    enderecos = historico.get("enderecos_distintos", 1)
    if enderecos > 5:
    score -= 10
    fatores_neg.append(f"Muitos endereços distintos ({enderecos}) (-10)")

    return {
    "score": score,
    "fatores_positivos": fatores_pos,
    "fatores_negativos": fatores_neg,
    }

def classificar_risco(score_total: float) -> dict:
    """Classifica o nível de risco e define políticas."""

    if score_total >= 70:
    return {
    "nivel": "VERDE",
    "descricao": "Cliente confiável",
    "politicas": {
    "checkout": "SIMPLIFICADO",
    "limiteCredito": 5000,
    "revisaoManual": False,
    "metodosPagamento": ["CARTAO", "PIX", "BOLETO", "CREDITO_LOJA"],
    "prioridadeEntrega": True,
    },
    }
    elif score_total >= 40:
    return {
    "nivel": "AMARELO",
    "descricao": "Atenção moderada",
    "politicas": {
    "checkout": "PADRAO",
    "limiteCredito": 1000,
    "revisaoManual": False,
    "metodosPagamento": ["CARTAO", "PIX", "BOLETO"],
    "prioridadeEntrega": False,
    },
    }
    elif score_total >= 20:
    return {
    "nivel": "LARANJA",
    "descricao": "Alerta — verificação adicional recomendada",
    "politicas": {
    "checkout": "REFORÇADO",
    "limiteCredito": 200,
    "revisaoManual": True,
    "revisaoAcimaDe": 500,
    "metodosPagamento": ["CARTAO", "PIX"],
    "prioridadeEntrega": False,
    },
    }
    else:
    return {
    "nivel": "VERMELHO",
    "descricao": "Alto risco — restrições aplicadas",
    "politicas": {
    "checkout": "RESTRITO",
    "limiteCredito": 0,
    "revisaoManual": True,
    "revisaoAcimaDe": 100,
    "metodosPagamento": ["PIX"],
    "prioridadeEntrega": False,
    },
    }

def segmentar_cliente(
    cpf: str,
    nome_informado: str,
    dados_transacao: dict = None,
) -> dict:
    """Segmenta um cliente por perfil de risco."""

    cpf_limpo = re.sub(r"\D", "", cpf)

    # Consulta CPF na API
    dados_cpf = None
    try:
    dados_cpf = consultar_cpf(cpf_limpo)
    except Exception as e:
    return {
    "erro": f"Falha na consulta de CPF: {str(e)}",
    "nivel_default": "LARANJA",
    }

    # Score de identidade
    identidade = calcular_score_identidade(dados_cpf, nome_informado)

    # Score comportamental
    historico = historicos.get(cpf_limpo, None)
    comportamento = calcular_score_comportamental(historico)

    # Score contextual (baseado na transação atual)
    score_contextual = 0
    fatores_ctx_pos = []
    fatores_ctx_neg = []

    if dados_transacao:
    valor = dados_transacao.get("valor", 0)

    # Valor muito acima da média
    if historico:
    media = historico.get("total_gasto", 0) / max(
    historico.get("total_compras", 1), 1
    )
    if valor > media * 3 and media > 0:
    score_contextual -= 15
    fatores_ctx_neg.append(
    f"Valor ({valor:.2f}) muito acima da média ({media:.2f}) (-15)"
    )
    elif valor > 1000:
    score_contextual -= 10
    fatores_ctx_neg.append(
    f"Primeira compra com valor alto (R$ {valor:.2f}) (-10)"
    )

    # Score total (normalizado para 0-100)
    score_bruto = (
    identidade["score"]
    + comportamento["score"]
    + score_contextual
    )
    score_total = max(0, min(100, score_bruto + 50)) # Centraliza em 50

    # Classificação
    classificacao = classificar_risco(score_total)

    # Monta perfil completo
    perfil = PerfilRisco(
    cpf=cpf_limpo[:3] + ".***.***-" + cpf_limpo[-2:],
    nome=dados_cpf.get("name", nome_informado) if dados_cpf else nome_informado,
    nivel=classificacao["nivel"],
    score=score_total,
    fatores_positivos=(
    identidade["fatores_positivos"]
    + comportamento["fatores_positivos"]
    + fatores_ctx_pos
    ),
    fatores_negativos=(
    identidade["fatores_negativos"]
    + comportamento["fatores_negativos"]
    + fatores_ctx_neg
    ),
    politicas=classificacao["politicas"],
    calculado_em=datetime.now().isoformat(),
    )

    return {
    "perfil": {
    "cpf": perfil.cpf,
    "nome": perfil.nome,
    "nivel": perfil.nivel,
    "descricao": classificacao["descricao"],
    "score": perfil.score,
    },
    "analise": {
    "fatoresPositivos": perfil.fatores_positivos,
    "fatoresNegativos": perfil.fatores_negativos,
    },
    "politicas": perfil.politicas,
    "calculadoEm": perfil.calculado_em,
    }

# Exemplo de uso
if __name__ == "__main__":
    # Cliente antigo e confiável
    print("--- Cliente Confiável ---")
    r1 = segmentar_cliente(
    cpf="123.456.789-09",
    nome_informado="João da Silva",
    dados_transacao={"valor": 350.00},
    )
    print(json.dumps(r1, indent=2, ensure_ascii=False))

    # Cliente novo com compra alta
    print("\n--- Cliente Novo ---")
    r2 = segmentar_cliente(
    cpf="987.654.321-00",
    nome_informado="Pedro Santos",
    dados_transacao={"valor": 3499.00},
    )
    print(json.dumps(r2, indent=2, ensure_ascii=False))

Aplicação das políticas por nível

Cada nível de risco aciona políticas específicas que equilibram segurança e experiência do usuário.

Checkout diferenciado

Clientes verdes passam por um checkout simplificado, com menos etapas e menos verificações. Clientes vermelhos enfrentam um checkout mais rigoroso, com verificação adicional de identidade e restrição de métodos de pagamento.

Limites dinâmicos

Limites de crédito, valores máximos por pedido e quantidade máxima de itens variam conforme o nível de risco. Isso permite que clientes confiáveis operem com liberdade enquanto clientes de alto risco são automaticamente limitados.

Revisão manual seletiva

Em vez de revisar manualmente todos os pedidos acima de um valor fixo, a revisão manual é acionada apenas para clientes com nível de risco laranja ou vermelho. Isso reduz drasticamente o volume de revisões sem comprometer a segurança.


Evolução dinâmica do perfil

O perfil de risco não é estático. Ele evolui conforme o comportamento do cliente muda ao longo do tempo.

Um cliente novo começa naturalmente com score mais baixo (amarelo ou laranja) devido à falta de histórico. À medida que realiza compras sem problemas, acumula fatores positivos e migra para níveis mais favoráveis. Por outro lado, um cliente que começa como verde pode migrar para amarelo ou laranja após uma disputa ou chargeback.

Essa evolução dinâmica garante que o sistema se adapta continuamente à realidade, sem intervenção manual.


Métricas de eficácia

Para avaliar se a segmentação está funcionando, monitore as métricas por nível de risco.

A taxa de fraude por nível deve mostrar que clientes verdes têm taxa de fraude significativamente menor que vermelhos. Se não houver diferença, o modelo precisa ser recalibrado. A taxa de falso positivo por nível indica quantos clientes legítimos estão sendo classificados incorretamente como alto risco. A taxa de conversão por nível revela o impacto das políticas restritivas nas vendas — o objetivo é que clientes verdes tenham alta conversão enquanto vermelhos têm conversão menor mas com fraude controlada.

A FEBRABAN recomenda que sistemas antifraude no varejo digital revisem seus modelos de scoring ao menos trimestralmente, ajustando pesos conforme a sazonalidade e os padrões de fraude mais recentes.


Perguntas frequentes

Quais dados da API de CPF são usados na segmentação por perfil de risco?

A API retorna nome completo, data de nascimento e gênero. Na segmentação, o dado mais relevante é o nome: a correspondência entre o nome informado no cadastro e o nome no CPF é o primeiro filtro de confiança. A data de nascimento serve para detectar inconsistências de idade (ex: menor de 18 anos em compras que exigem maioridade).

Como o sistema distingue um cliente novo legítimo de um fraudador?

Clientes novos sem histórico recebem score neutro e são classificados como amarelo por padrão. O que eleva o alerta para laranja ou vermelho são inconsistências combinadas: nome diferente do CPF, valor de compra muito acima da média do produto, endereço de entrega em cidade diferente do IP e método de pagamento de alto risco (ex: cartão pré-pago). Nenhum fator isolado define o nível — é a combinação que importa.

Com que frequência devo recalcular o perfil de risco de cada cliente?

O score deve ser recalculado a cada transação, pois o contexto muda (valor, horário, dispositivo). O histórico comportamental pode ser atualizado diariamente em batch. Perfis com chargeback ou disputa aberta devem ser reclassificados imediatamente, sem aguardar o ciclo de atualização.

A CPFHub.io bloqueia consultas quando o limite do plano é atingido?

Não. A API nunca bloqueia. Quando o limite mensal do plano é atingido, cada consulta adicional é cobrada a R$0,15 — o serviço continua operando normalmente. Isso é especialmente importante em modelos de segmentação em tempo real, onde uma consulta bloqueada pode forçar uma decisão sem dados de identidade.


Conclusão

A segmentação de clientes por perfil de risco baseada em CPF é uma estratégia que equilibra segurança e experiência do usuário de forma inteligente. Em vez de aplicar políticas uniformes que frustram clientes bons e ainda assim deixam passar fraudadores, o sistema adapta a verificação ao nível de confiança de cada cliente — com base em dados reais de identidade e comportamento.

A API da CPFHub.io fornece os dados de identidade necessários em ~900ms, sem bloquear o fluxo de compra. Com o plano gratuito (50 consultas/mês, sem cartão), você já consegue prototipar o motor de segmentação completo antes de ir para produção.

Cadastre-se em cpfhub.io e comece a segmentar com dados reais hoje mesmo.

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