PEP e listas restritivas
PEP e listas restritivas
O módulo pep_sancoes confere o CPF e o nome lidos do documento contra listas oficiais de pessoas expostas politicamente e de sanções. Ele exige Verificação de Identidade + Face Match + Liveness no mesmo flow: o dado consultado vem do documento apresentado por quem está vivo na frente da câmera, nunca de um CPF digitado. O widget não ganha nenhum passo novo.
review, com a evidência (lista, referência da entrada, score e motivo) no webhook, para a sua análise decidir. Nunca a denied automático.Cobertura desta fase, e nada além dela: PEP federal e expulsões da administração federal (CGU: PEP e CEAF), empresas e pessoas inidôneas ou punidas (CGU: CEIS e CNEP) e as listas internacionais de sanções da ONU (obrigatória no Brasil pela Lei 13.810/2019), do OFAC (Tesouro dos EUA) e do Reino Unido (UK Sanctions List, do FCDO). Não estão incluídos, e não os anunciamos: a lista de sanções da União Europeia (a fonte exige uma credencial que ainda não temos, então ela nasce desabilitada e sai marcada como tal em dataset_versions), parentes e associados de PEP, PEP estadual/municipal, PEP estrangeiro, improbidade do CNJ e adverse media.
Cada resposta carimba a idade e o tamanho de cada lista em dataset_versions (ingested_at, age_hours e record_count). Se uma lista que entraria na resposta estiver vencida, o módulo devolve pending com dataset_stale e a verificação vai para review: nós não afirmamos "nada consta" sobre uma base que não conseguimos atualizar, e esse caso não é cobrado. Sem CPF legível no documento o resultado também é pending.
A mesma regra vale quando a lista não foi consultada, e não só quando ela envelheceu. A resposta sai pending com no_coverage quando nenhuma lista do módulo está disponível, e com critical_source_disabled quando uma lista que a resposta não pode dispensar está fora do ar. Os dois casos vão para review e não são cobrados, pelo mesmo motivo do dataset_stale: um veredito de "nada consta" só vale se alguma lista tiver sido de fato consultada. E quando uma lista específica não entrou na consulta, ela aparece em aggregates.by_list com null em vez de sumir do objeto, para que "não foi olhada" nunca se pareça com "olhada e sem resultado" no seu código.
A política "aceito clientes que são PEP?" é sua: por padrão ser PEP não reprova (sai como sinalização, que é o que a regulação pede: diligência reforçada, não recusa). Você pode desligá-la no flow, ou por sessão ao criar com sk_ mandando { "policy": { "allow_pep": false } }. Só o vínculo atual reprova; vínculo passado nunca. Chave de política desconhecida é 400 unknown_policy_key.
O resumo pronto de PEP e sanção. Você não precisa refazer a conta em cada integração. O bloco pep_status diz se há função pública em exercício (current) e se a pessoa deixou a função no último ano, nos últimos três ou nos últimos cinco anos (last_1y, last_3y, last_5y), contados do fim do exercício. roles traz a descrição da função como a fonte oficial publica, e só quando o casamento foi pelo documento e forte: semelhança de nome nunca traz cargo. Em aggregates, is_pep, has_sanctions_br (lista publicada por órgão brasileiro) e has_sanctions_intl (lista publicada por organismo ou governo estrangeiro) resumem os hits, worst_severity dá a pior zona entre eles (no_hit, weak ou strong), e sanction_windows e pep_windows separam as janelas por tipo de lista. windows continua no payload como a soma das duas, marcado como depreciado: prefira as separadas.
Programe contra source, não contra list. Em cada hit, source é o identificador estável da lista (cgu_pep, cgu_ceis, ofac_sdn) e não muda; list é o rótulo legível e pode mudar de texto. Na lista de PEP, left_at é o fim do período em que a pessoa é considerada politicamente exposta, e exercise_end é o fim do exercício da função; pep_in_carency marca quem já deixou a função e ainda está dentro dos cinco anos.
Cota diária do módulo. Cada organização tem uma cota diária de sessões novas com este módulo em produção. Passando dela, a criação de sessão responde 429 module_quota_reached com Retry-After até a virada do dia (meia-noite UTC). A renovação de uma sessão não conta de novo. Se o seu volume pede mais, fale com a gente: o ajuste é por organização.
A lista de hits tem teto, e o corte vem declarado. Nome comum produz muito candidato, e um payload sem limite viraria incidente de custo e de leitura do seu lado. Passando do teto, hits sai cortado e hits_truncated vem true. Duas garantias tornam o corte seguro de programar: os aggregates são calculados sobre o conjunto completo (a contagem continua verdadeira mesmo com a lista cortada), e a ordem é determinística antes do corte, com hit forte na frente do fraco e casamento por documento na frente do casamento por nome. O que fica de fora é sempre a cauda mais fraca, nunca a evidência que decide.
// pep_sancoes: nada consta
{ "module": "pep_sancoes", "passed": true, "outcome": "approved", "score": 95,
"data": { "pep": false, "flagged": false, "matched_by": "none", "reason": "clean",
"pep_status": { "current": false, "last_1y": false, "last_3y": false, "last_5y": false,
"roles": [] },
"hits": [], "hits_truncated": false,
"aggregates": { "total": 0, "pep": 0, "sanctions": 0, "strong": 0,
"is_pep": false, "has_sanctions_br": false, "has_sanctions_intl": false,
"worst_severity": "no_hit",
"pep_windows": { "d30": 0, "d90": 0, "d180": 0, "d365": 0, "d1825": 0, "total": 0 },
"sanction_windows": { "d30": 0, "d90": 0, "d180": 0, "d365": 0, "d1825": 0, "total": 0 },
"windows": { "d30": 0, "d90": 0, "d180": 0, "d365": 0, "d1825": 0, "total": 0 } },
"policy": { "allow_pep": true, "source": "flow" },
"dataset_versions": { "cgu_pep": { "ingested_at": "2026-08-21T03:10:00Z", "age_hours": 9.2,
"record_count": 133880,
"stale": false, "disabled": false } } } }
// pep_sancoes: PEP atual, política do flow permitindo (sinaliza, NÃO reprova)
{ "module": "pep_sancoes", "passed": true, "outcome": "approved", "score": 70,
"data": { "pep": true, "flagged": true, "matched_by": "document", "reason": "pep_current",
"pep_status": { "current": true, "last_1y": false, "last_3y": false, "last_5y": false,
"roles": [ "DIRETOR" ] },
"hits": [ { "source": "cgu_pep", "list": "PEP", "matched_by": "document", "strong": true,
"similarity": 1, "precision": 1, "listed_at": "2025-02-01", "left_at": null,
"current": true, "entry_ref": "cgu_pep:8831",
"exercise_end": null, "pep_in_carency": false,
"details": { "funcao": "DIRETOR", "orgao": "MINISTERIO X" } } ] } }
// pep_sancoes: deixou a função há dois anos e segue exposta pela carência de cinco anos
{ "module": "pep_sancoes", "passed": true, "outcome": "approved", "score": 70,
"data": { "pep": true, "flagged": true, "matched_by": "document", "reason": "pep_current",
"pep_status": { "current": false, "last_1y": false, "last_3y": true, "last_5y": true,
"roles": [ "SECRETARIO" ] },
"hits": [ { "source": "cgu_pep", "list": "PEP", "matched_by": "document", "strong": true,
"similarity": 1, "precision": 1, "listed_at": "2019-01-01",
"left_at": "2028-12-31", "current": true, "entry_ref": "cgu_pep:9120",
"exercise_end": "2023-12-31", "pep_in_carency": true,
"details": { "funcao": "SECRETARIO", "orgao": "MINISTERIO X" } } ] } }
// pep_sancoes: semelhança de NOME numa lista internacional (candidato, não veredito)
// repare no que NÃO vem: nome, documento, cargo ou texto livre do terceiro.
{ "module": "pep_sancoes", "passed": true, "outcome": "approved", "score": 60,
"data": { "pep": false, "flagged": true, "matched_by": "name", "reason": "sanction_name_weak",
"hits": [ { "source": "ofac_sdn", "list": "OFAC SDN", "matched_by": "name",
"strong": false, "similarity": 0.82, "precision": 0.64,
"listed_at": "2019-05-10", "left_at": null, "current": true,
"entry_ref": "ofac_sdn:4417" } ] } }
// pep_sancoes: lista nossa vencida, pending, review, e NÃO cobrado
// QUAL lista venceu você lê em dataset_versions, na fonte com "stale": true.
{ "module": "pep_sancoes", "passed": null, "outcome": "pending", "score": 0,
"data": { "pep": false, "flagged": false, "matched_by": "none", "reason": "dataset_stale",
"hits": [], "hits_truncated": false, "aggregates": null,
"policy": { "allow_pep": true, "source": "flow" },
"dataset_versions": { "cgu_pep": { "ingested_at": "2026-08-19T03:10:00Z",
"age_hours": 51.4, "record_count": 133880,
"stale": true, "disabled": false } } } }
// pep_sancoes: nenhuma lista do modulo disponivel, pending, review, e NAO cobrado
// dataset_versions continua vindo inteiro: voce ve exatamente quais listas ficaram de fora.
{ "module": "pep_sancoes", "passed": null, "outcome": "pending", "score": 0,
"data": { "pep": false, "flagged": false, "matched_by": "none", "reason": "no_coverage",
"hits": [], "hits_truncated": false, "aggregates": null,
"policy": { "allow_pep": true, "source": "flow" },
"dataset_versions": { "cgu_pep": { "ingested_at": "2026-08-21T03:10:00Z",
"age_hours": 9.2, "record_count": 133880,
"stale": false, "disabled": true } } } }
// pep_sancoes: uma lista que a resposta nao pode dispensar esta fora do ar
{ "module": "pep_sancoes", "passed": null, "outcome": "pending", "score": 0,
"data": { "pep": false, "flagged": false, "matched_by": "none",
"reason": "critical_source_disabled",
"hits": [], "hits_truncated": false, "aggregates": null,
"policy": { "allow_pep": true, "source": "flow" } } }
// pep_sancoes: lista NAO consultada aparece como null em by_list (nunca ausente)
{ "module": "pep_sancoes", "passed": true, "outcome": "approved", "score": 95,
"data": { "pep": false, "flagged": false, "matched_by": "none", "reason": "clean",
"aggregates": { "total": 0, "pep": 0, "sanctions": 0, "strong": 0,
"by_list": { "TCU": null },
"windows": { "d30": 0, "d90": 0, "d180": 0, "d365": 0, "total": 0 } } } }Em sandbox nada é consultado: o desfecho vem do sufixo do documento, como no resto do ambiente de testes. 66 devolve PEP atual com a política recusando, 77 PEP atual com a política permitindo, 44 PEP que deixou a função há dois anos e segue na carência, 88 sanção por documento no CEIS e 99 um homônimo na OFAC com semelhança 0,82. O pep_status e os agregados do sandbox saem da mesma conta da produção.
Pronto para integrar? A chave de sandbox sai no painel, logo depois do cadastro. Criar conta grátis