Guia de integração: KYT ponta a ponta
Este guia leva a sua engenharia do zero ao ciclo completo da integração de KYT: cadastrar o cliente final, vincular a carteira, analisar a transação, receber o evento e registrar a sua decisão. Todos os passos usam operações do contrato do cliente, autenticadas por X-API-Key.
Pré-requisitos:
- Conta do tenant liberada para a API pela Sentinex Risk (ver o passo 1 do Quickstart)
- Chave com os escopos
vasp:customers:write,vasp:wallets:write,vasp:transactions:screen,vasp:readevasp:webhooks:manage - URL HTTPS pública para receber webhooks
- Leitura de Homologação e testes e do Guia de chaves de API
-
Configure as variáveis de ambiente
Janela do terminal export SENTINEX_API_KEY="snxc_sand_<SUA_CHAVE>" # snxc_live_<SUA_CHAVE> na produçãoexport SENTINEX_BASE_URL="https://sandbox.api.crypto.sentinexrisk.com/api/v1" # https://crypto-api.sentinexrisk.com/api/v1 na produçãoexport SENTINEX_WEBHOOK_SECRET="$(openssl rand -hex 32)"O secret do webhook é gerado por você e enviado no passo 5; a API nunca o devolve. Guarde a chave e o secret num cofre de segredos, nunca no repositório.
-
Cadastre o cliente final
A API aceita
document(CPF ou CNPJ validado) oudocument_hash(SHA-256), um dos dois. Se ambos divergirem, responde422 DOCUMENT_HASH_MISMATCH. Comdocument, o servidor guarda índice cego e cifra; somente hash não permite exibir o documento depois. O exemplo usa hash sintético. Os campos livresattributesrecusam com400chaves e valores que carreguem identificador pessoal em claro. Escopo:vasp:customers:write.Janela do terminal curl -X POST $SENTINEX_BASE_URL/vasp/customers \-H "X-API-Key: $SENTINEX_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-d '{"external_id": "CLIENTE-TESTE-001","type": "PF","document_hash": "'$(printf %s "00000000000" | shasum -a 256 | cut -d" " -f1)'","kyc_tier": "STANDARD","risk_classification": "MEDIUM","consent_data_share": true}'A resposta
201traz o cliente emdata, comid(UUID),kyc_tier,risk_classificationescreening_status: "PENDING". Oexternal_idé único por tenant: repeti-lo responde409comcustomer_already_exists. -
Vincule uma carteira ao cliente
O endereço é validado pela rede (checksum EIP-55, bech32, base58 e afins) e gravado só cifrado. Escopo:
vasp:wallets:write.Janela do terminal curl -X POST "$SENTINEX_BASE_URL/vasp/wallets?mode=sync" \-H "X-API-Key: $SENTINEX_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-d '{"customer_id": "<id devolvido no passo 2>","external_id": "CARTEIRA-TESTE-001","address": "0x2222222222222222222222222222222222222222","blockchain": "eth","asset_symbol": "USDT","wallet_label": "Carteira principal","custody_type": "self_hosted"}'Com
mode=sync(o padrão), a resposta201já traz o resultado da triagem da carteira emdata:screening_status,decision(APPROVE,REVIEWouBLOCK) erisk_tier. Commode=async, a resposta é202comscreening_status: "PENDING", e o resultado é lido depois emGET /vasp/wallets/{id}. Carteira que o tenant já conhecia responde200com o resultado armazenado. -
Analise uma transação
Janela do terminal curl -X POST $SENTINEX_BASE_URL/vasp/screenings \-H "X-API-Key: $SENTINEX_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-d '{"client_transaction_id": "TXN-TESTE-001","customer_ref": "CLIENTE-TESTE-001","direction": "DEPOSIT","asset": "USDT","chain": "ethereum","counterparty_address": "0x1111111111111111111111111111111111111111","amount": 1500.25,"fiat_value_brl": 7500.5}'A resposta é síncrona (escopo
vasp:transactions:screen) e trazrecommendation(ALLOW,REVIEW,HOLDouDENY),risk_score,risk_level,sanctions,rule_hits,coverage,obligationseclient_decisioncomstatus: "PENDING_CLIENT_DECISION". O schema completo está emPOST /vasp/screenings.customer_refé uma referência opaca do seu lado: o servidor protege toda referência não vazia com HMAC versionado e isolado por tenant antes de gravar, mesmo quando não reconhece PII. Preserve sua referência original para novas chamadas; não espere eco em claro. Análise sinalizada abre alerta na fila do tenant, que você lê emGET /vasp/alerts. -
Receba os eventos
Cadastre a subscription com o secret do passo 1 e teste o receptor antes do tráfego real:
Janela do terminal curl -X POST $SENTINEX_BASE_URL/vasp/webhooks \-H "X-API-Key: $SENTINEX_API_KEY" \-H "Content-Type: application/json" \-d '{"target_url": "https://hooks.demovasp.com.br/sentinex","events": ["kyt.screening.completed", "kyt.screening.sanction_hit", "kyt.case.client_decision.recorded"],"secret": "'"$SENTINEX_WEBHOOK_SECRET"'"}'curl -X POST $SENTINEX_BASE_URL/vasp/webhooks/<id devolvido acima>/test \-H "X-API-Key: $SENTINEX_API_KEY"Nas condições de entrega do tenant live, cada análise concluída chega como
kyt.screening.completed, num envelope comevent_type,event_id,delivery_id,attempte o conteúdo do evento empayload. Verifique a assinatura HMAC antes de processar: ver Webhooks. -
Registre a sua decisão
A recomendação da Sentinex Risk não decide nada por você. Registre a ação operacional e o desfecho de suspeição, uma única vez por análise:
Janela do terminal curl -X PATCH $SENTINEX_BASE_URL/vasp/screenings/<screening_id>/client-decision \-H "X-API-Key: $SENTINEX_API_KEY" \-H "Content-Type: application/json" \-d '{"client_decision": {"operational_action": "ALLOW","suspicion_outcome": "NOT_SUSPICIOUS","rationale": "Contraparte conhecida e valor compatível com o perfil do cliente."}}'O registro é imutável: a segunda chamada responde
409comKYT_CLIENT_DECISION_ALREADY_RECORDED, e o eventokyt.case.client_decision.recordedé enviado às suas subscriptions. O caminho antigoPATCH /vasp/screenings/{id}/decisionestá obsoleto. -
Acompanhe os alertas
GET /vasp/alertslista os alertas do tenant, comstatusopcional,limitde 1 a 200 (padrão 50) eoffset. A resposta trazdatae o blocopaginationcomtotal,limiteoffset. A resolução do alerta é feita pela sua equipe no painel, e cada resolução disparaalert.resolved.
Checklist antes do primeiro dado real
Seção intitulada “Checklist antes do primeiro dado real”- Chave
liveaprovada e emitida, com os escopos mínimos, guardada em cofre de segredos - Secret do webhook guardado em cofre, com plano de troca (não há rotação: troca é subscription nova)
-
Idempotency-Keyem todoPOST /vasp/screenings,POST /vasp/customersePOST /vasp/wallets, com os mesmos bytes a cada retentativa - Retentativa com espera crescente para
429e5xx, respeitandoRetry-Afterquando vier - Validação da assinatura HMAC em toda entrega de webhook
-
X-Request-IDdas respostas registrado no seu log, para o suporte cruzar a chamada - Acompanhamento de
X-RateLimit-Remaining, com alerta antes de chegar a zero - Regra de contingência para
503: a análise não foi feita e a transação não foi triada, então não a trate como aprovada
Interpretar antes de automatizar
Seção intitulada “Interpretar antes de automatizar”Use Como as regras decidem para tratar ALLOW, REVIEW, HOLD e DENY. Um HTTP 200 com fail_closed: true é análise gravada com retenção, não falha HTTP; reprocessar exige nova chave, pois replay e GET preservam o snapshot antigo. Consulte Dúvidas frequentes para conflitos, medições ausentes e prazos de alerta.