Pular para o conteúdo

Como as regras decidem

O produto atual de integração B2B é KYT. As rotas /api/v1/kyc/* e os eventos kyc.* não estão disponíveis nesse produto. Nas rotas B2B de cases, uma chamada que passa pela autenticação e pelo acesso da conta recebe 403 PRODUCT_MODULE_DISABLED no gate do produto. Contratar KYC exige uma instalação que o habilite, módulos e escopos próprios; não há data prometida por este guia.

Envie POST /api/v1/vasp/screenings com X-API-Key do ambiente correto, escopo vasp:transactions:screen e uma Idempotency-Key por intenção. A chave determina o tenant. O servidor confere ambiente, acesso da conta, limites, módulo KYT e entrada. asset é obrigatório; uma transferência cripto precisa de contraparte e rede para ser triada. O valor amount é a quantidade do ativo. fiat_value_brl é apenas o valor declarado para conferência, não decide regras.

Exemplo sintético da Demo VASP Ltda, usando o endereço da fixture de baixo risco no sandbox. Em produção, a mesma forma consulta evidência real e o resultado depende dela:

{
"client_transaction_id": "demo-operacao-001",
"customer_ref": "demo-cliente-001",
"direction": "WITHDRAWAL",
"asset": "ETH",
"chain": "ethereum",
"counterparty_address": "0x7eae68ba864d7e60463ca6842c53f1b20ecfb1a2",
"amount": 1.5
}

O fluxo consulta sanções e sinais da contraparte, verifica blocklist quando configurada, calcula o valor em BRL e lê a política do tenant. Avalia o agregado móvel de sete dias somente quando há referência de titular e limiar agregado ativo. O motor próprio em Go avalia as regras elegíveis para o pipeline wallet_screening, com os insumos realmente disponíveis. Registro de regra no catálogo não garante que ela participe dessa chamada.

O score combina contribuições e fica entre 0 e 100, arredondado uma vez. score_ledger explica operações MAX, FLOOR e ADD; somar os pesos de rule_hits não reproduz necessariamente o score. A etapa de regras pode elevar a revisão, mas não liberar uma retenção anterior. A política KYT separa risco, recomendação pública e decisão do cliente. Sem sanção ou bloqueio configurado pelo tenant, risco alto por si só conduz à revisão. Evidência incompleta conduz a HOLD. Uma base de DENY válida prevalece mesmo se outra evidência estiver incompleta.

O servidor grava o screening, a auditoria, o uso e os eventos na fronteira transacional. Só então devolve a análise. Se não consegue assegurar essa gravação, responde erro, por exemplo 503 KYT_PERSISTENCE_UNAVAILABLE. HTTP 200 significa que a análise foi registrada, não que a operação foi aprovada.

recommendation Significado Ação na exchange
ALLOW Nenhum sinal avaliado exigiu revisão ou bloqueio nesta análise Aplicar os controles próprios e registrar a decisão. Conferir também cobertura e dimensões não cobertas
REVIEW Sinal de risco requer análise humana Encaminhar à mesa de compliance, examinar motivos e evidências, decidir permitir, reter ou negar
HOLD Evidência indisponível ou incompleta impede liberar a triagem Reter temporariamente, corrigir a causa e fazer nova análise. Replay da análise antiga não mede novamente
DENY Base de sanção ou bloqueio escolhido na política do tenant Impedir a liberação automática, encaminhar ao responsável e documentar a decisão operacional e o desfecho de suspeição

risk_level e risk_score expressam risco, não substituem recommendation. É possível ter risco alto e recomendação REVIEW. Uma recomendação não transmite fundos, não congela saldo na exchange e não comunica suspeição ao COAF: essas ações dependem de decisão humana.

A análise começa com client_decision.status: PENDING_CLIENT_DECISION. Registre a ação efetivamente tomada via PATCH /api/v1/vasp/screenings/{id}/client-decision, com o mesmo escopo de screening:

{
"client_decision": {
"operational_action": "HOLD",
"suspicion_outcome": "NOT_SUSPICIOUS",
"rationale": "Retenção técnica enquanto a fonte de evidência está indisponível; sem indício de suspeição na análise humana realizada."
}
}

O exemplo não permite inferir ausência de suspeição apenas da falha técnica. O cliente precisa ter fundamento próprio para esse desfecho. operational_action aceita ALLOW, HOLD ou DENY; não aceita REVIEW. suspicion_outcome aceita SUSPICIOUS ou NOT_SUSPICIOUS. rationale documenta o motivo. authority é atribuída pelo servidor a CLIENT_EXCHANGE.

Recorte da resposta HTTP 200:

{
"success": true,
"data": {
"screening_id": "00000000-0000-4000-8000-000000000001",
"recommendation": "HOLD",
"client_decision": {
"status": "RECORDED",
"authority": "CLIENT_EXCHANGE",
"operational_action": "HOLD",
"suspicion_outcome": "NOT_SUSPICIOUS",
"rationale": "Retenção técnica enquanto a fonte de evidência está indisponível; sem indício de suspeição na análise humana realizada.",
"recorded_at": "2026-11-01T12:00:00Z"
}
}
}

A decisão é imutável: segunda gravação responde 409 KYT_CLIENT_DECISION_ALREADY_RECORDED. Após timeout, consulte GET /api/v1/vasp/screenings/{id} com vasp:read para reconciliar. O alias /decision é obsoleto; use /client-decision. Para nova medição, crie outro screening com nova chave de idempotência e preserve o vínculo com o anterior no seu sistema.

Uma falha de evidência pode produzir uma análise válida e gravada, HTTP 200 com data.fail_closed: true e recommendation: HOLD. Não a trate como ausência de risco nem como um erro HTTP a retentar em laço. Estes casos existem no decisor:

Causa O que conferir Tratamento
Provedor indisponível, resposta ausente, score inválido ou status que não confirma conclusão reasons, estado de sanções e coverage Reter e reprocessar quando a fonte voltar
Sanção não medida sanctions.state: NOT_MEASURED, hit: null, capabilities.sanctions Não converter null em false
Política monetária interna ilegível ou indisponível coverage.input_assessments.suspicion_policy, motivo de leitura inválida ou indisponível Corrigir a política ou restaurar sua leitura antes de liberar
Agregado de 7 dias indisponível com limiar ativo e referência presente aggregate_7d: NOT_MEASURED e hit R-COAF-AGG7D-UNAVAILABLE, de peso 0 Reprocessar a leitura; não presumir soma zero
Quantidade ou cotação BRL ausente, indisponível ou vencida amount_brl: null e avaliação amount_brl: NOT_MEASURED Corrigir a entrada ou aguardar cotação utilizável

Recorte de uma retenção por agregado indisponível, sem base de DENY:

{
"success": true,
"data": {
"recommendation": "HOLD",
"fail_closed": true,
"rule_hits": [{
"rule_id": "R-COAF-AGG7D-UNAVAILABLE",
"name": "agregado COAF de 7 dias não medido (fonte indisponível)",
"severity": "MEDIUM",
"weight": 0
}],
"coverage": {
"input_assessments": {
"aggregate_7d": {"state": "NOT_MEASURED", "reason": "leitura indisponível; reprocessar"}
}
}
}
}

Uma falha de autenticação, limite, persistência, auditoria ou fila de eventos pode impedir o registro e devolver 4xx ou 5xx. Esse caminho é diferente do HOLD registrado. Veja Erros e Idempotência.

coverage.input_assessments informa a medição dos insumos da chamada. MEASURED significa medido, inclusive quando o resultado é negativo ou zero. NOT_MEASURED significa que o dado necessário não foi obtido. NOT_EVALUATED significa que a avaliação não foi executada, por exemplo agregado sem referência de titular ou com a política monetária interna desativada. A ausência de referência não cria, por si só, retenção pelo agregado. Política ausente é diferente de política inválida ou ilegível.

Os insumos incluem amount_brl, aggregate_7d, travel_rule e, quando sua leitura falha, suspicion_policy. travel_rule omitido sai UNKNOWN e NOT_MEASURED, sem impor HOLD por essa omissão isolada. A declaração não habilita transmissão de Travel Rule no produto KYT.

capabilities separa cinco dimensões, cada uma com MEASURED ou NOT_MEASURED. NOT_EVALUATED é estado dos insumos, não dessas cinco capacidades:

Capacidade O que foi medido
sanctions Consulta de sanções da contraparte
labels Etiquetas do endereço; etiqueta de bloqueio de emissor é um rótulo e não prova sanção
exposures Exposição direta e indireta por categoria
graph Sinais do grafo on-chain
typologies Tipologias on-chain

Uma fonte responder ok não torna as cinco capacidades medidas. Exposições não medidas são null, não percentuais zero. Sanção não medida publica hit: null; hit: false com estado MEASURED é um negativo medido. Rótulo adverso não equivale a evidência verificada de sanção.

coverage.state resume o motor: ACTIVE_READY, ACTIVE_DEGRADED ou DISABLED. Leia evaluable_rules, degraded_rules (regra, fonte e causa), disabled_rules e causes. O manifesto atual é snx-rule-capabilities/2026-10-09.v4. Trate a versão como identificador de evidência, preservando a que veio na resposta. O contrato publicado ainda fixa uma versão antiga, pendência de alinhamento, portanto não use uma enum antiga para descartar evidência atual.

not_covered declara dimensões fora da oferta por desenho (CAPABILITY_NOT_OFFERED) ou rede fora de determinado feed (NETWORK_NOT_COVERED). Não é uma falha de consulta e não comprova resultado negativo. Pode coexistir com ALLOW. Falha real de insumo oferecido degrada a cobertura e retém a análise.

Cada item de rule_hits contém rule_id, name, severity e weight. rule_id permite relacionar a regra à investigação; severidade prioriza o achado; peso informa a contribuição declarada. Hit de peso zero pode comunicar uma lacuna importante. score_ledger é a trilha do cálculo, e shadow_observations contém observação sem efeito na decisão. Lista de hits vazia com cobertura incompleta não é prova de baixo risco.

A tela Regras de alerta consulta GET /api/v1/rules com sessão do painel. Essa rota não pertence ao contrato por API key /vasp; não tente acessá-la com sua chave B2B. Cada entrada traz id, nome, descrição, categoria, severidade, estado, versão e capability. A resposta inclui summary (total, active, shadow, inactive) e coverage_manifest_version.

Em capability, confira source, required_inputs, pipelines, freshness_seconds, configured_state, readiness e criticality. runtime_evidence_required exige evidência de execução, disabled_by_configuration indica regra inativa ou shadow, not_bound_to_production_pipeline indica falta de pipeline declarado e manifest_missing indica declaração ausente. O catálogo descreve a configuração base; os overrides do tenant são consultados separadamente em Configuração de regras. A resposta do screening é que comprova a cobertura daquela operação.

Entre as regras de histórico KYT estão R-KYT-01 (velocidade), R-KYT-02 (layering), R-KYT-03 (estruturação), R-KYT-04 (smurfing) e R-KYT-05 (troca rápida de rede). Todas exigem kyt_transactions medido, sujeito identificado e histórico utilizável. Não basta enviar um endereço isolado para medir comportamento histórico.

A tabela abaixo transcreve o manifesto desta versão, por regra. T = transaction_analysis, W = wallet_screening e K = kyc_orchestration. Só W é o pipeline do POST /vasp/screenings. K depende do produto KYC contratado e habilitado, indisponível no KYT atual. Pipeline vazio significa ausência de vínculo decisório declarado. Mesmo com pipeline, a regra depende do sujeito aplicável, das flags de medição e do frescor. A tabela não promete ativação de todas essas regras para a sua requisição.

Regra Fonte Insumo obrigatório Pipelines Frescor máximo (s)
R-ADV-01 advanced_intelligence advanced_signals T 300
R-ADV-02 onchain_intelligence onchain_signals; em W: onchain_graph T,W 900
R-ADV-03 auth_device_intelligence auth_device_signals T 300
R-ADV-04 advanced_intelligence advanced_signals K 300
R-ADV-05 advanced_intelligence advanced_signals nenhum 300
R-ADV-06 wallet_intelligence wallet_signals T 900
R-ADV-07 advanced_intelligence advanced_signals nenhum 300
R-ADV-08 advanced_intelligence advanced_signals nenhum 300
R-ADV-09 advanced_intelligence advanced_signals nenhum 300
R-ADV-10 advanced_intelligence advanced_signals nenhum 300
R-ADV-11 advanced_intelligence advanced_signals nenhum 300
R-ADV-12 advanced_intelligence advanced_signals nenhum 300
R-ADV-13 advanced_intelligence advanced_signals nenhum 300
R-ADV-14 advanced_intelligence advanced_signals nenhum 300
R-ADV-15 advanced_intelligence advanced_signals nenhum 300
R-ADV-16 advanced_intelligence advanced_signals nenhum 300
R-ADV-17 advanced_intelligence advanced_signals nenhum 300
R-ADV-18 advanced_intelligence advanced_signals T 300
R-ADV-19 advanced_intelligence advanced_signals nenhum 300
R-ADV-20 advanced_intelligence advanced_signals nenhum 300
R-ADV-21 advanced_intelligence advanced_signals T 300
R-ADV-22 advanced_intelligence advanced_signals nenhum 300
R-ADV-23 advanced_intelligence advanced_signals nenhum 300
R-ADV-24 advanced_intelligence advanced_signals nenhum 300
R-ATO-01 auth_device_intelligence auth_device_signals T 300
R-ATO-02 auth_device_intelligence auth_device_signals T 300
R-ATO-03 auth_device_intelligence auth_device_signals T 300
R-ATO-04 auth_device_intelligence auth_device_signals T 300
R-ATO-05 auth_device_intelligence auth_device_signals T 300
R-BYPASS-01 request_context transaction_context nenhum 0
R-BYPASS-02 compliance_intelligence compliance_signals T,K 900
R-BYPASS-03 auth_device_intelligence auth_device_signals T 300
R-BYPASS-04 onchain_intelligence onchain_signals; em W: onchain_graph T,W 900
R-COMP-01 request_context transaction_context T,W 0
R-COMP-02 compliance_intelligence compliance_pep_signals T,K,W 900
R-COMP-03 onchain_intelligence onchain_signals; em W: onchain_graph T,W 900
R-COMP-04 travel_rule travel_rule_result T 0
R-COMP-05 compliance_intelligence compliance_signals T,W 900
R-CONT-01 pkyc_events pkyc_events nenhum 86400
R-CONT-02 pkyc_events pkyc_events nenhum 86400
R-CONT-03 pkyc_events pkyc_events nenhum 86400
R-CONT-04 pkyc_events pkyc_events nenhum 86400
R-CONT-05 pkyc_events pkyc_events nenhum 86400
R-CONT-06 pkyc_events pkyc_events nenhum 86400
R-CONT-07 pkyc_events pkyc_events nenhum 86400
R-CONT-08 pkyc_events pkyc_events nenhum 86400
R-CONT-09 auth_device_intelligence auth_device_signals T 300
R-CONT-10 transaction_history transaction_history T 900
R-CONT-11 auth_device_intelligence auth_device_signals T 300
R-CONT-12 auth_device_intelligence auth_device_signals T 300
R-CONT-13 wallet_intelligence wallet_signals T 900
R-CONT-14 wallet_intelligence wallet_signals T 900
R-CONT-15 auth_device_intelligence auth_device_signals T 300
R-CONT-17 travel_rule travel_rule_result nenhum 0
R-CONT-18 wallet_intelligence wallet_signals T 900
R-CONT-19 wallet_intelligence wallet_signals T 900
R-CONT-20 adverse_media adverse_media_result K 86400
R-CROSS-01 holder_cross holder_cross_facts T 900
R-CROSS-02 holder_cross holder_cross_facts T 900
R-CROSS-03 holder_cross holder_cross_facts T 900
R-CROSS-04 holder_cross holder_cross_facts T 900
R-CROSS-05 holder_cross holder_cross_facts T 900
R-CROSS-06 holder_cross holder_cross_facts T 900
R-CROSS-07 holder_cross holder_cross_facts T 900
R-CROSS-08 holder_cross holder_cross_facts T 900
R-CROSS-09 holder_cross holder_cross_facts T 900
R-CROSS-10 holder_cross holder_cross_facts T 900
R-CROSS-11 holder_cross holder_cross_facts T 900
R-CROSS-12 holder_cross holder_cross_facts T 900
R-CRYPTO-01 onchain_intelligence onchain_signals; em W: onchain_exposures T,W 900
R-CRYPTO-02 onchain_intelligence onchain_signals; em W: onchain_exposures T,W 900
R-CRYPTO-03 onchain_intelligence onchain_signals; em W: onchain_graph T,W 900
R-CRYPTO-04 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-05 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-06 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-07 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-08 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-09 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-10 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-11 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-12 onchain_intelligence onchain_signals; em W: onchain_typologies T,W 900
R-CRYPTO-13 wallet_intelligence wallet_signals nenhum 900
R-CRYPTO-25 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-26 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-27 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-28 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-29 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-30 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-31 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-32 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-33 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-34 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-35 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-36 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-37 onchain_intelligence onchain_signals; em W: onchain_sanctions T,W 900
R-CRYPTO-38 advanced_intelligence advanced_signals K 300
R-CRYPTO-39 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-41 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-42 advanced_intelligence advanced_signals nenhum 300
R-CRYPTO-43 advanced_intelligence advanced_signals nenhum 300
R-DEFI-01 defi_intelligence defi_signals nenhum 300
R-DEFI-02 defi_intelligence defi_signals nenhum 300
R-DEFI-03 defi_intelligence defi_signals nenhum 300
R-DEFI-04 defi_intelligence defi_signals nenhum 300
R-DEFI-05 defi_intelligence defi_signals nenhum 300
R-KYT-01 kyt_history kyt_transactions T,W 900
R-KYT-02 kyt_history kyt_transactions T,W 900
R-KYT-03 kyt_history kyt_transactions T,W 900
R-KYT-04 kyt_history kyt_transactions T,W 900
R-KYT-05 kyt_history kyt_transactions T,W 900
R-KYT-WALLET-LABEL wallet_intelligence wallet_signals T 900
R-MULE-01 transaction_history transaction_history T 900
R-MULE-02 transaction_history transaction_history T 900
R-MULE-03 transaction_history transaction_history T 900
R-MULE-04 transaction_history transaction_history T 900
R-MULE-05 transaction_history transaction_history T 900
R-PIX-01 transaction_history transaction_history T 900
R-PIX-02 transaction_history transaction_history T 900
R-PIX-03 transaction_history transaction_history T 900
R-PIX-04 transaction_history transaction_history T 900
R-PIX-05 transaction_history transaction_history T 900
R-STAB-06 stablecoin_intelligence stablecoin_signals nenhum 300
R-STAB-07 stablecoin_intelligence stablecoin_signals nenhum 300
R-STAB-08 stablecoin_intelligence stablecoin_signals nenhum 300
R-STAB-09 stablecoin_intelligence stablecoin_signals nenhum 300
R-STAB-10 stablecoin_intelligence stablecoin_signals nenhum 300
R-STABLE-01 request_context transaction_context T 0
R-STABLE-02 transaction_history transaction_history T 900
R-STABLE-03 transaction_history transaction_history T 900
R-STABLE-04 request_context transaction_context T 0
R-STABLE-05 transaction_history transaction_history T 900

Frescor 0 significa que não há janela temporal imposta por essa declaração, não dispensa evidência. Regras fora do pipeline, inativas ou shadow não compõem cobertura decisória. O catálogo de runtime também pode conter regras com declaração própria; ele é a fonte da lista efetivamente registrada na instalação, sem inferir total a partir desta tabela. Regras de matrícula de carteira e hits do decisor, como R-SANCTION, R-BLOCKLIST, R-KYT-SCAM, R-COAF-SINGLE e R-COAF-AGG7D, não devem ser confundidos com o inventário compilado do motor.

Área logada Ajuste e limite
Regras de alerta Catálogo, descrição e estado base da regra; não atesta que todos os insumos foram medidos
Configuração de regras Override por tenant: enabled, shadow_mode, weight_override, decision_override, notas e motivo auditável; alteração por Tenant Admin com MFA recente
Política de decisão KYT Política do tenant para score, combinações de regras e opções previstas pelo produto; não remove retenção por evidência incompleta nem bloqueio de sanção
Regras de monitoramento Regras do monitoramento contínuo em /kyt/monitor-rules, separadas do screening pontual

As chaves runtime screening.score_monitor_threshold, screening.score_review_threshold, screening.score_block_threshold e screening.score_critical_threshold têm padrões 25, 50, 75 e 90. Overrides só baixam limiares positivos, endurecendo o screening; valores não positivos ou acima do padrão mantêm a base da plataforma. São bandas internas, não uma tabela direta de ALLOW e DENY.

screening.suspicion_policy é um envelope com tenant_id, version, enabled, single_brl e aggregate_brl. Requer opt-in e versão do tenant correto. O padrão está desligado, com limiares 0. As chaves antigas screening.coaf_single_threshold_brl e screening.coaf_agg_threshold_brl são legado inativo. Não as use para ativar a política.

rules.holder_cross_policy contém limiares escolhidos pelo tenant para renda PF, faturamento PJ, empresa ou relacionamento recente, PEP e validade do KYC por risco. Valor vazio ou parâmetro zero mantém a regra dependente não medida. Contratação, habilitação do cruzamento e fatos do titular são requisitos separados. customer_id resolvido não atesta que KYC foi enriquecido; KYC próprio continua fora do produto KYT atual.

Shadow por tenant observa a regra quando há insumos válidos, sem afetar score ou recomendação. Configuração shadow global exige autoridade de plataforma e afeta todos os tenants; não é permissão do integrador nem do Tenant Admin. Ausência de insumo também impede uma observação shadow confiável.

Os limiares de suspeição são internos e configuráveis, sem piso legal de comunicação de operação suspeita. Superá-los é indício para análise, não decisão automática de comunicar. Base: Lei 9.613/1998, art. 11, II e Circular BCB 3.978/2020, arts. 48 e 49, alterada pela Resolução BCB 591.

Essa análise de suspeição é distinta da comunicação objetiva prevista na norma. obligations.coaf_sar é legado: MONITOR não é dispensa legal e não é comunicação enviada. coaf_objective é prévia, com final: false e lacunas, não conclusão jurídica nem protocolo do órgão. A exchange avalia a obrigação aplicável e registra seu desfecho com fundamento próprio.

Veja também Dúvidas frequentes de integração e Glossário.