Visão geral
A Travel Rule do GAFI (Recomendação 16), implementada na UE como o Regulamento de Transferências de Fundos (TFR), exige que o Provedor de Serviços de Ativos Virtuais remetente (o VASP remetente) colete e transmita as informações do remetente e do beneficiário ao VASP destinatário (o VASP beneficiário) antes que uma transferência de ativo virtual seja liquidada. Ao contrário da maioria das jurisdições, o TFR da UE se aplica sem valor mínimo: toda transferência de cripto está no escopo, não apenas as transferências acima de um limiar de reporte. O produto Travel Rule da Didit é uma troca gerenciada, não apenas um campo de dados:- Você envia uma transferência com
transaction_category: "travelRule". - A Didit tenta os trilhos em ordem de prioridade para alcançar o VASP da contraparte, executa a troca pelo primeiro que o alcança e, quando o outro lado retorna um nome de beneficiário, compara esse nome com o que você enviou.
- Somente depois que a troca chegar a
COMPLETEDvocê deve transmitir a transferência on-chain. - Em seguida, você informa à Didit o hash da transação on-chain para encerrar a troca como
FINISHED.
GTR, TRUST, VERIFYVASP, SYGNA) exigem uma associação à rede do lado remetente e, hoje, essa associação precisa ser sua.
Conecte as credenciais da sua associação no Marketplace do console (categoria de redes de Travel Rule), e suas transferências trafegam sob a sua própria identidade na rede.
Hoje a Didit não possui associação de plataforma em nenhuma das quatro redes e está em processo de onboarding como provedor nelas.
Até que esse onboarding seja concluído, platform_available é false para as quatro, o modo didit das configurações (roteamento pela associação de plataforma da Didit) não está disponível para nenhuma rede, e disabled_networks não tem nada para desativar.
Uma associação que você mesmo conecta sempre tem precedência sobre uma associação de plataforma.
Nenhuma associação de rede está incluída por padrão, nem mesmo a GTR.
Ativar a Travel Rule não ativa GTR, TRUST, VerifyVASP nem Sygna.
Consulte Obter configurações da Travel Rule para ver os modos efetivos de networks da sua aplicação, e Redes de Travel Rule para saber o que cada rede alcança hoje.
Se as quatro informarem unavailable, nenhuma consegue rotear uma troca: conecte sua própria associação no Marketplace ou use uma contraparte alcançável por INTERNAL, TRP ou EMAIL.
Ao salvar uma associação, o código de participante precisa ser o seu: a operação retorna 400 quando o código é o próprio código da Didit naquela rede ou um código que a associação de outra aplicação já possui.
Uma associação GTR precisa da sua chave privada ed25519 (base64), aquela cuja chave pública está registrada no portal da GTR: ela criptografa os dados pessoais que você envia e descriptografa os dados que você recebe.
Uma associação VerifyVASP aponta para o seu próprio VerifyVASP Enclave: a URL é a do seu Enclave, e o token é o que o seu Enclave apresenta à Didit.
Mesmo com sua própria associação, um trilho de rede só roteia uma transferência quando o beneficiary_data dela traz o id da contraparte naquela rede (counterparty_gtr_vasp_code, counterparty_trust_membership_id, counterparty_verifyvasp_id ou counterparty_sygna_vasp_code), ou quando a entrada da contraparte no diretório a lista naquela rede (veja Rotas).
platform_available informa se a associação de plataforma está configurada, e não é uma verificação em tempo real do status da rede. Da mesma forma, connected significa que as credenciais da sua associação estão salvas e passaram na validação local; a primeira troca real as verifica junto à rede. Um modo didit ou own não garante que a contraparte seja alcançável nem que a entrega seja bem-sucedida.
Com sua própria associação, a Didit lê a resposta da contraparte via GTR, VERIFYVASP e SYGNA a partir da resposta da rede ou consultando a rede a cada 5 minutos, o que conclui ou recusa a transferência.
TRUST apenas envia: uma transferência enviada por ela permanece em AWAITING_COUNTERPARTY até que confirmation_timeout_hours se esgote, depois passa para EXPIRED e o seu timeout_outcome é aplicado.
O recebimento de uma transferência que outro VASP envia a você por uma rede ainda não está ativado, e nenhuma troca por uma rede foi concluída em uma rede de produção até agora: consulte Redes de Travel Rule.
Outras redes (CODE, a aliança coreana, TRISA, Notabene e Veriscope) aparecem no Marketplace do console como blocos para solicitar acesso.
A Didit ainda não tem integração com elas, então nenhuma transferência pode ser roteada por elas hoje.
Quando nenhum dos sete canais consegue identificar uma contraparte, a Didit executa mais uma etapa de identificação antes de desistir: a atribuição por análise de blockchain.
A carteira de destino é consultada nos dados de análise de blockchain; quando a carteira pertence a uma exchange ou custodiante conhecida, a Didit registra o VASP atribuído na transferência, adiciona-o ao diretório e executa os canais mais uma vez com o novo nome.
Consulte Atribuição por análise de blockchain para ver o comportamento completo e os preços.
Uma transferência cujo destino foi declarado como carteira autocustodiada ignora os sete canais, já que não há VASP de contraparte com quem trocar dados, e segue diretamente para a comprovação de propriedade da carteira pelo usuário final.
/v3/ descritos nesta página.O que é executado quando você envia uma transferência
As verificações são executadas na única chamadaPOST /v3/transactions/. Quando você recebe a resposta, a triagem já foi executada, a transferência já está armazenada e as regras já foram avaliadas.
A troca em si começa depois da resposta: a Didit escolhe o trilho e contata a contraparte fora da sua requisição, então nenhuma rede ou contraparte pode atrasar ou fazer a criação falhar.
Cada mudança de status a partir daí chega como um webhook travel_rule.status.updated que informa o trilho. O objeto de transferência retornado pelos endpoints de transferência da Travel Rule traz um campo delivery que mostra se a mensagem foi entregue.
Não há pipeline para consultar periodicamente: as partes assíncronas são a troca, a resposta da contraparte e qualquer ação do usuário final.
Etapa por etapa:
- Validação e vinculação do titular. O payload é validado.
Um
transaction_idjá usado na sua aplicação é rejeitado com400. Quando duas requisições com o mesmo id concorrem, uma delas recebe409. Osubjecté vinculado ao perfil do seu usuário ou da sua empresa porvendor_data, para que a transferência apareça nesse perfil para monitoramento. Umvendor_datade titular ou de contraparte que esteja na lista de bloqueio é rejeitado com400, e nenhuma transação é criada. Carteiras, contas bancárias, IPs e dispositivos na lista de bloqueio são verificados na etapa 6 e recusam a transação nesse ponto, depois que o roteamento foi executado. - Enriquecimento de dispositivo e rede. Os IPs das partes são enriquecidos com dados geográficos, e qualquer contexto de dispositivo (automático no envio pelo SDK) é normalizado no grafo de dispositivos. É o mesmo grafo alimentado pelas sessões de KYC, então a relação “relacionado por dispositivo” funciona entre onboarding e transações.
- Triagem cripto. Em transferências cripto com monitoramento ativado, a carteira relevante (ou o hash on-chain) passa por triagem com análise de blockchain antes de qualquer troca: exposição a sanções, proximidade com mixers e fundos roubados. Consulte Triagem cripto e de carteiras.
- Transferência da Travel Rule. O mecanismo de troca verifica o limiar e respeita uma declaração de carteira autocustodiada. Em seguida, armazena a transferência com o trilho ainda vazio:
NOT_APPLICABLEabaixo do seu limiar,UNCONFIRMED_OWNERSHIPpara uma carteira autocustodiada declarada,COMPLETEDquando a outra carteira é a sua própria carteira verificada eAWAITING_COUNTERPARTYnos demais casos. Cada mudança de status coloca um eventotravel_rule.status.updatedna fila, e a Didit o envia depois dotransaction.createdda transação (etapa 7). - Criação da sessão de propriedade da carteira. Se a transferência exige que o usuário final comprove o controle da carteira e
auto_wallet_verificationestá ativado, uma sessão do widget de propriedade da carteira é criada e retornada emaction_required. - Avaliação de regras. Todas as regras ativas são executadas. O pacote EU TFR reage ao status de transferência definido na etapa 4, e suas regras personalizadas veem o resultado da triagem da etapa 3. Uma regra pode reter a transação (
IN_REVIEW), recusá-la ou exigir uma verificação adicional (AWAITING_USER). - Faturamento e notificação. Uma transação de saída é faturada em uma única linha: a linha da Travel Rule quando a transação iniciou uma troca, e Triagem de transações nos demais casos. Uma transferência de entrada não gera nenhuma das duas tarifas, e uma aplicação de sandbox nunca é cobrada.
A resposta é enviada, e
transaction.createdé disparado para os seus destinos de webhook, seguido dos eventostravel_rule.status.updatedda etapa 4. - Roteamento, depois da resposta. A Didit percorre os sete trilhos em ordem de prioridade. Se nenhum deles encontrar a contraparte, a atribuição por análise de blockchain identifica a contraparte e os trilhos são executados novamente uma vez. O primeiro trilho alcançável conduz a troca. Nesse trilho, a transferência permanece em
AWAITING_COUNTERPARTYenquanto a contraparte responde. Ela é liquidada na hora quando uma contraparteINTERNALé encontrada (COMPLETEDouCOUNTERPARTY_MISMATCHED_DATA), e passa aCOUNTERPARTY_VASP_NOT_FOUNDquando nenhum trilho alcança a contraparte. Cada mudança disparatravel_rule.status.updated, e suas regras são executadas novamente sempre que o status ou o trilho mudam. Uma transferência que o roteamento deixa emCOUNTERPARTY_VASP_NOT_FOUNDrecebe nesse momento a sua sessão do widget de propriedade da carteira (quandoauto_wallet_verificationestá ativado). Leia essa sessão noaction_requiredda transação com Obter transação.
Como cada etapa corresponde às suas obrigações
transaction.created nem transaction.status.updated. As transações de sandbox permanecem APPROVED, a menos que uma transferência da Travel Rule que expira aplique o seu timeout_outcome, e nada é cobrado.
O próprio mecanismo de troca da Travel Rule é executado em aplicações de sandbox quando a Travel Rule está ativada, com uma única contraparte: toda troca de saída vai para o Didit Test VASP no trilho TEST_VASP. Ele responde dentro da Didit com o cenário que você escolher, então a transferência é concluída, é recusada, apresenta divergência, fica inalcançável, expira ou aguarda a comprovação de propriedade da carteira.
Nenhuma mensagem de conformidade chega a uma VASP real da contraparte, e os webhooks travel_rule.status.updated são entregues com environment: sandbox.
Entrada: o test VASP pode enviar uma transferência para você (Acionar transferência de entrada do Test VASP), e o registro (POST /v3/travel-rule/inbound/) é liquidado com base no seu catálogo de endereços de carteira, como em uma aplicação de produção: ON_HOLD, UNCONFIRMED_OWNERSHIP, COUNTERPARTY_MISMATCHED_DATA ou COMPLETED e depois FINISHED.
Consulte Testar a Travel Rule no sandbox.Ciclo de vida
Toda transferência tem umstatus que assume um de 13 valores.
A troca começa em AWAITING_COUNTERPARTY no caso normal, em NOT_APPLICABLE quando o valor está abaixo do seu threshold_amount ou quando uma solicitação de pagamento Lightning não indica nenhum beneficiário (consulte Lightning), ou em UNCONFIRMED_OWNERSHIP quando o destino foi declarado como carteira autocustodiada. Ela termina em um dos estados finais: FINISHED, CANCELLED ou EXPIRED.
A transferência segue sua própria máquina de estados, separada do status de revisão da transação subjacente.
Um status da troca nunca altera sozinho o status da transação, com uma exceção: uma expiração aplica o timeout_outcome que você configurou (ou uma política de sunrise ou de contraparte não responsiva, quando aplicável).
Em vez disso, suas regras são executadas novamente a cada transição. Assim, as regras da EU TFR ou qualquer regra baseada em travel_rule_status podem mover a transação, por exemplo para IN_REVIEW.
Uma transferência que exige que o usuário final comprove o controle da carteira adiciona um bloco action_required à transação, mas o status da transação permanece como suas regras o deixaram.
Leia o estado da troca em travel_rule.status e o veredito de permitir / reter / recusar no próprio status da transação.
Cada transição (e cada status informado passivamente) também é replicada nos valores personalizados da transação, para que as regras possam se basear neles: custom_values.travel_rule_status (status canônico), custom_values.travel_rule_rail (o canal que transportou a troca, vazio até que um seja selecionado) e custom_values.travel_rule_regime (derivado da jurisdiction nas suas configurações: SG → singapore, GB → uk e qualquer código de país membro da UE ou do EEE, como DE ou FR → eu. Códigos sem mapeamento são gravados em minúsculas, por exemplo US → us. Um props.travel_rule_regime que você mesmo envia sempre prevalece sobre o valor derivado).
CANCELLED também pode ser alcançado a partir de qualquer estado não terminal com action: "cancel"):
Entrega e novas tentativas
A Didit envia cada mensagem que uma transferência deve enviar fora da requisição que a originou e tenta novamente até que o outro lado a receba. O objeto de transferência retornado por Finalizar, cancelar ou reenviar, Confirmar propriedade e registro sunrise traz a mensagem mais recente emdelivery, assim como o objeto travel_rule incorporado à transação; ele é null quando a transferência nunca deveu nenhuma mensagem.
408, 429 ou 5xx) é tentada novamente após 30 segundos, 2 minutos, 10 minutos, 30 minutos e 1 hora.
Quando uma primeira mensagem falha definitivamente (a rede a recusou ou a sexta tentativa também falhou), a transferência passa para COUNTERPARTY_VASP_NOT_REACHABLE com last_error em sua timeline, e você pode tentar novamente com action: "resend".
Qualquer outra mensagem que falhe definitivamente é registrada na timeline.
delivery nunca substitui o status da transferência: acompanhe a troca pelo status e use delivery para ver por que uma transferência ainda está aguardando.
Valores de status legados
Se você já enviavatravel_rule_details.status antes desta versão, esses valores continuam funcionando e são mapeados automaticamente.
Grafias em camelCase de qualquer status (por exemplo counterpartyVaspNotFound) também são aceitas, tanto no envio quanto nos valores de condição de regras, e são normalizadas para a forma canônica:
Configuração
Configure o perfil do seu VASP e a política de negociação uma vez por aplicação comGET/PUT /v3/travel-rule/settings/.
PUT é uma atualização parcial: envie apenas os campos que você quer alterar.
Rigor da correspondência de nomes
Modos de validação de propriedade
ownership_validation_mode define quanta prova a propriedade de uma carteira exige antes que uma transferência se apoie nela:
FULL e SIMPLIFIED, uma transferência posterior só a reutiliza quando ela é respaldada por uma prova que o modo aceita para essa transferência.
Quando inbound_auto_accept não tem uma carteira do catálogo de endereços para corresponder, uma carteira cripto que você registrou nas transações de exatamente um usuário final identifica o titular.
A Didit adiciona essa carteira ao catálogo de endereços do usuário final como sua autodeclaração, verificada, a menos que o modo seja FULL. Ela nunca adiciona uma carteira que o catálogo de endereços já lista sob outro nome da mesma chain (eth e ethereum), incluindo uma registrada como de outro VASP.
As verificações de endereço que outros VASPs fazem antes de enviar (via GTR, Sygna e VerifyVASP) também seguem o modo: em FULL, uma carteira que o usuário final apenas declarou não é informada como sua.
Compartilhamento de dados
data_sharing_fields escolhe quais campos a Didit envia à contraparte sobre os seus próprios usuários, separadamente para pessoas físicas e empresas:
- Pessoas físicas podem compartilhar
name,wallet_address,address,national_id,customer_identification,date_of_birtheplace_of_birth. Empresas usam os cinco primeiros. nameewallet_addresssão sempre enviados.- Um tipo de entidade para o qual você nunca fez uma escolha compartilha todos os campos. Uma lista vazia também é uma escolha: ela compartilha apenas o nome e a carteira.
- Um
PUTfaz a mesclagem por tipo de entidade, então enviarindividualmantém intacta a escolha decompanyarmazenada. - Uma escolha que não consegue cumprir as obrigações do remetente do regime da sua
jurisdiction(EU TFR ou Recomendação 16 do FATF), incluindo uma lista vazia, é recusada com400. Os erros ficam emdata_sharing_fields, indexados por tipo de entidade.
Correspondência por campo
matching_rules define o rigor com que cada campo dos dados da contraparte é comparado com o que você tem:
NONE, STRICT, CONTAINS, DEFAULT ou FUZZY.
Padrões: name segue name_matching_strictness, date_of_birth e address são NONE, e account é STRICT.
Um campo omitido mantém o seu padrão, e um campo que o tipo de entidade não compara (uma empresa não tem date_of_birth) é recusado com 400.
Limiares por jurisdição
threshold_amount existe porque o escopo do Travel Rule varia conforme o regulador.
A Didit usa 0.00 como padrão (a posição da UE), então toda transferência é trocada, a menos que você aumente o valor deliberadamente:
threshold_amount com o valor do seu regulador; transferências abaixo dele resultam em NOT_APPLICABLE sem trocar nenhum dado de identidade.
Os limiares mudam com o tempo: confirme o valor atual com a sua assessoria jurídica de conformidade em vez de tratar esta tabela como aconselhamento jurídico.
Modelo de dados IVMS 101
O padrão do setor para os dados trocados no âmbito da Travel Rule é o IVMS 101 (interVASP Messaging Standard).travel_rule_details.originator_data e travel_rule_details.beneficiary_data são payloads de pessoa no estilo IVMS 101. A Didit os encapsula no envelope nativo de cada trilho: o trilho TRP troca blocos IVMS101 (ivms101.2023, informado no campo ivms_version da transferência), o trilho Sygna usa sua variante IVMS criptografada com ECIES, e os trilhos GTR, TRUST e VERIFYVASP usam seus próprios envelopes criptografados. Assim, um único formato de payload chega a cada contraparte no formato que o protocolo dela espera.
Ao montar a mensagem IVMS 101, a Didit lê estas chaves de cada payload de pessoa: first_name e last_name (ou um único name ou full_name), date_of_birth, place_of_birth, residence_country (ou country), vendor_data (ou customer_identification) e wallet_address.
Duas regras práticas:
- Alfabeto latino. O IVMS 101 exige valores em alfabeto latino, então translitere os nomes escritos originalmente em outro alfabeto. A correspondência de nomes da Didit compara conjuntos de tokens normalizados, então diferenças de ordem e de maiúsculas e minúsculas não fazem uma troca falhar. Alfabetos diferentes nos dois lados, sim.
- Envie dados que você verificou. Quando o titular por trás de
vendor_dataé um usuário com uma verificação KYC da Didit aprovada, a Didit transmite a identidade verificada, não os valores que você digitou: consulte Dados verificados e procedência. Para qualquer outro titular, a Didit transmite exatamente osoriginator_dataque você envia. Por isso, monte-os a partir da identidade que você verificou no onboarding, e não de um campo de formulário não verificado. É isso que exige a redação do FATF: “informações do remetente exigidas e precisas”. No trilhoINTERNAL, a aplicação do beneficiário também recebe osubjectque você enviou (nome,vendor_data, data de nascimento, país e endereço) como a parte contraparte da transação de entrada dela.
Dados verificados e procedência
Quando o titular de uma transferência é um dos seus usuários, uma pessoa física com uma verificação KYC aprovada, a Didit monta esse lado da troca a partir dos dados verificados:- o remetente de uma transferência de saída que você cria com
POST /v3/transactions/; - o beneficiário de uma transferência de entrada que você informa com
POST /v3/transactions/, ou comPOST /v3/travel-rule/inbound/quando oholder_vendor_datada carteira correspondente indica esse usuário.
POST /v3/transactions/, os dois casos se aplicam a uma transação cuja transaction_category é travel_rule enquanto a Travel Rule está ativada.
Os nomes, a data e o local de nascimento, o número e o tipo do documento, o endereço e o país de residência (obtido desse endereço) verificados têm precedência sobre os valores que você enviou. Um campo que a verificação não contém mantém o seu valor. O mesmo vale para um endereço completo que você enviou quando o endereço verificado não está completo o suficiente para ser transmitido.
Os metadata da transferência, no objeto travel_rule incorporado à transação, registram a origem de cada campo e onde os seus valores eram diferentes:
*_provenance associa cada campo a verified ou caller, e *_verified_differences lista todos os campos em que você enviou um valor diferente do verificado, sem considerar maiúsculas e minúsculas, espaços nem códigos de país de duas ou três letras. Enquanto os dados de uma transferência de entrada estão mascarados, as diferenças ficam de fora. A Didit calcula os dois, então cópias dessas chaves, ou de name_match, que você enviar em travel_rule_details.metadata são descartadas.
Envio direto de IVMS 101
Além dos objetos planosoriginator_data e beneficiary_data, travel_rule_details (em POST /v3/transactions/) e POST /v3/travel-rule/inbound/ aceitam IVMS 101 nativo:
- um bloco
originatore um blocobeneficiary, comoriginatorPersonsoubeneficiaryPersonscontendo umanaturalPersonou umalegalPerson, eaccountNumber; - os mesmos blocos dentro de um objeto
ivms101(ouIVMS101); - uma pessoa IVMS 101, ou um bloco inteiro, como
originator_dataoubeneficiary_data.
naturalPerson ou uma legalPerson, o que torna a parte uma empresa. Um originator_data ou beneficiary_data plano não vazio prevalece sobre um bloco do mesmo lado.
400 com a chave do seu caminho, por exemplo {"travel_rule_details": {"originator.originatorPersons": ["must be a non-empty list of originator persons."]}}. Em POST /v3/travel-rule/inbound/, as mesmas chaves ficam no nível superior, sob ivms101. quando você usou o objeto envoltório.
Dados obrigatórios por regime
Enquanto a Travel Rule está ativada, uma transferência de saída igual ou acima do seu limiar deve conter o que o seu regime exige, ou retorna400. Apenas os lados que você enviou são verificados, os dados verificados contam para o remetente, e os erros ficam sob travel_rule_details.originator_data ou travel_rule_details.beneficiary_data, por exemplo "EU TFR requires the originator name." ou "FATF Recommendation 16 requires the beneficiary wallet address.":
data_sharing_fields, porque são apenas esses que um trilho envia. O beneficiário é verificado tal como você o enviou. Quando a transferência só atende ao regime com um campo que você não compartilha, o 400 indica o requisito do regime e, em seguida, os campos que as suas configurações compartilham.
O número do documento oficial é national_id (ou document_number), o número de identificação do cliente é customer_identification (ou vendor_data) e a data de nascimento é date_of_birth. Um beneficiary_data.wallet_address vazio é preenchido com counterparty.payment_method.account_id antes da verificação. Um saque UTXO cuja saída do beneficiário a Didit inferiu a partir de travel_rule_details.utxo conta como se contivesse esse dado. Uma transferência Lightning à qual a Travel Rule não se aplica não é verificada.
Endereços de viagem
Um endereço de viagem (travel address) é uma string compacta e codificada que aponta para o endpoint de consultaTRP de entrada de um VASP. Ele nunca expõe uma URL bruta nem qualquer endereço de carteira.
Depois que a Travel Rule é ativada, a Didit gera o seu próprio travel_address (retornado como somente leitura nas configurações) para que você possa compartilhá-lo com outros VASPs que chegam até você pelo canal TRP.
Cada carteira da sua própria agenda de endereços também recebe um receiving_travel_address próprio: uma consulta enviada a ele identifica essa carteira, então a Didit não precisa encontrá-la pelo número da conta ou pelo nome do titular.
O host TRP público da Didit ainda não responde a outros VASPs, portanto o recebimento por TRP só estará disponível quando isso acontecer: consulte Redes da Travel Rule.
Quando você souber o endereço de viagem de uma contraparte, armazene-o no registro da agenda de endereços de carteiras de destino para que a Didit encaminhe as transferências desse beneficiário diretamente por TRP, em vez de recorrer ao e-mail.
A Didit valida os endereços de viagem que você armazena em um registro da agenda de endereços de carteiras ou envia em originating_vasp: cada um deve começar com ta e ser decodificado em uma URL de consulta que contenha t=i. Por isso, um valor provisório como ta... retorna 400.
Um beneficiary_data.travel_address em uma transação não é validado: se ele não puder ser decodificado, o canal TRP é ignorado.
A codificação é Base58Check com o prefixo ta: o host e o caminho do endpoint (que sempre contém o par de consulta t=i), mais um checksum double-SHA-256 de quatro bytes, codificados em base58.
Um endereço real, portanto, tem esta aparência e chega a cerca de 100 caracteres:
400 com "Invalid travel address.".
Use um endereço real obtido na resposta das suas próprias configurações ou fornecido pela própria contraparte.
Testes sem credenciais de rede
Você não precisa ser membro da GTR, TRUST, VerifyVASP ou Sygna para testar os caminhos que dispensam associação. Você ainda precisa de uma chave de API da Didit para a aplicação em teste.- Envio em sandbox: envie uma transação
travelRulea partir de uma aplicação de sandbox. Após as verificações de limiar e de carteira autocustodiada, o Didit Test VASP responde a ela dentro da Didit com o cenário que você escolher pela carteira ou pelo nome do beneficiário: aceitar, recusar, divergência de nome, inacessível, tempo esgotado ou autocustodiada. Nenhuma rede, e-mail ou outro cliente da Didit recebe nada. - Recebimento em sandbox: faça o VASP de teste enviar uma transferência para você com Trigger Test VASP Inbound Transfer ou registre uma você mesmo com Register Inbound Travel Rule Transfer. Teste uma carteira desconhecida, uma carteira não verificada, uma divergência no nome do beneficiário e uma carteira verificada e correspondente. Esses testes acionam decisões reais de recebimento sem contatar nenhuma rede.
- Duas aplicações de produção controladas: use o canal
INTERNALentre duas das suas próprias aplicações de produção (a que recebe pode ser descoberta e comprova o controle da carteira de destino com uma mensagem assinada ou um depósito de teste), ou uma contraparte TRP controlada, para testar uma troca entre duas partes sem credenciais comerciais de rede. Aplicações de produção podem gerar cobranças e notificações normais; use identidades de teste e contrapartes que você controla.
Envio de uma transferência
Inclua a transferência emPOST /v3/transactions/ definindo transaction_category como travelRule (ou travel_rule) e anexando um objeto travel_rule_details (alias: travelRule).
O bloco travel_rule_details em si é opcional, mas, depois que você o anexa, travel_rule_details.status passa a ser obrigatório: um bloco sem ele retorna 400.
Quando o Travel Rule está ativado para a sua aplicação, a Didit ignora o valor de status que você envia e conduz a troca por conta própria:
- Se o valor estiver abaixo do
threshold_amountconfigurado, a transferência é resolvida imediatamente comoNOT_APPLICABLEe nada é negociado. - Se o método de pagamento da contraparte declarar o destino como uma carteira autocustodiada (
payment_method.method_type: "unhosted_wallet"), nenhum trilho é tentado: a transferência vai direto paraUNCONFIRMED_OWNERSHIPe o widget de propriedade da carteira é gerado automaticamente (veja Carteiras autocustodiadas declaradas). - Caso contrário, os trilhos são executados em ordem de prioridade, e o primeiro que conseguir alcançar a contraparte conduz a troca:
INTERNAL- exatamente um outro cliente da Didit tem uma prova por mensagem assinada ou por depósito de teste parabeneficiary_data.wallet_address, feita depois da última troca de titular da carteira. A sua própria aplicação nunca conta e, quando o seu usuário final escolheu um membro da rede Didit no widget de propriedade da carteira, só a prova desse membro conta. A aplicação desse cliente está em produção (não em sandbox), tem o Travel Rule ativado eis_discoverabledefinido, e é o VASP que você indicou quando enviacounterparty_vasp_leioucounterparty_vasp_name. Uma carteira apenas autodeclarada, comprovada por captura de tela, não verificada ou apenas listada em um catálogo de endereços nunca recebe nada peloINTERNAL.TRP- o ativo da transferência tem um mapeamento de Digital Token Identifier para a rede da transferência (veja Identificadores de ativos TRP), e o payload trazbeneficiary_data.travel_address, a entrada do catálogo de endereços do próprio destino armazena um, ou a contraparte é resolvida no diretório (porcounterparty_vasp_leioucounterparty_vasp_name) com um endpoint TRP.GTR,TRUST,VERIFYVASP,SYGNA- você conectou a sua própria associação a essa rede em Marketplace, e a contraparte é resolvida para um ID de rede (campo explícito ou entrada do diretório; veja Campos de resolução da contraparte). A Didit ainda não tem associação de plataforma nessas redes (está em processo de onboarding como provedor), entãodisabled_networksnão altera esta etapa hoje.EMAIL-beneficiary_data.counterparty_vasp_emailfoi informado, oucounterparty_vasp_nameé resolvido para uma entrada do diretório com um e-mail de conformidade.
- Se nenhum trilho conseguir resolver uma contraparte, a Didit executa a cadeia de descoberta de contraparte. Com
vasp_attribution_enabledativado, isso inclui a atribuição por análise de blockchain: a carteira de destino é associada ao VASP que a detém, o nome atribuído é gravado embeneficiary_data.counterparty_vasp_name(quando vazio) e no diretório, e os trilhos são executados novamente uma vez. Assim, uma carteira atribuída a um VASP cuja entrada no diretório traz um endpoint TRP, um ID de rede ou um e-mail de conformidade é roteada nesta segunda passagem. - Se a contraparte continuar sem resolução, a transferência passa para
COUNTERPARTY_VASP_NOT_FOUND. Em transferências de saída, a Didit gera automaticamente o widget de propriedade da carteira (quandoauto_wallet_verificationestá ativado) para que a transferência ainda possa ser concluída como transferência para carteira autocustodiada, e você pode executar o roteamento novamente mais tarde comaction: "resend"quando tiver dados melhores da contraparte.
AWAITING_COUNTERPARTY com protocol: null, e cada resultado chega como um webhook travel_rule.status.updated.
Identificadores de ativos TRP
OTRP identifica o ativo transferido pelo seu Digital Token Identifier (DTI) da ISO 24165.
Um DTI identifica um token em uma blockchain, portanto um token multichain tem um DTI por rede.
A Didit envia transferências pelo TRP para estes ativos:
USDC são os que o emissor do token publica no seu white paper MiCA.
Para um token multichain, a transferência deve indicar a sua rede em transaction_details.crypto_params.crypto_chain (por exemplo, CELO, BASE, OP, ARB ou POL).
Sem uma rede, ou em uma rede sem mapeamento, a transferência não é enviada pelo TRP e a Didit tenta os trilhos restantes: primeiro as redes de interoperabilidade, depois o e-mail.
O USDT ainda não está mapeado.
Um token sem mapeamento de DTI, como a stablecoin própria de uma empresa, exige que o seu emissor registre um DTI junto à autoridade de registro da ISO 24165, um por token por blockchain.
Depois que os DTIs existirem, entre em contato com o suporte da Didit informando cada DTI, a sua blockchain e as casas decimais do token, e a Didit adiciona o mapeamento.
Consultas TRP de entrada que trazem um DTI por cadeia mapeado são registradas com a moeda do token, o valor nas casas decimais do token e a rede.
Descoberta de contraparte
Uma transferência que traz apenas um endereço de carteira ainda chega à sua contraparte sempre que alguém consegue identificá-la. Antes de uma transferência de saída ser declarada impossível de rotear, a Didit consulta, nesta ordem, e para na primeira etapa que indicar um VASP com uma rota:discovery da transferência lista cada etapa executada com seu outcome (match, miss ou skipped), um reason legível por máquina, o vasp e o rail encontrados e um registro de data e hora.
Um VASP escolhido por você ou pelo usuário final tem prioridade sobre todas as etapas automáticas: a descoberta nunca o substitui por um palpite próprio.
Quando nenhuma etapa identifica uma contraparte, a transferência passa para COUNTERPARTY_VASP_NOT_FOUND, ou para COUNTERPARTY_VASP_NOT_REACHABLE quando um VASP foi identificado, mas nenhuma de suas rotas está disponível para sua aplicação.
A transferência passa então a ter um reason (awaiting_end_user, no_directory_match, directory_match_no_route ou picked_member_without_proven_wallet quando o membro escolhido pelo usuário final não comprovou a carteira) e uma lista de next_actions:
url nas ações que o usuário final executa.
Quando uma ação de propriedade de carteira está pendente, o bloco action_required da transação (tipo wallet_ownership) traz o mesmo reason e as mesmas next_actions, de modo que um cliente que já acompanha action_required exibe o seletor sem trabalho adicional.
Campos de resolução da contraparte
Tudo o que a Didit sabe sobre a contraparte vem detravel_rule_details.beneficiary_data.
Estes campos orientam a resolução do rail; todos são opcionais:
Formatos de blockchain
Em uma blockchain baseada em contas (blockchains EVM, Solana, Tron), uma transferência move fundos de um endereço para outro, e a Didit lê as duas carteiras diretamente da transação. Três outros formatos exigem mais, e o que a Didit resolveu para eles fica na transferência comochain_details (vazio, {}, em uma blockchain baseada em contas).
chain_details.originator e chain_details.beneficiary trazem, cada um, o address, seu memo e a source de onde veio, e a correspondência e o roteamento leem as carteiras primeiro a partir daí.
Transferências UTXO
Uma transação de Bitcoin, Litecoin, Bitcoin Cash ou Dogecoin gasta entradas de qualquer número de endereços e paga qualquer número de saídas, algumas delas como troco de volta ao remetente. Envie as entradas e saídas comotravel_rule_details.utxo (valores na unidade da própria moeda, como strings decimais), e a Didit infere o que você não declarar:
- Remetente:
originator_data.wallet_addressquando você o envia; caso contrário, o endereço de entrada que mais contribuiu (source: largest_input). - Beneficiário: a carteira declarada; caso contrário, a única saída que não devolve troco a um endereço de entrada (
only_non_change_output); caso contrário, a única saída que paga o valor da transferência (amount_match).
chain_details.warnings sinaliza o que não confere: declared_originator_not_an_input, declared_beneficiary_not_an_output, beneficiary_output_ambiguous (nenhuma saída pôde ser distinguida das demais) e beneficiary_output_amount_differs.
utxo em qualquer outra chain resulta em 400, e cada lista contém no máximo 1.000 entradas.
Um depósito informado recebe o mesmo objeto utxo (consulte Registro sunrise após o depósito).
Redes com memo e tag
Em XRP, Stellar (XLM), EOS, Cosmos (ATOM) e Hedera (HBAR), uma exchange recebe todos os clientes em um único endereço compartilhado e os distingue pela destination tag ou pelo memo. Por isso, o memo faz parte da carteira: envie-o comopayment_method.memo no participante, ou como memo em originator_data / beneficiary_data (alias destinationTag), e a Didit compara o endereço e o memo em conjunto.
- Uma entrada do catálogo de endereços com memo corresponde apenas às transferências que indicam esse memo. Uma entrada sem memo corresponde ao endereço inteiro. Uma transferência que não indica memo nunca chega a uma entrada que tem memo: em um endereço compartilhado, um depósito sem a sua tag não pertence a ninguém.
- Um X-address de XRP traz a tag embutida: a Didit o divide no endereço clássico e na tag (
source: x_address), de modo que uma carteira registrada em qualquer um dos formatos corresponde a uma transferência no outro. - Cada memo em um endereço compartilhado é um método de pagamento próprio na transação.
- O que cada rede aceita: uma destination tag de XRP é um número inteiro de 0 a 4294967295 (um número JSON é aceito); um memo da Stellar tem até 28 bytes de texto, um id de 64 bits ou um hash de 32 bytes em hexadecimal; EOS aceita até 256 bytes, Cosmos até 256 caracteres e Hedera até 100 bytes. Um memo em uma chain que não tem memo (Bitcoin, chains EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin, Lightning) resulta em
400.
Lightning
Um pagamento Lightning não tem endereço on-chain do beneficiário: o pagador tem uma solicitação de pagamento. Em uma transferência de cripto em bitcoin ou Lightning,payment_method.account_id pode ser essa solicitação, e a Didit identifica o beneficiário a partir dela sem contatar nenhuma rede:
chain_details.beneficiary (source: invoice_payee), na chain LIGHTNING, e o conteúdo da solicitação fica em chain_details.lightning.
Quando a solicitação não indica nenhum recebedor, uma transferência de saída fica NOT_APPLICABLE, com o motivo em chain_details.not_applicable_reason e na sua timeline: LIGHTNING_NO_PAYEE_IDENTIFIER, LIGHTNING_BOLT12_BLINDED_PAYEE ou LIGHTNING_LNURL_NAMES_NO_PAYEE.
Um valor é interpretado como Lightning apenas em bitcoin, em LIGHTNING ou quando nenhuma chain é indicada (uma Lightning Address apenas em bitcoin ou LIGHTNING): em qualquer outra chain, ele é um endereço da própria chain.
INTERNAL chega a outro cliente da Didit somente por meio de uma carteira que esse cliente comprovou controlar com uma mensagem assinada ou um depósito de teste, e essas comprovações existem hoje para Bitcoin, chains EVM, Solana e Tron.
Portanto, em redes com memo, Lightning, Litecoin, Bitcoin Cash e Dogecoin, uma transferência nunca chega a outro cliente da Didit pelo INTERNAL.
A correspondência por memo, tag e Lightning continua valendo para o seu próprio catálogo de endereços: transferências de entrada, depósitos informados e consultas TRP às suas carteiras.Atualização da carteira do remetente
Um saque costuma ser declarado a partir da carteira principal do seu cliente e transmitido a partir de quaisquer endereços que detinham as moedas. Registre a carteira da qual os fundos realmente saíram comPATCH /v3/transactions/{transaction_id}/travel-rule/:
- Somente transferências de saída, e nunca uma
CANCELLEDouEXPIRED(409). - Quando as entradas UTXO da transferência são conhecidas, a carteira deve ser uma delas (caso contrário,
400). Em uma rede com memo, envie tambémmemo. - Isso altera apenas o registro: nada é reenviado à contraparte e o status se mantém.
chain_details.originatorpassa a ser a nova carteira comsource: updated, atimelineregistra a carteira anterior e a nova, e a contraparteINTERNALda transferência é atualizada da mesma forma.
Atribuição por análise de blockchain
Quando você informa apenas um endereço de carteira, a Didit ainda consegue descobrir quem está do outro lado. Se nenhum rail consegue rotear a transferência, a Didit resolve a carteira de destino com base em dados de atribuição de análise de blockchain - a mesma análise que alimenta a triagem de transações cripto sabe quais carteiras pertencem a quais exchanges e custodiantes. A atribuição é executada apenas em transferências de saída que contêm tanto uma carteira de destino quanto umachain (consulte Campos de resolução da contraparte); sem uma chain, ela é ignorada.
Quando a carteira é atribuída a uma entidade conhecida, a Didit:
- Registra a atribuição na transferência:
beneficiary_data.counterparty_vasp_nameé preenchido (quando você não informou um), e os metadados da transferência contêm um blocovasp_attributioncom o nome da entidade, o tipo da entidade, o país esource: "blockchain_analytics". - Adiciona a entidade ao diretório de VASPs (ou a associa à entrada existente), para que a atribuição se mantenha estável entre transferências.
- Executa os rails novamente uma vez com o nome atribuído - uma entrada do diretório que já tem um endpoint TRP faz a transferência ser roteada imediatamente, em vez de cair em
COUNTERPARTY_VASP_NOT_FOUND.
custom_values.aml_screening_trigger da transação é definido como travel_rule_attribution, para que você veja que a triagem foi executada porque o roteamento da Travel Rule a exigiu.
Quando o monitoramento cripto já fez a triagem da mesma carteira nesta transação, o resultado armazenado é reutilizado - sem uma segunda chamada de análise e sem uma segunda cobrança.
A atribuição nunca bloqueia a criação da transação: se a consulta de análise falhar ou o seu saldo não for suficiente para cobri-la, a transferência simplesmente segue para COUNTERPARTY_VASP_NOT_FOUND e nada é cobrado pela tentativa.
Em action: "resend", uma atribuição registrada anteriormente é reutilizada em vez de ser consultada novamente.
Desative a etapa inteira com vasp_attribution_enabled: false nas configurações.
Consulte Preços para saber como a chamada de atribuição é cobrada.
Quando a Travel Rule está desativada, travel_rule_details (incluindo um status informado por quem faz a chamada, legado ou atual) continua sendo registrado na transação, mas de forma passiva: nenhum rail é acionado.
Use isso para preencher retroativamente dados de conformidade que você já acompanhava com o seu próprio processo.
Uma transferência de saída passiva não inicia nenhuma troca, por isso é cobrada como Transaction Screening, e não na linha da Travel Rule.
Com a Travel Rule ativada, esta requisição é roteada pelo rail EMAIL, porque informa o e-mail de conformidade da contraparte e nenhum rail anterior consegue alcançar o beneficiário:
originator_dataé o que você enviou, porque o titular do exemplo não tem uma verificação KYC aprovada. Para um usuário verificado, a Didit o monta a partir dos dados verificados (consulte Dados verificados e procedência). O railEMAILmostra ao destinatário apenas os campos do remetente que você compartilha emdata_sharing_fields.beneficiary_data.chainéETHporque a requisição não informou nenhuma chain, então a Didit a obteve a partir da moeda.statuséAPPROVEDporque nenhuma regra atuou sobre a transação. Suas próprias regras podem definir outro status.- O contato de conformidade recebe o link de retirada. A transferência é concluída, falha na correspondência de nome ou é recusada quando ele responde, ou expira se ele não responder (consulte Retirada por e-mail).
protocol ainda é null porque o rail é escolhido depois da resposta (por exemplo, EMAIL quando você informou counterparty_vasp_email). Obter transação o mostra depois de escolhido, e todo webhook travel_rule.status.updated posterior o traz em rail.
Se a carteira do beneficiário pertencer a outro cliente da Didit que comprovou ter controle sobre ela, o rail INTERNAL conclui toda a troca logo após a resposta, e esse webhook já informa COMPLETED (ou COUNTERPARTY_MISMATCHED_DATA). Quando o nome não corresponde, sua transferência fica em COUNTERPARTY_MISMATCHED_DATA e o outro cliente não recebe nada.
Sem counterparty_vasp_email, e quando nem os rails nem a atribuição conseguem alcançar o beneficiário, a transferência termina depois em COUNTERPARTY_VASP_NOT_FOUND, com uma ação wallet_ownership na transação.
travel_rule incorporado à transação traz os campos próprios da transferência (uuid, status, protocol, required, obligations_count, originator_data, beneficiary_data, metadata), o que a Didit resolveu e comparou (chain_details, name_match, data_match, mismatched_fields e os campos de mascaramento data_masked e data_unmasked) e os campos que indicam em que ponto ela está: direction, rail, counterparty_vasp, delivery, discovery, reason e next_actions (consulte Por que uma transferência fica travada).
Cada linha de GET /v3/transactions/ traz o mesmo bloco, ou null para uma transação sem transferência.
Os endpoints dedicados a transferências descritos abaixo também retornam esses campos, além de ivms_version, ownership_confirmed, deadline_at, timeline e created_at, mas não obligations_count nem metadata.COMPLETED depois de transmiti-la on-chain:
COMPLETED; caso contrário, a API retorna 409.
Em caso de sucesso, tanto a transferência de saída quanto a sua contraparte no rail INTERNAL passam para FINISHED, e o payment_txn_id da transação recebe o hash que você informou.
No rail TRP, a Didit também envia o hash para o callback de confirmação da contraparte.
Para cancelar uma transferência que ainda não chegou a um estado final, envie {"action": "cancel"} para o mesmo endpoint.
A contraparte no rail INTERNAL também é cancelada e, no rail TRP, depois que a contraparte aprova a consulta, a Didit envia o cancelamento para o callback de confirmação dela.
Uma transferência que já está em FINISHED, CANCELLED ou EXPIRED retorna 409.
Uma requisição sem payment_txn_id e sem uma action compatível retorna 400.
Em uma transferência que passou por GTR, VERIFYVASP ou SYGNA, a Didit informa o hash on-chain (ou o cancelamento) à rede depois da resposta, com as mesmas novas tentativas. O delivery da resposta mostra essa mensagem.
Para tentar novamente uma transferência de saída que não conseguiu alcançar a contraparte, ou seja, uma que esteja atualmente em COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA, primeiro melhore os dados da contraparte. Por exemplo, adicione um travel_address à entrada da carteira de destino, adicione um contato à entrada da contraparte no diretório ou catalogue o VASP no diretório.
Em seguida, envie {"action": "resend"} para o mesmo endpoint.
A Didit reinicia o prazo de confirmação e coloca a sequência de roteamento novamente na fila desde o início, usando os dados armazenados na transferência: a resposta mostra a transferência de volta em AWAITING_COUNTERPARTY (com resend queued no seu timeline), e o resultado chega como um webhook travel_rule.status.updated.
Um reenvio feito enquanto uma tentativa anterior ainda está em andamento é enviado assim que essa tentativa termina.
Qualquer outro status, ou uma transferência de entrada, retorna 409.
{"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"} (o id de GET /v3/travel-rule/vasps/).
A transferência é roteada para esse VASP e enviada novamente.
Somente uma transferência de saída em COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA aceita essa ação. Qualquer outro status retorna 409, e um id desconhecido retorna 404.
Por que uma transferência fica travada
Uma transferência emCOUNTERPARTY_VASP_NOT_FOUND ou COUNTERPARTY_VASP_NOT_REACHABLE informa por que está travada e o que a faz avançar, em toda leitura da sua transação.
O bloco travel_rule de GET /v3/transactions/{transaction_id}/, do 201 de POST /v3/transactions/ e de cada linha de GET /v3/transactions/ traz essa informação, assim como o objeto de transferência com que o endpoint de transferência responde:
reasoné a causa legível por máquina,""em qualquer outro status.next_actionslista o que faz a transferência avançar,[]em qualquer outro status.deliveryé a mensagem mais recente que a transferência deve entregar à outra parte:kind,status(QUEUED,SENDING,RETRYING,DELIVEREDouFAILED),rail,attempts,last_error,next_attempt_atedelivered_at, ounullquando não houve nenhuma a entregar.discoverymostra onde a Didit procurou a contraparte, com uma entrada por etapa executada:step,outcome(match,missouskipped),reason,vasp,raileat.
email_undeliverable e delivery_failed resultam de uma entrega com falha e aparecem apenas em COUNTERPARTY_VASP_NOT_REACHABLE.
Uma entrega com falha define o reason primeiro, de modo que uma contraparte que a Didit encontrou nunca é informada como uma que ela não conseguiu encontrar.
Os outros quatro vêm do rastro de descoberta, em qualquer um dos dois status.
reason dela é limpo.
A entrada da linha do tempo de uma transição causada por uma entrega com falha traz o mesmo valor em reason.
Se o provedor de e-mail recusar o e-mail de conformidade da transferência de exemplo acima, o bloco travel_rule da transação fica assim, de forma resumida:
delivery coincide com reason, porque o próprio envio foi recusado.
Uma recusa em um lembrete, ou um bounce informado depois, mantém delivery.status em DELIVERED: o primeiro e-mail de fato foi enviado.
Leia reason, não delivery, para saber por que uma transferência está travada.
Para corrigir, informe novamente o e-mail de conformidade da contraparte e depois reenvie:
update_compliance_email mantém o endereço como beneficiary_data.counterparty_vasp_email desta transferência: ele pertence somente a esta transferência e não entra em nenhuma entrada do diretório nem em nenhuma lista de contatos.
O status não muda, a linha do tempo ganha compliance email updated e a transferência mantém reason: email_undeliverable até que o reenvio envie a requisição para o novo endereço.
Somente uma transferência de saída em COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA aceita essa ação; qualquer outra transferência responde 409, e um compliance_email ausente ou malformado responde 400.
Carteiras autocustodiadas declaradas
Quando seu cliente informar que o destino é a própria carteira autocustodiada (não hospedada), declare isso na transação em vez de deixar o roteamento descobrir que não há nenhum VASP por trás dela: defina o tipo de método de pagamento da contraparte comounhosted_wallet.
- Nenhum rail é tentado (não há VASP de contraparte com quem trocar dados) e a transferência é criada diretamente em
UNCONFIRMED_OWNERSHIP. - Quando
auto_wallet_verificationestá ativado (o padrão), a Didit gera automaticamente uma sessão do widget de propriedade da carteira vinculada à transação e a retorna no blocoaction_requiredda transação; os SDKs a abrem automaticamente no envio pelo lado do cliente. - Assim que o cliente comprova o controle da carteira, a transferência executa a correspondência do nome do beneficiário e avança para
COMPLETED(ouCOUNTERPARTY_MISMATCHED_DATAse a correspondência falhar).
UNCONFIRMED_OWNERSHIP não é um estado que permite reenvio: conclua a comprovação de propriedade (ou cancele) em vez de chamar action: "resend".
Recebimento
Confirmação de propriedade da carteira
Uma transferência fica emUNCONFIRMED_OWNERSHIP em dois casos:
- Uma transferência de entrada corresponde a uma entrada do catálogo de endereços cuja propriedade ainda não foi verificada.
- A carteira da contraparte foi declarada autocustodiada (
counterparty.payment_method.method_type: "unhosted_wallet"), em um saque de saída ou em um depósito de entrada. Consulte Carteiras autocustodiadas declaradas.
confirmed (obrigatório, booleano) e um wallet_address opcional.
O endpoint aceita uma transferência em qualquer um destes estados e retorna 409 com {"detail": "Transfer is not awaiting ownership confirmation."} para qualquer outro:
UNCONFIRMED_OWNERSHIP, em qualquer direção.ON_HOLDem uma transferência de entrada.UNCONFIRMED_OWNERSHIP,ON_HOLDouCOUNTERPARTY_MISMATCHED_DATAem uma transferênciaTRPde entrada, para que um responsável por conformidade possa resolver manualmente uma consulta da contraparte.
INTERNAL, registro sunrise ou carteira autocustodiada declarada):
confirmed: truemarca a entrada correspondente do catálogo de endereços de carteiras como verificada quanto à propriedade e, em seguida, executa a correspondência de nome com oholder_namedessa entrada:COMPLETEDse ela for aprovada,COUNTERPARTY_MISMATCHED_DATAse não for. A contraparte no trilhoINTERNAL, quando existe, recebe o mesmo resultado. Para uma carteira autocustodiada declarada,confirmed: trueregistra que seu cliente verificou quem controla a carteira da contraparte e conclui a transferência (COMPLETED), seja de saída ou de entrada. Uma transferência de entrada cujo depósito já foi liquidado passa então diretamente paraFINISHED.confirmed: falsemove os dois lados da transferência paraCOUNTERPARTY_VASP_GENERAL_DECLINE.- A entrada correspondente é buscada no seu próprio catálogo de endereços apenas pelo endereço da carteira, sem considerar a blockchain.
Resolver uma transferência de entrada em
ON_HOLDsem entrada correspondente cria a entrada a partir dobeneficiary_data.wallet_addressda transferência e a marca como verificada. Uma carteira autocustodiada declarada é a exceção: a carteira é registrada no seu catálogo de endereços como verificada quanto à propriedade, conforme descrito abaixo. Em todos os outros casos, uma entrada inexistente retorna409com{"detail": "wallet address entry no longer available"}, que também é o que uma entrada excluída retorna.
TRP de entrada, a mesma chamada responde à consulta da contraparte:
confirmed: trueexige um endereço de pagamento a ser retornado, obtido dowallet_addressda requisição, depois da entrada correspondente e depois debeneficiary_data.wallet_address. Sem nenhum dos três, a requisição retorna400com{"wallet_address": ["wallet_address is required to approve."]}. A Didit cria ou verifica a entrada, envia o callback de resolução da consulta à contraparte, defineownership_confirmede move a transferência paraCOMPLETED.confirmed: falseenvia uma resolução de recusa e move a transferência paraCOUNTERPARTY_VASP_GENERAL_DECLINE.- Se o endpoint de callback da contraparte não puder ser alcançado, a requisição retorna
502e a transferência mantém seu status atual. Em uma aprovação, a entrada do catálogo de endereços de carteiras ainda é criada ou marcada como verificada.
COUNTERPARTY_MISMATCHED_DATA.
Se a transferência não indicar nenhuma carteira da contraparte, informe wallet_address no corpo da requisição.
Quando nem a transferência nem a requisição fornecem um endereço de carteira, a requisição é rejeitada com 400.
- Uma transferência de rede já respondida pela própria rede (uma transferência VerifyVASP, ou uma transferência GTR ou Sygna Bridge já decidida) retorna
409(consulte Transferências de uma rede).
INTERNAL nunca fica aguardando aqui: ela só chega a um cliente que já comprovou a carteira. Uma transferência INTERNAL mais antiga, ainda aguardando desde antes dessa regra, mantém os dados do remetente ocultos até que você comprove o controle da carteira (uma mensagem assinada ou um depósito de teste), e confirmá-la retorna 409 até que você o faça. Recusá-la continua funcionando.
Quando a contraparte responde que a carteira é autocustodiada (hoje, o Didit Test VASP dá essa resposta no sandbox), confirmar adiciona a carteira ao seu catálogo de endereços sob o nome do beneficiário e executa a correspondência de nome: uma correspondência conclui a transferência e marca a carteira como verificada.
Transferências de uma rede
A Didit também pode receber transferências Travel Rule que uma contraparte envia porGTR, VERIFYVASP ou SYGNA.
O recebimento é ativado pela Didit para cada rede separadamente, e nenhuma está ativada hoje: ele também exige que cada rede registre os endpoints da Didit, e a Didit ainda não é membro dessas redes.
Transferências TRUST não podem ser recebidas.
Depois que uma rede é ativada, uma mensagem entregue por ela é tratada assim:
- Roteamento. A mensagem chega à sua aplicação quando indica o código de participante da sua própria associação conectada a essa rede. Uma mensagem endereçada à associação da própria Didit só chega até você quando você é o único cliente da Didit em produção que comprovou o controle da carteira do beneficiário. Qualquer outra é recusada, para que nenhum cliente jamais receba a transferência de outro cliente.
- Decisão. A Didit cria a transferência de entrada na sua aplicação e a decide como uma consulta TRP: correspondência de carteira, propriedade, correspondência de nome e
inbound_auto_accept. - Uma única vez. As redes reenviam uma mensagem até que ela seja respondida. Uma repetição recebe a mesma resposta que a primeira cópia recebeu, e nada é criado ou decidido duas vezes.
- Sua revisão, por
GTReSYGNA. Uma transferência que aguarda por você (UNCONFIRMED_OWNERSHIP,ON_HOLDouCOUNTERPARTY_MISMATCHED_DATA) é decidida comPOST .../travel-rule/ownership/:confirmed: truea aprova (informewallet_addressquando a transferência não indicar nenhum) econfirmed: falsea recusa. A Didit responde à rede depois da resposta, com as mesmas novas tentativas. Uma transferência que já foi respondida retorna409. - Sem resposta posterior por
VERIFYVASP. A VerifyVASP recebe a resposta no momento em que pergunta, então uma transferência que precisaria da sua revisão é recusada imediatamente e não pode ser decidida depois (409).
Dados mascarados da contraparte
Até que a propriedade da carteira seja confirmada, os dados pessoais da contraparte em uma transferência recebida vêm mascarados, em vez de omitidos. A primeira letra de cada palavra é mantida, e a carteira, a chain e o roteamento do VASP continuam legíveis.data_masked é true, e a parte contraparte no detalhe da transação, na lista e na exportação CSV é mascarada da mesma forma.
Assim que a propriedade é confirmada, os valores reais aparecem e data_unmasked registra a entrada de auditoria:
reason é ownership_confirmed, wallet_proof, address_book_match, own_verified_wallet, inquiry_approved (você aprovou uma consulta TRP ou uma mensagem GTR ou Sygna), known_payment_method (a carteira do usuário final nos seus próprios registros respondeu) ou travel_address (o travel address por carteira identificou a carteira).
Uma transferência recebida INTERNAL traz data_unmasked com reason: wallet_proof desde o momento em que é criada, porque só um destinatário que comprovou a carteira recebe uma.
actor é o e-mail do usuário do console ou o rótulo da chave de API, e fica em branco para uma decisão automática.
O relatório Registro de transferências da Travel Rule (CSV e PDF) mascara os nomes de uma transferência recebida da mesma forma até que a propriedade seja confirmada. Os relatórios que você envia a um regulador, como o XML do goAML e o PDF do relatório regulatório, trazem os dados reais da contraparte.
Retorno sobre divergências
Uma transferênciaCOUNTERPARTY_MISMATCHED_DATA agora indica os campos que divergem.
data_match contém a comparação e mismatched_fields lista os campos.
Ambos trazem apenas nomes de campos e resultados, nunca valores, por isso continuam legíveis enquanto os dados estão mascarados:
TRP após uma divergência informa ao VASP remetente quais campos divergem, por exemplo “Beneficiary data does not match the wallet holder: name”.
O que o outro VASP fica sabendo é limitado de propósito: enquanto o nome estiver errado, o nome é o único campo informado (mismatched_fields: ["name"], todos os outros campos not_compared), e, assim que o nome corresponde, todo campo que diverge é indicado. Isso se aplica ao lado do remetente de uma troca INTERNAL e a uma rejeição TRP.
Um nome ausente nos dois lados aparece como not_compared e não é uma divergência, e um país corresponde pelo que ele designa, então ES e ESP coincidem.
Pontuação de correspondência de nomes
Toda transferência cujo nome foi comparado trazname_match, e a entrada da linha do tempo que decidiu isso traz o mesmo objeto ao lado do seu detail:
scoreé a similaridade entre os dois nomes completos, de 0 a 100, e0quando algum deles está em branco.matchedé o resultado no nível destrictness, então os dois podem discordar:FUZZYdecide pela própria razão de similaridade de0.85.matched_namessão as palavras do nome da transferência encontradas no outro nome;mismatched_namessão as palavras que um dos lados tem e o outro não.methodénone,exact_token,token_subset,token_containmentousequence_ratio, paraNONE,STRICT,DEFAULT,CONTAINSeFUZZY.compared_withéwallet_holder(o titular registrado para a carteira) oucounterparty_vasp(o nome que a contraparte respondeu na página de resposta por e-mail, ou a resposta do Didit Test VASP).- O resultado da transferência segue
data_match, que compara todos os campos, então uma transferência pode serCOUNTERPARTY_MISMATCHED_DATAenquantoname_match.matchedétrue. name_matchestá no objeto de transferência que os endpoints da Travel Rule retornam e notravel_ruleincorporado da transação, e énullaté que um nome seja comparado. A lista de transferências e os webhooks não o incluem.- Os nomes ficam ocultos enquanto as partes estão mascaradas e na cópia do outro cliente de uma troca
INTERNAL.
Mensagens e solicitações de documentos
Dois VASPs podem resolver uma transferência contestada dentro da Didit, em vez de por e-mail.GET e POST /v3/transactions/{transaction_id}/travel-rule/messages/ listam e enviam mensagens em uma transferência:
kindéMESSAGE(padrão) ouDOCUMENT_REQUEST. Uma solicitação de documento precisa de pelo menos uma entrada emrequested_documents(até 10); uma mensagem precisa de umbody(até 5000 caracteres) ou de um arquivo.reply_toindica uma mensagem anterior da mesma transferência. Uma resposta do outro lado que traz um documento atende à solicitação de documento que ela responde, efulfilled_até preenchido nela. Sua própria resposta nunca atende à sua própria solicitação.- Envie multipart com
filespara anexar até 5 arquivos de 10 MB cada, em PDF, PNG, JPEG ou WebP. A Didit verifica o conteúdo de cada arquivo, não apenas o tipo declarado, e qualquer outro arquivo retorna400emfiles(“Attach PDF, PNG, JPEG or WebP files only.”). - Uma transferência comporta até 100 mensagens, das quais até 20 podem ter anexos (cada uma com até 5 arquivos), contando os dois lados; além de qualquer um desses limites, a requisição retorna
400. Os anexos de mensagens não contam para os documentos da própria transação. - As mensagens funcionam nos rails
INTERNALeEMAIL. NoINTERNAL, o outro cliente da Didit vê a mensagem no seu lado do par. NoEMAIL, a contraparte recebe um e-mail e responde no portal de retirada. Se esse e-mail de notificação não puder ser enviado, a mensagem é salva mesmo assim e a requisição retorna201. - A requisição retorna
409com um motivo emdetailpara uma transferência porTRP,GTR,TRUST,VerifyVASPouSygna(esses protocolos não transportam mensagens), uma transferência ainda sem contraparte, uma transferênciaINTERNALcujos dados não corresponderam ao titular da carteira (nada chegou ao destinatário), uma transferênciaINTERNALcujo destinatário ainda não comprovou o controle da carteira (nos dois lados, até que comprove), uma transferênciaEMAILcuja contraparte não tem mais um endereço de e-mail de conformidade e uma transferênciaEMAILcujo link de retirada expirou ou cuja transferência está encerrada. - Nenhum webhook é disparado quando a contraparte responde. Consulte o endpoint de mensagens.
- O e-mail que avisa a contraparte sobre uma nova mensagem é enviado em inglês.
Catálogo de endereços de carteiras
Registre as carteiras que você controla para que as transferências recebidas (railINTERNAL, consultas TRP recebidas e registros após o depósito) possam ser resolvidas com base nelas, usando POST/GET /v3/travel-rule/wallet-addresses/ e PATCH/DELETE /v3/travel-rule/wallet-addresses/{entry_uuid}/.
PATCH aceita holder_name, holder_vendor_data, entity_type e travel_address, e retorna apenas esses quatro campos.
DELETE exclui a entrada (204): o endereço fica liberado para novo registro e ela deixa imediatamente de corresponder a novas transferências.
memo em uma rede com memo e é delimitada por chain.
Quando uma transferência informa uma blockchain, uma entrada só corresponde se o chain dela tiver o mesmo valor (sem diferenciar maiúsculas de minúsculas) ou estiver vazio.
Os nomes de blockchain são comparados como texto, sem conversão, portanto uma entrada armazenada como ethereum não corresponde a uma transferência cuja blockchain é ETH.
As transferências enviadas obtêm a blockchain de beneficiary_data.chain, depois de transaction_details.crypto_params.crypto_chain, depois de custom_properties.crypto_chain e depois da moeda (por exemplo, ETH, ou, para USDT e USDC, a blockchain inferida a partir de payment_reference_id), definida apenas quando é uma blockchain que a Didit reconhece; os registros após depósito a obtêm do campo chain, em minúsculas.
As consultas TRP recebidas ignoram a blockchain: elas correspondem pelo endereço ou, quando a consulta não nomeia nenhuma carteira, pelo nome do beneficiário em relação às suas entradas verificadas.
POST .../travel-rule/ownership/ também corresponde apenas pelo endereço.
Quando várias entradas correspondem, o trilho INTERNAL e os registros após depósito preferem uma entrada com propriedade verificada e, em seguida, a mais antiga; a busca TRP de saída usa a entrada mais antiga que armazena um travel address.
As consultas TRP recebidas e o endpoint de propriedade usam qualquer uma das entradas correspondentes, portanto mantenha uma entrada por endereço sempre que possível.
O trilho INTERNAL não corresponde a nenhuma entrada quando existem entradas verificadas para o endereço em mais de uma outra aplicação.Importação de carteiras em massa
Importe até 10.000 carteiras em uma única chamada comPOST /v3/travel-rule/wallet-addresses/import/, em JSON ({"entries": [...]} ou um array simples) ou como um arquivo CSV UTF-8 de no máximo 5 MB com uma linha de cabeçalho.
Uma linha identifica uma carteira pelo address, pelo address_hash (o SHA-256 do endereço em minúsculas, com 64 caracteres hexadecimais ou 44 em base64) ou por ambos, além de qualquer um dos campos de entrada acima.
Envie apenas o hash para registrar uma carteira sem revelar o endereço: ela corresponde a transferências para esse endereço como qualquer outra entrada e pode ser comprovada com o widget de propriedade de carteira.
created, existing (a mesma carteira, blockchain e memo já está no cadastro e não foi alterada), duplicate (repete uma linha anterior, indicada em duplicate_of_row) ou failed com seus errors.
Uma linha com erro nunca faz as outras falharem: a resposta é 200 quando nenhuma linha falhou e 207 quando alguma falhou, com as contagens em total, created, existing, duplicate e failed.
Uma célula vazia no CSV conta como não enviada, e as colunas que a importação não lê são ignoradas, então uma exportação de outra ferramenta é importada como está.
Em GET /v3/travel-rule/transfers/, cada linha traz originator_memo e beneficiary_memo ao lado das duas carteiras.
Coleta por e-mail para contrapartes inacessíveis
Quando nenhum trilho de protocolo consegue alcançar a contraparte, a Didit recorre aoEMAIL: ela envia um link de coleta de uso único para beneficiary_data.counterparty_vasp_email (ou para um e-mail obtido a partir de beneficiary_data.counterparty_vasp_name no registro do diretório de VASPs).
O destinatário não precisa de uma conta Didit nem de uma chave de API: o token do link é a autenticação.
Como a requisição é enviada:
- Para os endereços certos. Um
counterparty_vasp_emailque você informa é o único destinatário. Caso contrário, a Didit escreve para até três endereços: os contatos da contraparte que não tiveram devolução (os seus primeiro, depois os contatos da plataforma, com os que já responderam antes em primeiro lugar) e, em seguida, o e-mail de conformidade da entrada do diretório, quando sobra uma vaga. Cada endereço recebe o próprio e-mail. - Em seu nome. O e-mail sai do endereço da Didit como “sua razão social via Didit”, no idioma da jurisdição da contraparte (inglês quando nenhuma é conhecida), e o link abre a página de resposta nesse idioma. Você não recebe cópia: acompanhe a linha do tempo da transferência.
- Com lembretes. Até a contraparte responder, a Didit envia lembretes 72, 24 e 6 horas antes do prazo, com no mínimo 12 horas após a requisição ou o último lembrete, e nunca depois do prazo.
- Com tratamento de devoluções. Uma devolução ou uma denúncia de spam marca o contato atingido como inválido, com o motivo, e a linha do tempo da transferência registra isso. Um contato da plataforma passa então a ser inválido para todos os clientes da Didit; o contato próprio da sua aplicação, apenas para a sua aplicação. Quando a entrega de e-mails da Didit para totalmente de enviar para um endereço (após uma devolução permanente, uma denúncia de spam ou um cancelamento de inscrição), todos os contatos nesse endereço são marcados como inválidos (
suppressed) e voltam a ser válidos assim que o envio para o endereço é retomado. Quando não resta nenhum endereço para escrever, a transferência passa aCOUNTERPARTY_VASP_NOT_REACHABLE, com o motivo do servidor de e-mail de destino na linha do tempo. Uma devolução permanente ou uma denúncia de spam nocounterparty_vasp_emailque você informou faz isso imediatamente, porque ele é o único destinatário; uma devolução temporária (soft_bounce) nele, ou no próprio e-mail de conformidade da entrada do diretório, mantém a requisição aberta para os lembretes.
reference é o uuid da transferência. originator_data e o ivms_request IVMS 101 gerado a partir dele contêm apenas os campos do remetente que você compartilha em data_sharing_fields; o nome e a carteira são sempre incluídos. fiat_amount e fiat_currency ficam vazios quando você não enviou nenhum valor convertido, contact repete o valor ?contact= do link e decline_reasons lista os valores aceitos por decline_reason. join_invitation.eligible é true enquanto a contraparte tiver um convite ativo para entrar na Didit; o link do convite em si só é enviado no e-mail.
Este endpoint retorna o valor armazenado sem alterações, por isso traz as 18 casas decimais completas, e não a forma reduzida usada pelo objeto de detalhes da transação.
decision é accept ou decline.
Em accept, o beneficiary_name informado é comparado com o beneficiary_data.name da transferência segundo a sua regra de nomes: COMPLETED quando há correspondência, COUNTERPARTY_MISMATCHED_DATA caso contrário. Em vez disso, a contraparte pode enviar uma resposta IVMS 101 completa como ivms_response; nesse caso, o nome do beneficiário dessa resposta prevalece sobre beneficiary_name.
Em decline, a transferência passa para COUNTERPARTY_VASP_GENERAL_DECLINE. A contraparte pode informar um decline_reason de decline_reasons, com um decline_detail (até 512 caracteres, obrigatório para other), e a linha do tempo da sua transferência registra isso, por exemplo counterparty declined: The beneficiary is not our customer.
A resposta é o {"status": "..."} resultante, mais decline_reason após uma recusa. Depois que a contraparte responde, os dois endpoints retornam 410.
Os dois endpoints retornam 404 para um token desconhecido e 410 quando a janela se encerra: ou a transferência saiu de AWAITING_COUNTERPARTY, ou o prazo de confirmação dela (confirmation_timeout_hours após a criação ou o último reenvio) já passou.
A contraparte lê e responde pelo link de coleta com GET e POST /v3/travel-rule/pickup/{token}/messages/.
Ela não precisa de chave de API, aceita apenas anexos em PDF, PNG, JPEG ou WebP e responde 410 quando o link expira ou a transferência é encerrada.
Uma mensagem que você enviou mostra o nome do seu VASP como author e como uploaded_by do anexo, nunca a pessoa ou a chave de API por trás dela.
Depósitos sem correspondência
Um depósito de entrada pode chegar antes dos dados de Travel Rule do VASP de origem. Esse depósito permanece emAWAITING_COUNTERPARTY ou NOT_ENOUGH_COUNTERPARTY_DATA até os dados chegarem.
Liste os depósitos que ainda estão aguardando com uma chave de API que tenha o privilégio de transações:
GET /v3/travel-rule/transfers/, limitadas aos depósitos de entrada que aguardam os dados do VASP de origem.
Quando os dados tiverem chegado como uma mensagem recebida separada, faça você mesmo o pareamento entre os dois:
{transaction_uuid} é o depósito.
transaction_id é a transação da mensagem de Travel Rule recebida.
A chamada retorna { "deposit": ..., "message": ... }.
Ela responde 404 quando alguma das transações não existe mais e 409 com travel_rule_match_conflict (“This deposit can no longer be matched.”) quando algum dos lados já avançou.
Registro sunrise após o depósito
Quando um depósito de cripto é liquidado on-chain antes de qualquer troca de Travel Rule ter ocorrido (o VASP remetente estava inacessível, ou você está preenchendo retroativamente depósitos históricos), registre-o posteriormente comPOST /v3/travel-rule/inbound/.
originating_vasp.travel_address deve ser um travel address real e com checksum válido: um valor fictício retorna 400 com "Invalid travel address.".
originating_vasp.lei deve estar vazio ou ter 20 caracteres no formato LEI (18 letras ou dígitos, seguidos de 2 dígitos); qualquer outro valor retorna 400 com "Invalid LEI: expected 20 alphanumeric characters (ISO 17442).".
A Didit verifica apenas esse formato, não os dígitos de verificação da ISO 17442.
travelRule de entrada (ou reutiliza um depósito de entrada que você já enviou com o mesmo hash e a mesma carteira, se ele ainda não tiver uma transferência Travel Rule) e confere a transferência com o seu catálogo de endereços de carteiras, pelo endereço e pelo seu memo:
- Nenhuma entrada correspondente ->
ON_HOLD. Resolva comPOST .../travel-rule/ownership/:confirmed: trueadiciona a carteira ao seu catálogo de endereços como verificada e executa a correspondência de nomes; se houver correspondência, a transferência passa paraCOMPLETEDe depois paraFINISHED. - A entrada existe, mas a propriedade não foi comprovada ->
UNCONFIRMED_OWNERSHIP. - O nome do beneficiário não corresponde ao
holder_nameda entrada ->COUNTERPARTY_MISMATCHED_DATA. - Entrada verificada e o nome corresponde ->
COMPLETEDe, logo em seguida,FINISHED(o depósito já foi liquidado).
txn_id da nova transação é tr-in-, seguido dos primeiros 80 caracteres do txid e de um hash de 12 caracteres do txid e da carteira.
created é true (HTTP 201) quando esta chamada registrou o depósito, e false (HTTP 200) quando o mesmo txid e o mesmo wallet_address já estavam registrados; nesse caso, a transferência existente é retornada sem alterações.
No caminho da entrada verificada, as duas transições acontecem antes de o endpoint responder, então a resposta síncrona já mostra o status final FINISHED. A etapa intermediária COMPLETED continua registrada no timeline da transferência.
Cada transição dispara um webhook travel_rule.status.updated (COMPLETED e FINISHED disparam um cada).
Quando Didit cria uma nova transação, envia primeiro transaction.created e, depois dele, esses eventos.
O registro não gera tarifa de Travel Rule nem de monitoramento.
Quando o monitoramento de cripto está ativado e a chain é uma que Didit consegue analisar, um depósito recém-criado também passa por triagem e é cobrado uma única vez pela tarifa de Wallet Verification & Screening.
Widget de propriedade da carteira
Para tirar uma transferência deUNCONFIRMED_OWNERSHIP, ou para pré-verificar uma carteira antes da chegada de qualquer transferência, gere um widget hospedado de propriedade da carteira com POST /v3/travel-rule/widget-session/ e envie o seu cliente para a url retornada. O widget comprova o controle da carteira por assinatura de mensagem (incluindo contas de smart contract EVM, por meio de ERC-1271 e ERC-6492), teste de Satoshi, captura de tela ou autodeclaração e, em seguida, marca como verificada a entrada correspondente do catálogo de endereços para que a troca possa continuar.
A captura de tela é a exceção: ela nunca verifica a carteira sozinha. Por isso, a sua equipe de conformidade a analisa e confirma uma transferência em UNCONFIRMED_OWNERSHIP com POST .../travel-rule/ownership/.
Consulte Widget de propriedade da carteira para ver o fluxo completo, os métodos de comprovação e o aviso importante de que o widget deve ser aberto em um navegador real, nunca dentro de uma webview de SDK móvel.
Diretório
GET /v3/travel-rule/vasps/ pesquisa o diretório de VASPs: as entradas do diretório compartilhado e os membros da rede Didit. Cada linha informa como sua aplicação pode alcançar esse VASP hoje.
search corresponde a um trecho de nome ou alias, a um LEI exato ou a um domínio (counterparty.example ou uma URL nele). Restrinja os resultados com:
risk e responsiveness retornam apenas entradas do diretório. Os resultados são ordenados por nome e paginados com limit (padrão 50) e offset. Uma rede, um código de país, uma faixa de risco ou um status de responsividade desconhecido retorna 400 indicando o campo. GET /v3/travel-rule/vasps/{vasp_id}/ retorna uma linha pelo seu id. Seu próprio perfil de VASP nunca aparece nos seus próprios resultados.
dd_status, dd_score, dd_score_breakdown, dd_assessed_at, dd_score_semantic, risk_level, responsiveness e essential_checks trazem a avaliação de due diligence compartilhada de uma entrada do diretório. decision, entity_screening e questionnaires são os registros próprios da sua aplicação sobre o VASP, e nenhum outro cliente os vê. Consulte Due diligence de contrapartes para saber o que cada um significa, e condicione o fluxo a eles com os campos de regra de contraparte em vez de criar ramificações no código com base neles. Os membros da rede Didit não recebem pontuação: dd_status é COMPLETED, dd_score é null, risk_level fica vazio e o detalhamento fica vazio.
Rotas
routes lista as formas de entrega ao VASP disponíveis para sua aplicação, na ordem em que a sequência de roteamento as tenta, e reachable é true quando pelo menos uma está available:
TRPquando a entrada traz um endpoint TRP verificado pelo diretório.GTR,TRUST,VERIFYVASP,SYGNAquando uma rede lista o VASP sob um código. A rota ficaavailablesomente quando sua aplicação pode enviar por essa rede hoje (via: own_membershippara a sua própria associação conectada,via: didit_membershippara a da Didit). Caso contrário, ficaunavailablecomreason: no_membershipoureason: network_switched_off, e nunca é exibida como uma forma de alcançar o VASP. As associações da própria Didit às redes ainda não estão ativas, portanto hoje uma rota de rede só fica disponível por meio de uma associação que você conectou no Marketplace.EMAILquando existe um contato de conformidade para a entrada.INTERNALpara um membro da rede Didit.
TRISA aparece em networks e informa a identidade do VASP na TRISA, mas a Didit não tem um canal TRISA, portanto ela nunca é uma rota.
Uma aplicação de sandbox envia apenas para o Didit Test VASP, portanto nenhuma rota do diretório fica disponível para ela: todas as rotas ficam unavailable com reason: sandbox_application, todas as linhas têm reachable: false e reachable=true não retorna nenhuma linha.
Marcas e suas entidades
Uma marca que opera por meio de várias entidades reguladas é uma única linha cujasentities são as entidades jurídicas que recebem suas transferências; uma linha de entidade aponta de volta para sua marca em umbrella. Uma transferência que indica a marca vai para uma de suas entidades, escolhida entre todas elas: a que está na jurisdição informada em beneficiary_data.counterparty_vasp_jurisdiction; senão, a entidade que a atribuição por análise de blockchain vinculou à carteira de destino; senão, a única entidade da marca quando nenhuma jurisdição é informada. Só então essa entidade precisa estar acessível; se não estiver, a transferência nunca é enviada a outra entidade nem à marca em seu lugar. Quando nenhuma entidade se encaixa (duas se encaixam igualmente, ou foi informada uma jurisdição em que nenhuma delas está), é usada a rota da própria marca e, sem ela, a transferência fica COUNTERPARTY_VASP_NOT_FOUND. Qual entidade jurídica recebe os dados do remetente nunca é um palpite, e nunca é decidida pela entidade que por acaso tenha um contato.
Várias entradas com o mesmo nome, como empresas de um grupo que compartilham um nome comercial, são diferenciadas pela mesma regra: a que está na jurisdição informada; senão, a que a atribuição por análise de blockchain vinculou. Quando nenhum dos dois critérios escolhe uma, nenhuma é usada, e os dados são tratados como se não indicassem nenhuma entrada do diretório.
Contatos
contacts são os endereços de e-mail para os quais o canal EMAIL envia mensagens. Os contatos scope: platform atendem a todos os clientes da Didit: a Didit os seleciona (source: staff), ou um endereço em um dos domínios do próprio VASP respondeu a uma requisição pelo seu link de resposta (source: learned). Os contatos scope: application são privados da sua aplicação: os que você adiciona (source: application) e um endereço fora dos domínios do próprio VASP que respondeu a uma de suas requisições (source: learned). Uma transferência envia e-mail primeiro ao contato da sua própria aplicação, depois a um contato da plataforma que já respondeu antes (verified_at preenchido) e, em seguida, aos demais.
Gerencie os contatos da sua própria aplicação com a API de contatos de contrapartes:
GET /v3/travel-rule/counterparty-contacts/lista todos os contatos para os quais sua aplicação pode enviar, incluindo contatos da plataforma e os que retornaram com falha de entrega, do mais recente para o mais antigo, paginados comlimiteoffset. Filtre com?counterparty=e oidde uma entrada do diretório; um valor que não seja um UUID retorna400.POSTadiciona um contato privado (counterparty,email,nameopcional) e retorna201. Adicionar um endereço que a entrada já tem entre os seus próprios contatos retorna esse contato. Uma entrada desconhecida retorna400("No directory entry with this id.").DELETE /v3/travel-rule/counterparty-contacts/{contact_uuid}/exclui um dos seus próprios contatos (204). Os contatos da plataforma não podem ser excluídos e retornam404.
is_invalid: true, com invalid_reason (hard_bounce, soft_bounce, spam_complaint ou suppressed), invalid_detail e invalid_at, e o canal EMAIL o ignora. created_by fica vazio nos contatos da plataforma e nos contatos adicionados por uma chave de API.
Como as entradas chegam ao diretório
- O registro provisório MiCA da ESMA de prestadores de serviços de criptoativos, lido toda semana: o nome, o LEI e o estado-membro de origem de cada prestador.
- O diretório público da TRISA, lido toda semana: quem é cada membro, seu país e sua listagem na TRISA. Uma listagem que o diretório deixa de exibir por três semanas é removida.
- O registro global de LEI informa o LEI, outros nomes jurídicos e o país de uma entrada, e encontra o LEI de uma entrada pelo seu nome jurídico exato no seu país.
- A atribuição por análise de blockchain adiciona ou associa o VASP dono de uma carteira de destino e mantém o nome atribuído como alias.
- A equipe da Didit faz a curadoria das entradas: identificadores de roteamento e listagens de rede que verificou, contatos de conformidade, aliases, marcas e suas entidades, duplicatas mescladas e entradas ocultas.
originating_vasp de entrada ou um Travel Address, ficam na transferência desse cliente e nunca alteram uma entrada compartilhada. As entradas são associadas primeiro pelo LEI, depois pelo nome exato ou alias, e são enriquecidas em vez de duplicadas.
A rede Didit
Seu perfil de VASP é membro da rede Didit, de modo que outros clientes da Didit o encontram no diretório e no seletor de VASP do usuário final, somente enquanto todas estas condições forem atendidas:- sua aplicação está em produção (não em sandbox) e a Travel Rule está ativada;
is_discoverableétrueelegal_nameestá definido;compliance_emailestá definido e confirmado: envie a solicitação de confirmação comPOST /v3/travel-rule/settings/compliance-email/confirmation/e abra o link recebido por e-mail. Alterar o endereço exige uma nova confirmação;- a Didit não marcou a aplicação como de teste, demonstração ou interna.
INTERNAL faz a entrega para uma carteira cuja titularidade você comprovou, conforme descrito em Envio de uma transferência: ele exige sua aplicação em produção, a Travel Rule ativada e is_discoverable, e não o restante da lista.
GET /v3/travel-rule/settings/ retorna didit_network: listed, compliance_email_confirmed e, em missing, cada condição ainda não atendida (travel_rule_off, sandbox_application, not_discoverable, legal_name_missing, compliance_email_missing, compliance_email_unconfirmed, excluded_by_staff, internal_organization).
Identificadores de roteamento
O roteamento de saída consulta uma entrada do diretório sempre que sua transferência identifica a contraparte porcounterparty_vasp_lei ou counterparty_vasp_name (um alias também funciona). Uma entrada contém um identificador para cada rede pela qual pode ser alcançada, um endpoint TRP verificado e seus contatos de conformidade, e routes mostra quais deles sua aplicação pode usar. Você sempre pode ignorar o diretório em uma única transferência informando os campos explícitos em Campos de resolução da contraparte.
Due diligence de contrapartes
Antes que os fundos dos seus clientes cheguem a outro VASP, você precisa saber quem é esse VASP e se você o aceita. A due diligence de uma contraparte tem duas camadas:- A avaliação compartilhada. Cada entrada do diretório traz uma pontuação de due diligence, seu nível de risco, um status de capacidade de resposta e um relatório de verificações essenciais. A Didit os calcula a partir dos próprios dados da plataforma, então todos os clientes veem os mesmos valores.
- Seus próprios registros. Sua decisão sobre o VASP, sua triagem de sanções e mídia adversa dele e os questionários de due diligence que você trocou com ele pertencem apenas à sua aplicação. Nenhum outro cliente os vê, e eles nunca alteram a entrada compartilhada.
id que o diretório mostra.
Pontuação e nível de risco
dd_score vai de 0 a 100 e quanto maior, mais seguro. Todo resultado indica isso em dd_score_semantic, que é sempre higher_is_safer. risk_level é a faixa em que a pontuação se encaixa:
dd_score_breakdown mostra cada um como {points, max, reason, detail}: max é o peso do componente, reason é um código legível por máquina que você pode traduzir, e detail é uma explicação de uma linha em inglês.
history lê as mesmas requisições que a capacidade de resposta, sem janela de tempo: uma troca COMPLETED ou FINISHED é um sucesso, e uma troca EXPIRED, COUNTERPARTY_MISMATCHED_DATA ou COUNTERPARTY_VASP_GENERAL_DECLINE é uma falha. Um cancelamento é um ato do próprio remetente e nunca conta.
A Didit recalcula a avaliação quando uma troca com a entrada é concluída, finalizada, expira, apresenta divergência ou é recusada, quando ela atualiza ou faz a curadoria da entrada, e para todas as entradas na atualização semanal do diretório. dd_assessed_at indica quando ela foi executada pela última vez; uma entrada ainda não avaliada não tem dd_assessed_at, tem dd_score igual a 0 e risk_level vazio, então leia risk_level em vez da pontuação bruta. Os membros da rede Didit não são pontuados: o dd_score deles é null, o risk_level é vazio e o dd_score_breakdown é vazio.
Verificações essenciais
essential_checks é um relatório curto sobre quatro verificações que a Didit executa em todas as entradas do diretório, apenas a partir das fontes verificadas da plataforma, nunca a partir de dados informados por um cliente:
checks informa seu status (pass, fail ou unknown quando nenhuma fonte registrada consegue decidi-la), um reason legível por máquina e um detail de uma linha em inglês. passed, failed, unknown e total fazem a contagem delas, level é essential, e checked_at indica quando o relatório foi gerado. O componente essentials pontua a proporção das verificações decididas que passam, então uma verificação unknown não conta nem a favor nem contra a entrada. O relatório fica vazio até que a atualização semanal do diretório verifique uma entrada pela primeira vez, e é sempre vazio para um membro da rede Didit.
Capacidade de resposta
responsiveness indica se o VASP responde às requisições de Travel Rule:
total conta as requisições que os clientes da Didit iniciaram em direção ao VASP nos últimos 90 dias cujo resultado está decidido, e answered conta as que ele respondeu:
- Contadas: requisições enviadas por um canal de rede ou de protocolo, e requisições enviadas por e-mail para um endereço compartilhado, que é o endereço de conformidade da entrada ou um contato da plataforma.
- Nunca contadas: uma requisição enviada por e-mail para um endereço digitado por um cliente ou para um contato privado de um cliente. Essa troca permanece no histórico de transferências do próprio cliente e nunca rotula o VASP para os demais.
- Respondidas:
COMPLETED,FINISHED,COUNTERPARTY_VASP_GENERAL_DECLINEouCOUNTERPARTY_MISMATCHED_DATA. Uma recusa ou uma divergência é uma resposta: o VASP interagiu. - Não respondidas:
EXPIRED. - Nenhuma das duas: todos os outros status. Uma requisição
CANCELLEDé um ato do próprio remetente,COUNTERPARTY_VASP_NOT_REACHABLEpode ser uma falha do lado do remetente, e uma requisição ainda em andamento ainda não está decidida.
UNKNOWN com contagens zeradas. Aja sobre uma contraparte que não responde com a política de não resposta ou com o preset travel-rule-counterparty-unresponsive.
Sua decisão sobre uma contraparte
Registre o parecer da sua equipe de conformidade sobre uma contraparte comPUT /v3/travel-rule/vasps/{vasp_id}/decision/:
- A decisão é privada da sua aplicação: nenhum outro cliente a vê, e ela nunca altera a entrada compartilhada.
- Uma decisão não altera nada por si só e nunca muda a forma como uma transferência é roteada. Ela chega às suas transações por meio do campo de regra
counterparty_dd_status: instale os presets ou escreva sua própria regra sobre ele. - Uma decisão sobre uma marca abrange cada uma das suas entidades que não tenha decisão própria, e a entidade mostra a marca em
inherited_from. Uma decisão sobre a entidade substitui a da marca para essa entidade. GETretorna a decisão que se aplica, ou{"decision": null}.DELETEremove a sua própria decisão e retorna o que passa a se aplicar: a decisão da marca, no caso de uma entidade, ou entãonull. Ele responde404quando sua aplicação não tem decisão própria sobre a contraparte.reasoné opcional, tem até 255 caracteres, e cadaPUTo substitui.decided_byé o usuário do console que tomou ou alterou por último a decisão, e fica vazio quando foi uma chave de API.
Triagem da contraparte
A triagem da contraparte verifica o próprio VASP da contraparte, como empresa, contra sanções e mídia adversa. Ela é opcional e cobrada: ative-a comcounterparty_screening_enabled nas suas configurações. Enquanto estiver desativada, nada é verificado nem cobrado.
- Faturamento. Cada nova triagem custa o preço de Análise AML de empresas da sua organização.
GET /v3/travel-rule/vasps/{vasp_id}/screening/retorna esseprice,fresh_dayse se a triagem estáenabled, sem custo. Uma triagem com menos de 30 dias é recente:POSTa retorna novamente com200eoutcome: reusede não cobra nada, a menos que você envierefresh: true. Uma nova triagem responde201comoutcome: screened. Aplicações de sandbox nunca são verificadas nem cobradas. - Triagem automática. Com a triagem ativada, a Didit também verifica a contraparte alcançada por uma troca de saída quando a troca começa, antes de suas regras avaliarem a transação, com a mesma reutilização e o mesmo faturamento. Uma recusa ou falha nesse ponto nunca faz a transferência falhar.
- Resultado.
statuséApprovedquando nenhuma possível correspondência exige atenção, eIn ReviewouDeclinedpara uma possível correspondência em sanções ou mídia adversa.flaggedétrueenquanto uma triagem recente estiverIn ReviewouDeclined. - Efeito. Enquanto sua triagem mais recente de uma contraparte estiver sinalizada e a triagem permanecer ativada,
counterparty_risk_leveléHIGHnas suas regras, de modo que o presettravel-rule-counterparty-high-risk, uma vez instalado, retém as transferências dela. Orisk_levelcompartilhado no diretório não muda. - Privacidade. A triagem é privada da sua aplicação: nenhum outro cliente a vê, e ela nunca altera a entrada compartilhada. O diretório mostra a mais recente como
entity_screening. - Recusas.
409quando a triagem está desativada, para uma aplicação de sandbox ou enquanto uma triagem da mesma contraparte já estiver em andamento.403comcode: insufficient_creditsquando seu saldo não cobre o preço.502quando a triagem não pôde ser concluída. Nenhuma delas gera cobrança.
Questionário de due diligence
Solicite a uma contraparte suas respostas de due diligence com o questionário padrão da Didit.POST /v3/travel-rule/vasps/{vasp_id}/questionnaires/ o envia por e-mail para um endereço de conformidade registrado da contraparte, com um link de uso único para uma página de respostas:
- Para onde vai.
sent_todeve ser um endereço de conformidade registrado: para uma entrada do diretório, seu endereço de conformidade ou um contato que sua aplicação vê emcontacts; para um membro da rede Didit, seu e-mail de conformidade confirmado. Omita-o para usar o endereço para o qual vai um e-mail de Travel Rule à contraparte: primeiro o seu próprio contato, depois um contato da plataforma e, por fim, o endereço de conformidade da entrada. A Didit nunca envia o questionário para nenhum outro lugar e responde400quando a contraparte não tem endereço de conformidade registrado. - Respostas. O link abre
/v3/travel-rule/questionnaires/{token}/, uma página para uma pessoa da contraparte que não exige conta nem chave de API. Ela responde a todas as perguntas, com até 2.000 caracteres cada (N/Aquando uma não se aplica), e envia uma única vez. Uma contraparte também pode enviar{"answers": {"<question id>": "<answer>"}}para o mesmo link. Um link que já foi usado, foi substituído ou passou do prazo mostra uma página de expiração. O e-mail e a página são traduzidos; as perguntas em si estão sempre em inglês, para que seu significado nunca mude entre idiomas. - Prazos. A contraparte tem 30 dias para responder (
expires_at). As respostas permanecem válidas por 365 dias (valid_until), ecurrentétrueaté lá. Um questionário sem resposta após o prazo, e respostas após sua validade, passam aEXPIRED. - Um questionário aberto por contraparte. Um novo envio substitui seu questionário anterior sem resposta para a mesma contraparte: ele passa a
EXPIREDe seu link deixa de funcionar. Um e-mail por minuto pode ser enviado a um endereço; um envio mais rápido responde429. - Leitura das respostas.
GET /v3/travel-rule/vasps/{vasp_id}/questionnaires/lista seus questionários com a contraparte, do mais recente para o mais antigo, comanswersindexado pelo id da pergunta depois de respondido. O diretório os mostra comoquestionnaires. Eles são privados da sua aplicação.
1 do formulário faz estas doze perguntas:
Transferências com uma contraparte
GET /v3/travel-rule/transfers/?counterparty={vasp_id} lista as transferências da Travel Rule da sua aplicação com uma contraparte, das mais recentes para as mais antigas, pelo id exibido no diretório: as suas transferências cuja contraparte é essa entrada do diretório ou as suas trocas INTERNAL com esse membro da rede Didit. Um valor que não seja um ID válido retorna 400.
Cada linha traz reason logo depois de status: o próprio reason da transferência, para que a lista diferencie um e-mail de conformidade devolvido de uma contraparte sem rota sem que seja preciso abrir cada transferência.
Políticas de sunrise e de não resposta
Quando uma transferência expira (confirmation_timeout_hours se esgotou enquanto ela estava em AWAITING_COUNTERPARTY), timeout_outcome decide o que acontece com a transação correspondente. Duas configurações permitem tratar de forma diferente dois motivos comuns de expiração:
HOLD, REJECT ou PROCEED, com o mesmo significado que têm em timeout_outcome, ou uma string vazia para seguir timeout_outcome. Ambas ficam vazias por padrão, então nada muda até que você defina uma delas:
sunrise_policy, quando está definida e a jurisdição da contraparte está emsunrise_jurisdictions.non_responsive_policy, quando está definida e a contraparte estáUNRESPONSIVE.timeout_outcomeem todos os outros casos, inclusive em uma transferência para um membro da rede Didit ou para uma contraparte sem entrada no diretório.
sunrise_jurisdictions é somente leitura e atualmente vale ["CO", "KH", "VN"]. Apenas esses países são considerados em período de sunrise: qualquer outra jurisdição, assim como uma vazia ou desconhecida, segue timeout_outcome, de modo que uma contraparte nunca recebe a sua política de sunrise por acidente. A linha do tempo da transferência expirada informa o resultado aplicado, por exemplo sunrise_policy=PROCEED (counterparty jurisdiction CO does not enforce the Travel Rule yet). Suas regras continuam sendo executadas após a expiração, portanto uma regra como a tr_eu_expired_review do EU TFR ainda pode mover a transação para revisão com PROCEED.
Campos e presets de regras
Quatro campos de regra contêm o que a sua aplicação sabe sobre a contraparte alcançada pela troca da Travel Rule de uma transação: a entrada dela no diretório ou, em uma trocaINTERNAL, o cliente Didit que a recebeu. Cada campo fica vazio quando a troca não alcançou nenhuma contraparte conhecida.
travel_rule atuam sobre esses campos. Instale-os em Transactions → Rules → Library no Business Console ou com a API da biblioteca de regras:
Webhooks
Inscreva um destino no eventotravel_rule.status.updated para ser notificado a cada transição de status de cada transferência da sua aplicação, de saída e de entrada, incluindo os trechos pela rede INTERNAL.
O roteamento é executado após a resposta à criação da transação, então resultados como COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou uma troca INTERNAL que é liquidada imediatamente chegam até você por esse evento, e não na resposta de criação.
rail fica vazio até que um trilho seja selecionado.
Para uma mesma transação, a Didit envia travel_rule.status.updated depois de transaction.created: quando a Didit cria a transação (seu POST /v3/transactions/, um registro de sunrise, uma consulta TRP de entrada ou a perna de entrada do trilho INTERNAL), ela envia transaction.created primeiro.
Cada evento é entregue e reenviado de forma independente, então um transaction.created que precisou ser reenviado ainda pode chegar depois de um evento de status: indexe seu handler por transaction_id e consulte a transação quando um evento de status mencionar uma que você ainda não viu.
Uma transferência enviada por TRUST não recebe evento COMPLETED: o TRUST não devolve nada que a Didit consiga ler, então, a menos que o envio falhe ou você o cancele, seu último evento é EXPIRED. Em GTR, VERIFYVASP e SYGNA, o evento segue a resposta que a Didit lê da rede.
Aplicações de sandbox também enviam esse evento, com "environment": "sandbox"; uma transferência respondida pelo Didit Test VASP inclui rail: "TEST_VASP", test_vasp: true e test_vasp_scenario.
Consulte o guia de webhooks para ver o catálogo completo de eventos, a verificação de assinatura e a política de novas tentativas.
Preços
A tarifa da Travel Rule é de $0.02 por troca de saída iniciada, cobrada uma única vez quando a transação é criada, independentemente de quantas transições de status a troca tenha depois. Umresend nunca gera nova cobrança.
- Ela se aplica a uma transação
travelRulede saída em uma aplicação com a Travel Rule ativada, cujo valor seja igual ou superior ao seuthreshold_amount, de modo que a Didit inicia uma troca gerenciada para ela. Uma transferência para uma carteira autocustodiada, ou para a própria carteira verificada do seu usuário, também conta: a prova de propriedade é a sua troca. - Toda outra transação de saída que carrega dados da Travel Rule é faturada como Triagem de transações padrão, que o seu plano inclui até a sua franquia mensal de transações e cobra a $0.001 além dela: uma transferência abaixo do seu limiar, um pagamento Lightning ao qual a Travel Rule não se aplica e uma transferência registrada passivamente enquanto a Travel Rule está desativada. Uma transação é faturada em uma das duas linhas, nunca nas duas.
- Transações
travelRulede entrada não têm tarifa de Travel Rule nem de monitoramento: a transação de entrada que a Didit cria na aplicação do beneficiário pelo trilhoINTERNAL, as consultasTRPde entrada e os registros após o depósito. - Uma aplicação que aderiu à Travel Rule gratuitamente não paga nenhuma das duas tarifas em transações
travelRulede saída até ativar o faturamento de saída comPOST /v3/travel-rule/workspace/billing/; o recebimento continua gratuito. - Aplicações de sandbox nunca são cobradas.
- A tarifa da Travel Rule é de $0.02 e a Triagem de transações custa $0.001 além da sua franquia. Cada transação é cobrada pelo preço da linha em que é faturada.
- Se a triagem de AML cripto e de carteiras também for executada na mesma transação (por exemplo, um depósito de entrada com
currency_kind: "crypto"e monitoramento ativado), ela é faturada separadamente pela tarifa padrão de Verificação e triagem de carteiras; não está incluída na tarifa da Travel Rule. - A triagem de contrapartes é opcional e faturada separadamente, pelo preço da Análise AML de empresas por triagem; uma triagem com menos de 30 dias é reutilizada sem custo. Decisões, questionários e a avaliação de due diligence do diretório não custam nada.
Preços da atribuição
A atribuição por análise de blockchain exige uma consulta de carteira junto ao provedor de análise, e você sempre recebe o valor completo dessa consulta:- O monitoramento cripto já fez a triagem da carteira nesta transação: o resultado armazenado é reutilizado. Uma chamada de análise, uma cobrança de Verificação e triagem de carteiras (a já efetuada pelo monitoramento cripto). A atribuição não acrescenta nada.
- O monitoramento cripto não foi executado: a Didit faz a chamada de análise necessária uma única vez e repassa todo o seu valor: a transação é cobrada pela tarifa padrão de Verificação e triagem de carteiras ($0.15 com análise gerenciada pela Didit) e recebe em troca o resultado completo da triagem cripto (pontuação de risco, categoria de risco da carteira, snapshot da rede), e não apenas o nome do VASP. O item de uso é marcado com o gatilho
travel_rule_attributionpara que a cobrança seja explicável. - Chave de análise própria: a mesma tarifa de plataforma que se aplica ao monitoramento cripto com a sua própria chave se aplica aqui ($0.02 por chamada). O seu provedor cobra a consulta subjacente diretamente de você.
- Consultas com falha nunca são cobradas, reenvios reutilizam a atribuição registrada sem nova chamada nem cobrança, e aplicações de sandbox nunca são cobradas.
Pacote de regras EU TFR
Quatro regras predefinidas vêm no pacotetravel_rule_eu_tfr, criadas especificamente para as obrigações do EU TFR.
Como qualquer outro pacote predefinido, ative-o no Business Console em Transactions → Rules → Library.
Por que isso funciona melhor em uma única plataforma
A conformidade com a Travel Rule é um problema de identidade disfarçado de problema de pagamentos, e a Didit já já tem os dados de identidade:- Dados verificados disponíveis. O titular de cada transferência está vinculado por
vendor_dataao perfil KYC que a Didit verificou no onboarding (OCR do documento, prova de vida, correspondência facial), então você pode montaroriginator_dataa partir de campos verificados na mesma plataforma. Para um usuário com uma verificação KYC aprovada, a Didit transmite a identidade verificada em vez dos valores que você digitou (veja Dados verificados e procedência). - Biometria adicional para transferências de risco. Uma regra pode reter qualquer transferência de alto valor até que o usuário passe por uma nova verificação biométrica em comparação com o rosto capturado no onboarding, a resposta mais forte possível ao sequestro de conta no momento do saque. Veja o exemplo prático.
- Um único grafo de dispositivos. As transferências enviadas pelo SDK trazem a mesma inteligência de dispositivo das sessões de KYC, então “novo dispositivo + valor alto + beneficiário pela primeira vez” é uma única regra, e não um join no data warehouse.
- Triagem, regras, casos e a troca em um só lugar. A triagem de carteiras que identifica a VASP da contraparte é a mesma triagem que suas regras e seus analistas veem: uma cobrança, um console, uma trilha de auditoria.
- Preços publicados. $0.02 por intercâmbio de saída, sem níveis de volume, sem necessidade de falar com vendas.
Perguntas frequentes
Como funciona a troca
A Didit executa a troca VASP a VASP por conta própria ou apenas registra os dados da Travel Rule depois que outra rede conclui o handshake?
A Didit executa a troca VASP a VASP por conta própria ou apenas registra os dados da Travel Rule depois que outra rede conclui o handshake?
travelRule, a Didit faz a descoberta da contraparte em tempo real, envia os dados do remetente e do beneficiário ao VASP de destino pelos trilhos que os transportam e só marca a transferência como COMPLETED quando o lado da contraparte a confirma. É um handshake gerenciado, não um registro feito após a liquidação.
A resposta da contraparte é processada em todos os trilhos, exceto TRUST, que apenas envia; por isso, uma transferência por ele expira em vez de ser concluída. Em GTR, VERIFYVASP e SYGNA, a Didit lê a resposta na resposta da rede ou consultando-a a cada 5 minutos, e nenhuma troca por esses trilhos foi concluída ainda contra uma rede em produção; em TRP, uma resposta que a contraparte não dá de imediato depende do host TRP público da Didit, que ainda não está no ar (consulte Redes da Travel Rule).
A Didit também mantém o registro completo e o status de conformidade de cada troca (um ciclo de vida com 13 estados, webhooks e uma trilha de auditoria).
Se você preferir conduzir a Travel Rule pelo seu próprio processo, a Didit pode, em vez disso, registrar os dados de forma passiva como seu sistema de registro único (consulte a pergunta sobre registro passivo abaixo).
Os dois modos estão disponíveis: a troca ativa é executada quando você define is_enabled: true nas configurações (o padrão é false) e, até lá, a Didit registra os dados de forma passiva.A troca é nativa da Didit ou depende de um provedor externo de interoperabilidade (Notabene, Sygna, VerifyVASP, TRP)?
A troca é nativa da Didit ou depende de um provedor externo de interoperabilidade (Notabene, Sygna, VerifyVASP, TRP)?
trp.didit.me assim que esse host público estiver no ar (ele ainda não responde, então hoje as contrapartes não conseguem alcançar você pelo TRP), e implementa diretamente os protocolos das redes do setor: GTR (Global Travel Rule), TRUST, VerifyVASP e Sygna Bridge (implementado de forma nativa, incluindo o IVMS 101 criptografado com ECIES e as requisições de permissão assinadas da Sygna). A Didit não revende uma única camada de interoperabilidade de terceiros. Alcançar uma contraparte que está em uma rede de filiação específica acontece necessariamente por essa rede, pois não existe um canal universal único na Travel Rule, mas a descoberta, o handshake, a verificação e a manutenção de registros são todos executados pela Didit.
Hoje, todos os trilhos de rede exigem sua própria filiação, e TRUST apenas envia: consulte a Visão geral.Quais redes e protocolos da Travel Rule a Didit suporta?
Quais redes e protocolos da Travel Rule a Didit suporta?
INTERNAL (os dois VASPs na Didit), TRP (OpenVASP Travel Rule Protocol), GTR, TRUST, VerifyVASP, Sygna Bridge e um fallback por EMAIL para contrapartes sem ferramentas.
Hoje, os trilhos de rede exigem sua própria filiação, TRUST apenas envia e o recebimento por uma rede ainda não está ativado: consulte Redes da Travel Rule.
CODE, TRISA, Notabene e Veriscope aparecem no Marketplace da Didit como blocos de solicitação de acesso, ainda sem integração.
Consulte Como a Didit roteia uma troca para ver a tabela de roteamento completa e Redes da Travel Rule para saber o que cada uma alcança hoje.Qual rede devo usar e preciso ter minhas próprias filiações?
Qual rede devo usar e preciso ter minhas próprias filiações?
TRP é a base que recomendamos: não exige filiação compartilhada, pois compartilhar seu Travel Address permite que qualquer VASP que fale TRP alcance você. Quando uma contraparte é conhecida apenas pelo endereço da carteira, a atribuição por análise de blockchain a roteia pelo TRP somente se a entrada atribuída no diretório já tiver um endpoint TRP.
No envio, a Didit transmite por ele os ativos listados em Identificadores de ativos TRP, e uma contraparte que não responde de imediato depende do host TRP público da Didit, que ainda não está no ar.
Para redes de filiação, escolha de acordo com onde suas contrapartes operam: a GTR oferece ampla cobertura global, a TRUST é voltada para VASPs dos EUA e a VerifyVASP (que agora também opera a Sygna Bridge) tem forte cobertura na Ásia.
Sim, hoje você precisa da sua própria filiação: a Didit ainda não tem filiação de plataforma nessas redes e está em processo de onboarding como provedor.
Conecte sua filiação em Marketplace; você não fica preso a uma única rede.
Lembre-se de que TRUST apenas envia, então uma transferência por ela não é concluída, e de que nenhuma troca por uma rede foi concluída ainda contra uma rede em produção.Como a Didit encontra o VASP da contraparte quando tenho apenas um endereço de carteira?
Como a Didit encontra o VASP da contraparte quando tenho apenas um endereço de carteira?
INTERNAL), seu próprio catálogo de endereços de carteiras com um Travel Address armazenado, depois os trilhos de protocolo e de rede e, por fim, a atribuição por análise de blockchain.
Se a transferência trouxer apenas uma carteira de destino, a Didit a resolve com dados de análise de blockchain para atribuir a exchange ou o serviço de custódia da contraparte e o cataloga no diretório de VASPs.
A transferência só é roteada automaticamente se essa entrada no diretório já tiver uma rota, como um endpoint TRP; caso contrário, ela termina em COUNTERPARTY_VASP_NOT_FOUND com o nome da contraparte registrado, e você pode reenviá-la quando houver uma rota, por exemplo depois de armazenar o travel_address da contraparte na entrada do seu catálogo de endereços para essa carteira (para os ativos listados em Identificadores de ativos TRP).Preços e licenciamento
Quanto custa a Travel Rule e ela está incluída no meu plano de KYC ou de verificação?
Quanto custa a Travel Rule e ela está incluída no meu plano de KYC ou de verificação?
Serei cobrado em dobro quando a Travel Rule e o monitoramento de cripto forem executados juntos?
Serei cobrado em dobro quando a Travel Rule e o monitoramento de cripto forem executados juntos?
travelRule é cobrada em uma única linha: a tarifa da Travel Rule ($0.02) quando ela inicia uma troca de envio e, caso contrário, o Transaction Screening padrão. A consulta de análise de blockchain é cobrada uma única vez: se o monitoramento de cripto já tiver analisado a carteira de destino na transação, a atribuição reutiliza esse resultado armazenado sem custo adicional.
As transferências de recebimento que a Didit cria no lado do beneficiário nunca são cobradas com a tarifa da Travel Rule.A Didit pode fornecer documentação ou uma declaração de capacidades para o meu processo de licenciamento de VASP ou para o regulador?
A Didit pode fornecer documentação ou uma declaração de capacidades para o meu processo de licenciamento de VASP ou para o regulador?
Operações e dados
O que acontece com transferências abaixo do meu limiar?
O que acontece com transferências abaixo do meu limiar?
NOT_APPLICABLE: nenhum rail é acionado e nenhum dado de identidade sai da Didit.
A transação é cobrada como triagem de transações padrão, e não pela tarifa da Travel Rule.
A Didit compara o limiar com o valor convertido para a moeda padrão da sua aplicação.
Se a Didit não conseguir converter o valor, o limiar não é aplicado e a transferência segue pelo processo de troca.
O TFR da UE não tem valor mínimo, então CASPs da UE devem manter threshold_amount em 0.00.E se a contraparte nunca responder?
E se a contraparte nunca responder?
AWAITING_COUNTERPARTY até que confirmation_timeout_hours se esgote. Em seguida, um processo de varredura a move para EXPIRED e aplica o seu timeout_outcome à transação subjacente: HOLD para revisão, REJECT para recusar ou PROCEED para deixá-la intacta. A regra predefinida tr_eu_expired_review também exibe toda expiração para os seus analistas. Uma contraparte que nunca chega a receber a mensagem é um caso diferente: a Didit tenta novamente o envio e, após a sexta tentativa malsucedida, a transferência passa para COUNTERPARTY_VASP_NOT_REACHABLE (veja Entrega e novas tentativas).Minha contraparte não tem nenhuma ferramenta de Travel Rule. Ainda consigo estar em conformidade?
Minha contraparte não tem nenhuma ferramenta de Travel Rule. Ainda consigo estar em conformidade?
EMAIL. O contato de conformidade da contraparte recebe um link de acesso de uso único e pode confirmar ou recusar a troca de dados em uma página hospedada, sem conta na Didit, sem chave de API e sem integração. Para depósitos que já foram liquidados antes que qualquer troca fosse possível, use o registro sunrise após o depósito.Como funcionam os saques para a carteira do próprio usuário?
Como funcionam os saques para a carteira do próprio usuário?
payment_method.method_type: "unhosted_wallet"). A Didit ignora o roteamento entre VASPs e, em vez disso, coleta a prova de que o seu cliente controla a carteira (assinatura de mensagem, teste Satoshi, captura de tela ou autodeclaração) por meio do widget de propriedade de carteira. Essa é a obrigação do TFR da UE para carteiras autocustodiadas em forma de API.Os dados pessoais da contraparte ficam protegidos durante a troca?
Os dados pessoais da contraparte ficam protegidos durante a troca?
GTR, TRUST, VERIFYVASP, SYGNA) também criptografam o payload IVMS com a chave pública do VASP receptor.Já acompanho a conformidade com a Travel Rule com meu próprio processo. Posso apenas registrá-la?
Já acompanho a conformidade com a Travel Rule com meu próprio processo. Posso apenas registrá-la?
travel_rule_details que você enviar (incluindo um status informado por você, atual ou legado) são registrados passivamente na transação: nenhum rail é acionado e nada é negociado. Use isso para preencher dados retroativamente ou executar seu próprio processo, mantendo um único sistema de registro.Como testo isso antes de entrar em produção?
Como testo isso antes de entrar em produção?
transaction.created e transaction.status.updated, e toda troca de saída vai para o Didit Test VASP no rail TEST_VASP, que responde dentro da Didit com o cenário que você escolher: aceitar, recusar, divergência de nome, inalcançável, tempo esgotado ou carteira autocustodiada. Você recebe webhooks travel_rule.status.updated marcados com environment: sandbox, e nenhuma mensagem chega a uma contraparte real.
Para entrada, peça ao VASP de teste que envie uma transferência para você com Trigger Test VASP Inbound Transfer, ou registre uma com POST /v3/travel-rule/inbound/; ambas têm a decisão determinada com base no seu catálogo de endereços de carteira: ON_HOLD, UNCONFIRMED_OWNERSHIP, COUNTERPARTY_MISMATCHED_DATA ou COMPLETED e depois FINISHED.
Para uma troca entre duas partes com outra aplicação real, use duas das suas próprias aplicações em produção no rail INTERNAL: a receptora deve ser localizável e provar o controle da carteira de destino com uma mensagem assinada ou um depósito de teste.