Saltar para o conteúdo principal
A Didit executa a troca entre ordenante e beneficiário prevista pelo FATF/EU Transfer of Funds Regulation (TFR) para transferências de ativos virtuais: procura um canal que alcance a VASP contraparte, negocia os dados necessários através do mesmo, acompanha a troca ao longo de um ciclo de vida de 13 estados e informa-o quando a troca tiver sido concluída para que possa libertar fundos on-chain.

Visão geral

A Travel Rule do GAFI (Recomendação 16), implementada na UE como o Regulamento relativo às Transferências de Fundos (TFR), exige que um Prestador de Serviços de Ativos Virtuais remetente (o VASP ordenante) recolha e transmita informações do ordenante e do beneficiário ao VASP destinatário (o VASP beneficiário) antes da liquidação de uma transferência de ativos virtuais. Ao contrário da maioria das jurisdições, o TFR da UE aplica-se sem montante mínimo - todas as transferências de criptoativos estão abrangidas, e não apenas as transferências acima de um limiar de comunicação. O produto Travel Rule da Didit é uma troca gerida, não apenas um campo de dados:
  • Submete uma transferência com transaction_category: "travelRule".
  • A Didit tenta as vias por ordem de prioridade para contactar o VASP da contraparte, executa a troca através da primeira que a alcance e, caso o outro lado devolva um nome de beneficiário, compara-o com o que enviou.
  • Só quando a troca atinge o estado COMPLETED é que deve difundir a transferência on-chain.
  • Em seguida, comunica o hash da transação on-chain à Didit para fechar a troca como FINISHED.
Sete vias são disponibilizadas nesta versão, tentadas por estrita ordem de prioridade - a primeira que conseguir contactar a contraparte é a utilizada: As vias de rede (GTR, TRUST, VERIFYVASP, SYGNA) requerem uma adesão à rede do lado emissor e, atualmente, essa adesão tem de ser a sua própria. Associe as credenciais da sua adesão no Marketplace da consola (categoria Redes da Travel Rule), e as suas transferências serão processadas sob a sua própria identidade de rede. A Didit não detém atualmente qualquer adesão de plataforma para nenhuma das quatro redes e está a fazer onboarding como fornecedor nessas redes. Até que esse onboarding esteja concluído, platform_available é false para as quatro, o modo didit das definições (encaminhamento através da adesão de plataforma da Didit) não está disponível para nenhuma rede, e disabled_networks não tem nada para desativar. Uma adesão que o próprio utilizador ligue tem sempre precedência sobre uma adesão de plataforma. Nenhuma adesão a redes está incluída por defeito, incluindo a GTR. Ativar a Travel Rule não ativa a GTR, a TRUST, a VerifyVASP nem a Sygna. Consulte Obter definições da Travel Rule para ver os modos de networks em vigor da sua aplicação e Redes da Travel Rule para saber o que cada rede alcança atualmente. Se as quatro indicarem unavailable, nenhuma conseguirá encaminhar uma troca: associe a sua própria adesão no Marketplace ou utilize uma contraparte contactável por INTERNAL, TRP ou EMAIL. Ao guardar uma adesão, o código de participante tem de ser o seu: guardar a adesão resulta numa resposta 400 se o código for o código da própria Didit nessa rede, ou um código que a adesão de outra aplicação já detenha. Uma adesão à GTR necessita da sua chave privada ed25519 (base64), cuja chave pública está registada no portal da GTR: esta encripta os dados pessoais que envia e desencripta os dados que recebe. Uma adesão à VerifyVASP aponta para o seu próprio VerifyVASP Enclave: o URL é o do seu Enclave e o token é aquele que o seu Enclave apresenta à Didit. Mesmo com a sua própria adesão, uma via de rede só encaminha uma transferência se os respetivos beneficiary_data contiverem o ID da contraparte nessa rede (counterparty_gtr_vasp_code, counterparty_trust_membership_id, counterparty_verifyvasp_id ou counterparty_sygna_vasp_code), ou se a entrada da contraparte no diretório a listar nessa rede (consulte Rotas). O campo platform_available indica se a adesão da plataforma está configurada, não sendo uma verificação em tempo real do estado da rede. Da mesma forma, connected significa que as credenciais da sua adesão foram guardadas e passaram na validação local; a primeira troca em tempo real verifica-as junto da rede. Um modo didit ou own não garante que a contraparte seja contactável nem assegura uma entrega bem-sucedida. Com a sua própria adesão, a Didit lê a resposta da contraparte através de 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. O TRUST apenas envia: uma transferência enviada através deste permanece em AWAITING_COUNTERPARTY até decorrer confirmation_timeout_hours, passando depois para EXPIRED e aplicando-se o seu timeout_outcome. A receção de uma transferência que outro VASP lhe envie através de uma rede ainda não está ativa e nenhuma troca através de uma rede foi ainda concluída numa rede de produção: consulte Redes da Travel Rule. Outras redes - CODE (a aliança coreana), TRISA, Notabene e Veriscope - estão listadas no Marketplace da consola como blocos para solicitar acesso. A Didit ainda não tem integração com as mesmas, pelo que nenhuma transferência pode ser encaminhada através delas atualmente. Quando nenhuma das sete vias consegue resolver uma contraparte, a Didit executa mais um passo de resolução antes de desistir: atribuição por análise de blockchain. A carteira de destino é pesquisada em dados de análise de blockchain; quando a carteira pertence a uma exchange ou custodiante conhecido, a Didit regista o VASP atribuído na transferência, adiciona-o ao diretório e volta a executar as vias uma vez com o novo nome. Consulte Atribuição por análise de blockchain para obter informações sobre o comportamento completo e os preços. Uma transferência cujo destino seja declarado como uma carteira autocustodiada ignora todas as sete vias - não existe um VASP de contraparte com o qual trocar informações - e avança diretamente para a prova de propriedade da carteira pelo utilizador final.
A Didit também opera a vertente da troca direcionada para a contraparte: endpoints públicos de identidade e consulta TRP que outros VASP chamam para entrar em contacto consigo, endpoints de callback e o fluxo de recolha por e-mail. Nunca os chama diretamente - são infraestrutura gerida -, mas a página Interoperabilidade da Travel Rule documenta cada um deles para que os VASP de contraparte se possam ligar a si. Interage com a Travel Rule apenas através dos endpoints /v3/ descritos nesta página.

O que é executado ao submeter uma transferência

As verificações são executadas dentro da única chamada POST /v3/transactions/ - no momento em que recebe a resposta, a triagem já foi executada, a transferência está armazenada e as regras foram avaliadas. A troca em si tem início após a resposta: a Didit escolhe o rail e contacta a contraparte fora do seu pedido, para que nenhuma rede ou contraparte possa tornar a criação mais lenta ou fazê-la falhar. Cada alteração de estado posterior chega como um webhook travel_rule.status.updated que indica o rail, e o objeto de transferência devolvido pelos endpoints de transferência da Travel Rule contém um campo delivery que mostra se a mensagem foi entregue com sucesso. Não existe nenhum pipeline para consultar ciclicamente (polling); as partes assíncronas são a troca, a resposta da contraparte e qualquer ação do utilizador final. Passo a passo:
  1. Validação e vinculação do sujeito. O payload é validado. Um transaction_id já utilizado na sua aplicação é rejeitado com 400, e quando dois pedidos concorrem com o mesmo ID, um deles recebe 409. O subject é associado ao perfil de utilizador ou empresa através de vendor_data, para que a transferência apareça nesse perfil para monitorização. Um vendor_data do sujeito ou da contraparte presente na lista de bloqueio é rejeitado com 400, e nenhuma transação é criada. Carteiras, contas bancárias, IPs e dispositivos na lista de bloqueio são verificados no passo 6 e fazem com que a transação seja recusada nesse passo, após a execução do encaminhamento.
  2. Enriquecimento de dispositivo e rede. Os IPs das partes são geo-enriquecidos e qualquer contexto de dispositivo (automático no envio via SDK) é normalizado no grafo de dispositivos - o mesmo grafo alimentado pelas sessões de KYC, para que a associação “relacionado por dispositivo” funcione transversalmente no onboarding e nas transações.
  3. Triagem cripto. Para transferências cripto com monitorização ativada, a carteira relevante (ou o hash on-chain) é submetida a triagem em ferramentas de análise de blockchain antes de qualquer troca - exposição a sanções, proximidade a mixers, fundos roubados. Consulte Triagem de cripto e carteiras.
  4. Transferência Travel Rule. O motor de troca verifica o limiar e respeita uma declaração de carteira autocustodiada, armazenando depois a transferência: NOT_APPLICABLE abaixo do seu limiar, UNCONFIRMED_OWNERSHIP para uma carteira autocustodiada declarada, COMPLETED quando a outra carteira é a sua própria carteira verificada e AWAITING_COUNTERPARTY caso contrário, com o respetivo rail ainda vazio. Cada alteração de estado coloca em fila um evento travel_rule.status.updated, e a Didit envia-o após o transaction.created da transação (passo 7).
  5. Emissão da sessão de comprovação de propriedade da carteira. Se a transferência exigir comprovação de controlo por parte do utilizador final e auto_wallet_verification estiver ativado, é gerada uma sessão de widget de propriedade de carteira devolvida em action_required.
  6. Avaliação de regras. Todas as regras ativas são executadas - o pacote de regras TFR da UE reage ao estado da transferência definido no passo 4, as suas regras personalizadas consultam o resultado da triagem do passo 3, e uma regra pode reter a transação (IN_REVIEW), recusá-la ou exigir verificação reforçada (step-up) (AWAITING_USER).
  7. Faturação e notificação. Uma transação de saída é faturada numa única linha: a linha da Travel Rule quando iniciou uma troca, e a Triagem de Transações caso contrário. Uma transferência recebida não acarreta nenhuma das tarifas, e uma aplicação em sandbox nunca é cobrada. A resposta é devolvida e transaction.created é disparado para os seus destinos de webhook, seguido pelos eventos travel_rule.status.updated do passo 4.
  8. Encaminhamento, após a resposta. A Didit percorre os sete rails por ordem de prioridade; se nenhum resolver, a atribuição por análise de blockchain identifica a contraparte e os rails são executados novamente uma vez. O primeiro rail acessível processa a troca: a transferência permanece em AWAITING_COUNTERPARTY nesse rail enquanto a contraparte responde, liquida de imediato quando uma contraparte INTERNAL é correspondida (COMPLETED ou COUNTERPARTY_MISMATCHED_DATA), ou passa para COUNTERPARTY_VASP_NOT_FOUND quando nenhum rail alcança a contraparte. Cada alteração dispara travel_rule.status.updated, e as suas regras são executadas novamente sempre que o estado ou o rail mudarem. Uma transferência que o encaminhamento deixe em COUNTERPARTY_VASP_NOT_FOUND obtém a sua sessão do widget de propriedade de carteira nesse momento (quando auto_wallet_verification estiver ativado); consulte-a a partir de action_required da transação com Get transaction.

Como cada passo corresponde às suas obrigações

Nota sobre testes. As aplicações em sandbox ignoram a avaliação de regras e a faturação, e não enviam webhooks transaction.created ou transaction.status.updated. As transações em sandbox permanecem APPROVED, a menos que uma transferência Travel Rule prestes a expirar aplique o seu timeout_outcome, e nada é cobrado. O motor de troca da Travel Rule é executado em aplicações em sandbox quando a Travel Rule está ativada, contra uma única contraparte: cada troca de saída segue para o Didit Test VASP no rail TEST_VASP, que responde dentro da Didit com o cenário que escolher, para que a transferência fique concluída, seja recusada, apresente divergência de dados, fique inacessível, expire ou aguarde pela comprovação de propriedade da carteira. Nenhuma mensagem de conformidade chega a um VASP de contraparte real, e os webhooks travel_rule.status.updated são entregues com environment: sandbox. Numa transferência recebida, o VASP de teste pode enviar-lhe uma transferência (Trigger Test VASP Inbound Transfer), e o registo (POST /v3/travel-rule/inbound/) é liquidado com base no livro de endereços da sua carteira tal como numa aplicação em produção - ON_HOLD, UNCONFIRMED_OWNERSHIP, COUNTERPARTY_MISMATCHED_DATA ou COMPLETED seguido de FINISHED. Consulte Testar a Travel Rule em sandbox.

Ciclo de vida

Cada transferência tem um status selecionado a partir de 13 valores. A troca começa em AWAITING_COUNTERPARTY no caso normal, em NOT_APPLICABLE quando o montante está abaixo do seu threshold_amount ou um pedido de pagamento Lightning não indica nenhum beneficiário (consulte Lightning), ou em UNCONFIRMED_OWNERSHIP quando o destino foi declarado como uma carteira autocustodiada, e termina num dos estados terminais: FINISHED, CANCELLED ou EXPIRED. A transferência executa a sua própria máquina de estados, separada do estado de análise da transação subjacente. O estado de uma troca nunca altera o estado da transação por si só, com uma exceção: uma expiração aplica o seu timeout_outcome configurado (ou uma política de sunrise ou de não resposta quando aplicável). Em vez disso, as suas regras voltam a ser executadas em cada transição, pelo que as regras do TFR da UE ou qualquer regra baseada em travel_rule_status podem mover a transação, por exemplo para IN_REVIEW. Uma transferência que necessite de comprovativo de controlo da carteira por parte do utilizador final adiciona um bloco action_required à transação, mas o seu status permanece tal como as suas regras o deixaram. Leia o estado da troca a partir de travel_rule.status; leia o veredito de permissão / suspensão / recusa a partir do próprio status da transação. Cada transição (e cada estado reportado passivamente) é também refletida nos valores personalizados da transação para que as regras possam basear-se nela: custom_values.travel_rule_status (estado 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 das suas definições: SG → singapore, GB → uk, e qualquer código de membro da UE ou do EEE como DE ou FR → eu; códigos não mapeados são gravados em minúsculas, por exemplo US → us. Um props.travel_rule_regime submetido por si prevalece sempre sobre o valor derivado).
Nunca transmita para a rede antes de COMPLETED. Libertar fundos on-chain enquanto uma transferência está em AWAITING_COUNTERPARTY, UNCONFIRMED_OWNERSHIP, ou em qualquer estado de discrepância/recusa anula o propósito da troca de informações. Condicione o seu passo de transmissão a status == "COMPLETED", e depois chame PATCH .../travel-rule/ com o payment_txn_id resultante para transitar para FINISHED.
As transições, de relance (CANCELLED é adicionalmente acessível a partir de qualquer estado não terminal com action: "cancel"):

Entrega e tentativas

A Didit envia, fora do pedido que a originou, todas as mensagens que uma transferência tem de enviar, e tenta novamente até que a outra parte a receba. O objeto de transferência devolvido por Concluir, cancelar ou reenviar, Confirmar propriedade e registo de sunrise inclui a mais recente em delivery, tal como o objeto travel_rule embutido da transação; fica a null quando a transferência nunca exigiu uma mensagem. Uma falha da qual a rede ainda possa recuperar (falta de resposta atempada, falha de ligação, HTTP 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 recusou-a, ou a sexta tentativa falhou também - a transferência transita para COUNTERPARTY_VASP_NOT_REACHABLE com last_error na sua timeline, e pode tentar novamente com action: "resend". Qualquer outra mensagem que falhe definitivamente é registada na timeline. delivery nunca substitui o status da transferência: leia a troca de informações a partir de status, e utilize delivery para verificar por que motivo uma transferência ainda está em espera.

Valores de estado legados

Se já enviava travel_rule_details.status antes desta versão, esses valores continuam a funcionar e são mapeados automaticamente. As grafias em camelCase de qualquer estado (por exemplo counterpartyVaspNotFound) também são aceites, tanto no envio como em valores de condição de regra, e são normalizadas para a forma canónica:

Configuração

Configure o seu perfil de VASP e a política de negociação uma vez por aplicação com GET/PUT /v3/travel-rule/settings/.
O PUT é uma atualização parcial - envie apenas os campos que pretende alterar.

Rigor da correspondência de nomes

Modos de validação de propriedade

ownership_validation_mode determina o nível de comprovação da propriedade de uma carteira necessário antes de uma transferência poder basear-se nela: Uma carteira fica associada a cada utilizador final assim que for verificada. Em FULL e SIMPLIFIED, uma transferência posterior apenas reutiliza a carteira quando for suportada por um comprovativo que o modo aceite para essa transferência. Quando inbound_auto_accept não encontra nenhuma carteira no livro de endereços para corresponder, uma carteira de criptomoeda registada por si nas transações de exatamente um utilizador final identifica o titular. A Didit adiciona essa carteira ao livro de endereços do utilizador final como a sua autodeclaração, verificada exceto se o modo for FULL. Nunca adiciona uma carteira que o livro de endereços já liste sob outro nome da mesma cadeia (eth e ethereum), incluindo uma registada como pertencente a outro VASP. As verificações de endereço que outros VASP efetuam antes do envio (através de GTR, Sygna e VerifyVASP) também seguem o modo: sob FULL, uma carteira que o utilizador final apenas tenha declarado não é reportada como sendo sua.

Partilha de dados

data_sharing_fields escolhe quais os campos que a Didit envia à contraparte sobre os seus próprios utilizadores, separadamente para particulares e empresas:
  • Os particulares podem partilhar name, wallet_address, address, national_id, customer_identification, date_of_birth e place_of_birth. As empresas utilizam os primeiros cinco.
  • name e wallet_address são sempre enviados.
  • Um tipo de entidade que nunca tenha configurado partilha todos os campos. Uma lista vazia é também uma escolha: partilha apenas o nome e a carteira.
  • Um PUT faz a intercalação por tipo de entidade, pelo que enviar individual não altera a escolha armazenada para company.
  • Uma escolha que não consiga satisfazer as obrigações do ordenante do regime da sua jurisdiction (EU TFR ou Recomendação 16 do GAFI/FATF), incluindo uma lista vazia, é recusada com 400. Os erros surgem sob data_sharing_fields, indexados pelo tipo de entidade.

Correspondência por campo

matching_rules define o nível de rigor com que cada campo dos dados da contraparte é comparado com os dados que possui:
Cada valor é NONE, STRICT, CONTAINS, DEFAULT ou FUZZY. Predefinições: name segue name_matching_strictness, date_of_birth e address são NONE, e account é STRICT. Um campo omitido mantém a respetiva predefiniçã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 âmbito de aplicação da Travel Rule varia consoante o regulador. A Didit tem como predefinição 0.00 - a posição da UE - pelo que é trocada informação relativamente a todas as transferências, a menos que aumente este valor deliberadamente: Defina threshold_amount com o valor indicado pelo seu regulador; as transferências abaixo deste limiar resultam em NOT_APPLICABLE sem partilhar quaisquer dados de identidade. Os limiares evoluem - confirme o valor em vigor junto do seu consultor jurídico de conformidade em vez de tratar esta tabela como aconselhamento jurídico.

Modelo de dados IVMS 101

O padrão da indústria para os dados trocados ao abrigo da Travel Rule é o IVMS 101 (interVASP Messaging Standard). travel_rule_details.originator_data e travel_rule_details.beneficiary_data são payloads de pessoas no estilo IVMS 101: o Didit envolve-os no envelope nativo de cada rail - o rail TRP troca blocos IVMS101 (ivms101.2023, reportado no campo ivms_version da transferência), o rail Sygna a sua variante IVMS encriptada com ECIES, e os rails GTR, TRUST e VERIFYVASP os seus próprios envelopes encriptados - para que um único formato de payload chegue a cada contraparte no formato esperado pelo respetivo protocolo. O Didit lê estas chaves de cada payload de pessoa ao construir a mensagem IVMS 101: 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:
  • Sistema de escrita latino. O IVMS 101 exige valores no sistema de escrita latino; translitere nomes que estejam originalmente escritos noutro sistema de escrita. A correspondência de nomes do Didit compara conjuntos de tokens normalizados, pelo que diferenças de ordenação e de maiúsculas/minúsculas não inviabilizam uma troca - mas sistemas de escrita diferentes entre ambas as partes irão inviabilizá-la.
  • Envie dados que verificou. Quando a pessoa por trás de vendor_data for um utilizador com uma verificação KYC aprovada no Didit, o Didit transmite a identidade verificada, e não os valores que introduziu: consulte Dados verificados e proveniência. Para qualquer outra pessoa, o Didit transmite exatamente o originator_data que enviar, pelo que deve construí-lo a partir da identidade que verificou no onboarding, e não a partir de um campo de formulário não verificado. É isso que a redação de “informações obrigatórias e exatas sobre o ordenante” do GAFI/FATF exige. No rail INTERNAL, a aplicação do beneficiário também recebe o subject que enviou (nome, vendor_data, data de nascimento, país e morada) como a contraparte da sua transação recebida.

Dados verificados e proveniência

Quando a parte de uma transferência for um dos seus utilizadores, uma pessoa singular com uma verificação KYC aprovada, o Didit constrói esse lado da troca a partir dos dados verificados:
  • o ordenante de uma transferência enviada que criar com POST /v3/transactions/;
  • o beneficiário de uma transferência recebida que reportar com POST /v3/transactions/, ou com POST /v3/travel-rule/inbound/ quando o holder_vendor_data da carteira correspondente indicar esse utilizador.
No POST /v3/transactions/, ambos aplicam-se a uma transação cujo transaction_category seja travel_rule enquanto a Travel Rule estiver ativada. Os nomes verificados, a data e o local de nascimento, o número e o tipo de documento, a morada e o país de residência (a partir dessa morada) têm precedência sobre os valores que enviou. Um campo que a verificação não contenha mantém o seu valor, assim como uma morada completa que tenha enviado quando a verificada não for suficientemente completa para transmissão. Os metadata da transferência, no objeto incorporado travel_rule da transação, registam a origem de cada campo e onde os seus valores divergiram:
*_provenance mapeia cada campo para verified ou caller, e *_verified_differences lista todos os campos onde enviou um valor diferente do verificado, ignorando maiúsculas/minúsculas, espaçamento e códigos de país de duas ou três letras. Enquanto os dados de uma transferência recebida estiverem mascarados, as diferenças são omitidas. O Didit calcula ambos, pelo que cópias destas chaves, ou de name_match, que enviar em travel_rule_details.metadata são descartadas.

Envio direto de IVMS 101

Além dos objetos planos originator_data e beneficiary_data, o campo travel_rule_details (em POST /v3/transactions/) e o endpoint POST /v3/travel-rule/inbound/ aceitam IVMS 101 autêntico:
  • um bloco originator e um bloco beneficiary, com originatorPersons ou beneficiaryPersons contendo uma naturalPerson ou uma legalPerson, e accountNumber;
  • os mesmos blocos dentro de um objeto ivms101 (ou IVMS101);
  • uma pessoa IVMS 101, ou um bloco completo, como originator_data ou beneficiary_data.
Cada lado aceita uma pessoa: uma naturalPerson, ou uma legalPerson, o que torna a parte uma empresa. Um originator_data ou beneficiary_data plano não vazio tem precedência sobre um bloco para o mesmo lado.
Um bloco malformado devolve uma resposta 400 identificada pelo seu caminho, por exemplo {"travel_rule_details": {"originator.originatorPersons": ["must be a non-empty list of originator persons."]}}. No POST /v3/travel-rule/inbound/, as mesmas chaves situam-se no nível raiz, sob ivms101. quando utilizou o invólucro.

Dados obrigatórios por regime

Enquanto a Travel Rule estiver ativada, uma transferência enviada de valor igual ou superior ao seu limiar deve incluir o que o respetivo regime exige, caso contrário responderá com 400. Apenas os lados enviados são verificados, os dados verificados contam para o ordenante e os erros situam-se 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.": Para o ordenante, a validação lê os campos que a sua aplicação partilha em data_sharing_fields, pois são apenas esses que um rail envia; o beneficiário é verificado tal como o enviou. Quando a transferência cumpre o regime apenas através de um campo que não partilha, o erro 400 indica o requisito do regime seguido dos campos que as suas definições partilham. 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 a partir de counterparty.payment_method.account_id antes da validação, e um levantamento UTXO cujo output do beneficiário o Didit inferiu a partir de travel_rule_details.utxo conta como incluindo esse dado. Uma transferência Lightning à qual a Travel Rule não se aplica não é verificada.

Travel addresses

Um Travel Address é uma cadeia compacta e codificada que aponta para o endpoint de consulta TRP de entrada de um VASP - nunca expõe um URL em bruto nem qualquer endereço de carteira. Assim que a Travel Rule estiver ativada, a Didit deriva o seu próprio travel_address (devolvido em modo só de leitura nas definições) para que o possa partilhar com outros VASP que o contactem através do carril TRP. Cada uma das suas próprias carteiras do livro de endereços também recebe um receiving_travel_address por carteira: uma consulta enviada para o mesmo identifica essa carteira, pelo que a Didit não precisa de a procurar pelo número de conta ou nome do titular. O host TRP público da Didit ainda não responde a outros VASP, pelo que a receção através do TRP não está disponível até que o faça: consulte Redes da Travel Rule. Quando souber o Travel Address de uma contraparte, guarde-o na entrada do livro de endereços de carteiras de destino para que a Didit encaminhe diretamente através de TRP as transferências desse beneficiário em vez de recorrer ao e-mail. A Didit valida os Travel Addresses que guarda numa entrada do livro de endereços de carteiras ou que envia em originating_vasp: cada um deve começar por ta e descodificar-se num URL de consulta com t=i, pelo que um marcador de posição como ta... devolve 400. O campo beneficiary_data.travel_address numa transação não é validado: se não puder ser descodificado, o carril TRP é ignorado. A codificação é Base58Check com um prefixo ta: o host e caminho do endpoint (que inclui sempre o par de consulta t=i) mais uma soma de verificação double-SHA-256 de quatro bytes, codificada em base58. Um endereço real tem, portanto, o seguinte aspeto e tem cerca de 100 carateres:
Nos casos em que a Didit valida um Travel Address, um valor que não seja um endereço bem formatado e com soma de verificação válida devolve 400 com "Invalid travel address.". Obtenha um endereço real a partir da resposta às suas próprias definições ou diretamente da contraparte.

Testar sem credenciais de rede

Não precisa de uma adesão à GTR, TRUST, VerifyVASP ou Sygna para testar os caminhos sem adesão. Continua a necessitar de uma chave de API da Didit para a aplicação em teste.
  • Saída em sandbox: envie uma transação travelRule a partir de uma aplicação de sandbox. Após as verificações de limiar e de carteira autocustodiada, o Didit Test VASP responde dentro da Didit com o cenário que escolher com base na carteira ou no nome do beneficiário: aceitar, recusar, divergência de nome, inacessível, tempo limite excedido ou autocustodiada. Nenhuma rede, e-mail ou outro cliente da Didit recebe o que quer que seja.
  • Entrada em sandbox: faça com que o VASP de teste lhe envie uma transferência com Trigger Test VASP Inbound Transfer, ou registe uma por conta própria 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 correspondente verificada. Isto permite testar decisões de entrada reais sem contactar uma rede.
  • Duas aplicações de produção controladas: utilize o carril INTERNAL entre duas das suas próprias aplicações de produção (a recetora é detetável e comprova o controlo 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 de redes comerciais. As aplicações de produção podem incorrer em cobranças e notificações normais; utilize identidades de teste e contrapartes que controle.
Consulte Testar a Travel Rule em sandbox para conhecer todos os cenários e o respetivo resultado exato. Os testes bem-sucedidos em sandbox ou de protocolo local não validam as credenciais, a adesão ou a interoperabilidade em produção de uma rede comercial. Estes requerem uma sandbox de rede autorizada ou uma troca controlada em produção com credenciais de adesão válidas.

Enviar uma transferência

Inclua a transferência em POST /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 de o anexar, travel_rule_details.status é obrigatório: um bloco sem este campo devolve 400. Quando a Travel Rule está ativada para a sua aplicação, a Didit ignora o valor de status que enviar e gere a troca por si própria:
  1. Se o montante for inferior ao seu threshold_amount configurado, a transferência resolve-se imediatamente para NOT_APPLICABLE e nada é negociado.
  2. Se o método de pagamento da contraparte declarar o destino como uma carteira autocustodiada (payment_method.method_type: "unhosted_wallet"), nenhum canal é tentado - a transferência avança diretamente para UNCONFIRMED_OWNERSHIP e o widget de propriedade da carteira é gerado automaticamente (consulte Carteiras autocustodiadas declaradas).
  3. Caso contrário, os canais são executados por ordem de prioridade, e o primeiro que conseguir alcançar a contraparte processa a troca:
    • INTERNAL - exatamente um outro cliente da Didit possui uma prova por mensagem assinada ou depósito de teste para beneficiary_data.wallet_address, realizada após a carteira ter mudado de titular pela última vez. A sua própria aplicação nunca conta e, quando o seu utilizador final tiver selecionado um membro da rede Didit no widget de propriedade da carteira, apenas a prova desse membro é considerada. A aplicação desse cliente está em produção (não sandbox), tem a Travel Rule ativada e is_discoverable definido, e é o VASP que indicou ao enviar counterparty_vasp_lei ou counterparty_vasp_name. Uma carteira que seja apenas autodeclarada, comprovada por captura de ecrã, não verificada ou apenas listada num livro de endereços nunca recebe nada através de INTERNAL.
    • TRP - o ativo da transferência tem um mapeamento de identificador de token digital para a rede da transferência (consulte Identificadores de ativos TRP), e o payload contém beneficiary_data.travel_address, a própria entrada de livro de endereços do destino armazena um, ou a contraparte é resolvida no diretório (por counterparty_vasp_lei ou counterparty_vasp_name) com um endpoint TRP.
    • GTR, TRUST, VERIFYVASP, SYGNA - ligou a sua própria adesão a essa rede no Marketplace, e a contraparte resolve-se para um ID de rede (campo explícito ou entrada no diretório - consulte Campos de resolução da contraparte). A Didit ainda não possui adesão de plataforma nestas redes (está em onboarding como fornecedor), pelo que disabled_networks não altera este passo atualmente.
    • EMAIL - beneficiary_data.counterparty_vasp_email foi fornecido, ou counterparty_vasp_name é resolvido para uma entrada no diretório com um e-mail de conformidade.
  4. Se nenhum canal conseguir resolver uma contraparte, a Didit executa a cadeia de descoberta de contrapartes. Com vasp_attribution_enabled ativado, isso inclui a atribuição por análise de blockchain: a carteira de destino é resolvida para o respetivo VASP proprietário, o nome atribuído é gravado em beneficiary_data.counterparty_vasp_name (quando vazio) e no diretório, e os canais são executados novamente uma vez - assim, uma carteira atribuída a um VASP cuja entrada no diretório contenha um endpoint TRP, ID de rede ou e-mail de conformidade é encaminhada nesta segunda passagem.
  5. Se a contraparte continuar por resolver, 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 (quando auto_wallet_verification estiver ativado) para que a transferência ainda possa ser concluída como uma transferência para carteira autocustodiada, e pode voltar a executar o encaminhamento mais tarde com action: "resend" assim que tiver melhores dados da contraparte.
Os passos 1 e 2 ocorrem dentro do pedido. Os passos 3 a 5 são executados logo após a resposta: a transferência regressa com AWAITING_COUNTERPARTY e protocol: null, e cada resultado chega como um webhook travel_rule.status.updated.

Identificadores de ativos TRP

O TRP identifica o ativo transferido pelo seu Identificador de token digital (DTI) ISO 24165. Um DTI identifica um token numa blockchain, pelo que um token multicadeia possui um DTI por rede. A Didit envia transferências através de TRP para estes ativos: Os identificadores do USDC são os que o emissor do token publica no seu livro branco do MiCA. Para um token multicadeia, a transferência tem de indicar a sua rede em transaction_details.crypto_params.crypto_chain (por exemplo CELO, BASE, OP, ARB ou POL). Sem uma rede, ou numa rede sem mapeamento, a transferência não é enviada através de TRP e a Didit tenta os canais restantes: primeiro as redes de interoperabilidade e, em seguida, o e-mail. O USDT ainda não está mapeado. Um token sem mapeamento de DTI, tal como a stablecoin de uma própria empresa, requer que o seu emissor registe um DTI junto da autoridade de registo ISO 24165, um por token por blockchain. Assim que os DTI existirem, contacte o suporte da Didit com cada DTI, a respetiva blockchain e as casas decimais do token, e a Didit adicionará o mapeamento. Os pedidos de informação de TRP recebidos que incluam um DTI mapeado por cadeia são registados com a moeda do token, o montante nas casas decimais do token e a rede.

Descoberta de contrapartes

Uma transferência que contenha apenas um endereço de carteira continua a alcançar a sua contraparte sempre que alguém conseguir identificar esse endereço. Antes de uma transferência de saída ser declarada não encaminhável, a Didit consulta, por esta ordem, e interrompe no primeiro passo que indique um VASP com uma rota: O campo discovery da transferência lista cada passo executado com o respetivo outcome (match, miss ou skipped), um reason legível por máquina, a vasp e a rail encontradas, e um carimbo de data/hora. Uma VASP selecionada por si ou pelo utilizador final tem prioridade sobre qualquer passo automático: a descoberta nunca a substitui pela sua própria estimativa. Quando nenhum passo identifica uma contraparte, a transferência passa para COUNTERPARTY_VASP_NOT_FOUND, ou COUNTERPARTY_VASP_NOT_REACHABLE quando uma VASP foi identificada mas nenhuma das suas rotas está disponível para a sua aplicação. A transferência inclui então um reason (awaiting_end_user, no_directory_match, directory_match_no_route, ou picked_member_without_proven_wallet quando o membro selecionado pelo utilizador final não comprovou a carteira) e uma lista de next_actions: A ligação do widget é o url nas ações que o utilizador final executa. Quando uma ação de propriedade da carteira está pendente, o bloco action_required da transação (do tipo wallet_ownership) contém o mesmo reason e next_actions, para que um cliente que já processe action_required mostre o seletor sem trabalho adicional.

Campos de resolução da contraparte

Tudo o que a Didit sabe sobre a contraparte provém de travel_rule_details.beneficiary_data. Estes campos determinam a resolução da via; todos são opcionais:

Estruturas de blockchain

Numa blockchain baseada em contas (blockchains EVM, Solana, Tron), uma transferência move fundos de um endereço para outro, e a Didit lê ambas as carteiras diretamente da transação. Três outras estruturas exigem mais detalhes, e o que a Didit determinou para elas está na transferência como chain_details (vazio, {}, numa blockchain baseada em contas). chain_details.originator e chain_details.beneficiary contêm, cada um, o address, o respetivo memo e a source de onde veio, e a correspondência e o encaminhamento leem as carteiras a partir daí em primeiro lugar.

Transferências UTXO

Uma transação de Bitcoin, Litecoin, Bitcoin Cash ou Dogecoin gasta inputs de qualquer número de endereços e paga qualquer número de outputs, sendo alguns deles o troco devolvido ao remetente. Envie os inputs e outputs como travel_rule_details.utxo (valores na própria unidade da moeda, como cadeias de caracteres decimais), e a Didit deduz o que não declarar:
  • Ordenante: originator_data.wallet_address quando o envia, caso contrário o endereço de input que mais contribuiu (source: largest_input).
  • Beneficiário: a carteira declarada, caso contrário o único output que não devolve troco a um endereço de input (only_non_change_output), caso contrário o output que paga o valor da transferência (amount_match).
A transferência passa então a incluir:
chain_details.warnings sinaliza o que não coincide: declared_originator_not_an_input, declared_beneficiary_not_an_output, beneficiary_output_ambiguous (não foi possível distinguir uma saída única) e beneficiary_output_amount_differs. utxo em qualquer outra blockchain devolve um 400, e cada lista contém no máximo 1,000 entradas. Um depósito comunicado aceita o mesmo objeto utxo (consulte Registo sunrise após depósito).

Redes com memo e tag

No XRP, Stellar (XLM), EOS, Cosmos (ATOM) e Hedera (HBAR), uma exchange recebe todos os clientes num único endereço partilhado e distingue-os através da tag de destino ou memo. O memo faz, por isso, parte da carteira: envie-o como payment_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 livro de endereços com um memo corresponde apenas a transferências que indiquem esse memo. Uma entrada sem memo corresponde a todo o endereço. Uma transferência que não indique qualquer memo nunca chega a uma entrada que tenha um: num endereço partilhado, um depósito sem a sua tag não pertence a ninguém.
  • Um X-address do XRP inclui a sua tag no próprio endereço: a Didit divide-o no endereço clássico e na tag (source: x_address), pelo que uma carteira registada em qualquer um dos formatos corresponde a uma transferência no outro.
  • Cada memo num endereço partilhado é o seu próprio método de pagamento na transação.
  • O que cada rede aceita: uma tag de destino do XRP é um número inteiro de 0 a 4294967295 (um número em formato JSON é aceite); um memo da Stellar tem até 28 bytes de texto, um id de 64 bits ou um hash de 32 bytes em hexadecimal; a EOS aceita até 256 bytes, a Cosmos até 256 carateres e a Hedera até 100 bytes. Um memo numa blockchain que não os suporte (Bitcoin, blockchains EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin, Lightning) devolve um 400.

Lightning

Um pagamento Lightning não possui um endereço de beneficiário on-chain: o pagador detém um pedido de pagamento. Numa transferência cripto de bitcoin ou Lightning, payment_method.account_id pode ser esse pedido, e a Didit identifica o beneficiário a partir dele sem contactar nenhuma rede: O destinatário é armazenado como a conta e como chain_details.beneficiary (source: invoice_payee), na blockchain LIGHTNING, e o que o pedido indica é colocado em chain_details.lightning. Quando o pedido não indica nenhum destinatário, uma transferência de saída fica como NOT_APPLICABLE com o motivo indicado 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 só é interpretado como Lightning em bitcoin, em LIGHTNING ou quando nenhuma blockchain é indicada (um endereço Lightning apenas em bitcoin ou LIGHTNING): em qualquer outra blockchain, é interpretado como o próprio endereço dessa blockchain.
O canal INTERNAL só alcança outro cliente da Didit através de uma carteira que esse cliente tenha provado que controla com uma mensagem assinada ou um depósito de teste, e essas provas existem atualmente para Bitcoin, blockchains EVM, Solana e Tron. Em redes com memo, Lightning, Litecoin, Bitcoin Cash e Dogecoin, uma transferência, por conseguinte, nunca alcança outro cliente da Didit através de INTERNAL. A correspondência de memo, tag e Lightning continua a aplicar-se ao seu próprio livro de endereços: transferências recebidas, depósitos comunicados e consultas TRP às suas carteiras.

Atualizar a carteira do ordenante

Um levantamento é frequentemente declarado a partir da carteira principal do seu cliente e transmitido a partir dos endereços que continham as moedas. Registe a carteira de onde os fundos efetivamente saíram com PATCH /v3/transactions/{transaction_id}/travel-rule/:
  • Apenas transferências de saída, e nunca transferências CANCELLED ou EXPIRED (409).
  • Quando as entradas UTXO da transferência são conhecidas, a carteira tem de ser uma delas (caso contrário, 400). Numa rede com memo, envie também memo.
  • Altera apenas o registo: nada é reenviado para a contraparte e o estado mantém-se. chain_details.originator passa a ser a nova carteira com source: updated, a timeline regista a carteira anterior e a nova carteira, e a contraparte INTERNAL da transferência é atualizada da mesma forma.

Atribuição por análise de blockchain

Quando fornece apenas um endereço de carteira, a Didit consegue, ainda assim, descobrir quem está do outro lado. Se nenhum canal conseguir encaminhar a transferência, a Didit resolve a carteira de destino consultando os dados de atribuição de análise de blockchain - a mesma análise que suporta a triagem de transações de cripto sabe quais carteiras pertencem a que exchanges e custodiantes. A atribuição é executada apenas em transferências de saída que incluam tanto uma carteira de destino como uma chain (consulte Campos de resolução da contraparte); sem uma blockchain indicada, a atribuição é ignorada. Quando a carteira é atribuída a uma entidade conhecida, a Didit:
  1. Regista a atribuição na transferência: beneficiary_data.counterparty_vasp_name é preenchido (caso não tenha fornecido um), e os metadados da transferência passam a incluir um bloco vasp_attribution com o nome da entidade, o tipo de entidade, o país e source: "blockchain_analytics".
  2. Adiciona a entidade ao diretório de VASPs (ou faz a correspondência com a entrada existente), para que a atribuição seja estável entre transferências.
  3. Executa novamente os canais com o nome atribuído - uma entrada no diretório que já contenha um endpoint TRP faz com que a transferência seja imediatamente encaminhada em vez de terminar em COUNTERPARTY_VASP_NOT_FOUND.
A chamada de atribuição funciona também como uma triagem completa de cripto: a transação recebe o resultado completo da triagem - pontuação de risco, categoria de risco da carteira, instantâneo da rede - exatamente como se a monitorização de cripto tivesse sido executada, e custom_values.aml_screening_trigger da transação é definido como travel_rule_attribution para que possa verificar que a triagem foi executada porque o encaminhamento da Travel Rule a exigiu. Quando a monitorização de cripto já tiver analisado a mesma carteira nesta transação, o resultado armazenado é reutilizado - sem uma segunda chamada à análise e sem uma segunda cobrança. A atribuição nunca bloqueia a criação da transação: se a consulta analítica falhar ou o seu saldo não a puder cobrir, a transferência simplesmente avança para COUNTERPARTY_VASP_NOT_FOUND e nada é cobrado pela tentativa. Em action: "resend", uma atribuição registada anteriormente é reutilizada em vez de ser consultada de novo. Desative todo o passo com vasp_attribution_enabled: false nas definições. Consulte Preços para saber como a chamada de atribuição é faturada. Quando a Travel Rule está desativada, o objeto travel_rule_details (incluindo um status fornecido pelo autor da chamada, legado ou atual) continua a ser registado na transação, mas passivamente - nenhuma via (rail) é acionada. Utilize isto para preencher retroativamente dados de conformidade que já monitorizou através do seu próprio processo. Uma transferência passiva de saída não inicia qualquer troca, pelo que é faturada como Triagem de Transações, e não na linha da Travel Rule. Com a Travel Rule ativada, este pedido é encaminhado através da via EMAIL, porque indica o e-mail de conformidade da contraparte e nenhuma via anterior consegue alcançar o beneficiário:
A resposta, abreviada para os campos relevantes aqui:
  • originator_data corresponde ao que enviou, porque o utilizador do exemplo não tem uma verificação KYC aprovada; para um utilizador verificado, o Didit constrói-o a partir dos dados verificados (consulte Dados verificados e proveniência). A via EMAIL mostra ao destinatário apenas os campos do ordenante que partilhar em data_sharing_fields.
  • beneficiary_data.chain é ETH porque o pedido não especificou nenhuma cadeia, pelo que o Didit a deduziu a partir da moeda.
  • status é APPROVED porque nenhuma regra atuou sobre a transação; as suas próprias regras podem definir outro estado.
  • O contacto de conformidade recebe a ligação de recolha, e a transferência fica concluída, falha na correspondência do nome ou é recusada quando respondem, ou expira se não o fizerem (consulte Recolha por e-mail).
O campo protocol ainda é null porque a via é escolhida após a resposta (por exemplo, EMAIL quando indicou counterparty_vasp_email): Obter transação mostra-o assim que for escolhido, e cada webhook travel_rule.status.updated posterior transporta-o em rail. Se a carteira do beneficiário pertencer a outro cliente Didit que tenha comprovado o controlo da mesma, a via INTERNAL liquida toda a troca logo após a resposta, e esse webhook já reporta COMPLETED (ou COUNTERPARTY_MISMATCHED_DATA). Quando o nome não coincide, a sua transferência fica como COUNTERPARTY_MISMATCHED_DATA e o outro cliente não recebe nada. Sem counterparty_vasp_email, e quando nem as vias nem a atribuição conseguem alcançar o beneficiário, a transferência termina mais tarde em COUNTERPARTY_VASP_NOT_FOUND com uma ação wallet_ownership na transação.
O objeto travel_rule embutido na transação transporta os campos próprios da transferência (uuid, status, protocol, required, obligations_count, originator_data, beneficiary_data, metadata), o que o Didit determinou e comparou (chain_details, name_match, data_match, mismatched_fields, e os campos de mascaramento data_masked e data_unmasked), bem como os campos que indicam a sua situação atual: direction, rail, counterparty_vasp, delivery, discovery, reason e next_actions (consulte Por que motivo uma transferência está bloqueada). Cada linha de GET /v3/transactions/ transporta o mesmo bloco, ou null no caso de uma transação sem transferência. Os endpoints dedicados de transferência abaixo também devolvem esses campos, além de ivms_version, ownership_confirmed, deadline_at, timeline e created_at, mas sem obligations_count ou metadata.
Para encerrar uma transferência de saída COMPLETED após a ter transmitido on-chain:
Isto exige que a transferência seja uma transferência de saída no estado COMPLETED - caso contrário, a API devolve 409. Em caso de sucesso, tanto a transferência de saída como a sua contraparte da via INTERNAL transitam para FINISHED, e o campo payment_txn_id da transação é definido com o hash que forneceu. Na via TRP, o Didit também envia o hash para o callback de confirmação da contraparte. Para cancelar uma transferência que ainda não atingiu um estado terminal, envie, em vez disso, {"action": "cancel"} para o mesmo endpoint. A contraparte da via INTERNAL também é cancelada e, na via TRP, assim que a contraparte tiver aprovado o pedido de informação, o Didit envia o cancelamento para o respetivo callback de confirmação. Uma transferência que já esteja em FINISHED, CANCELLED ou EXPIRED devolve 409. Um pedido sem payment_txn_id nem uma action suportada devolve 400. Numa transferência efetuada através de GTR, VERIFYVASP ou SYGNA, o Didit comunica o hash on-chain (ou o cancelamento) à rede após a resposta, com as mesmas tentativas de repetição; o campo delivery da resposta mostra essa mensagem. Para tentar novamente uma transferência de saída que não conseguiu alcançar a respetiva contraparte - uma que esteja atualmente em COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA - melhore primeiro os dados da contraparte, por exemplo, adicionando um travel_address ao registo da carteira de destino, um contacto ao registo da contraparte no diretório, ou catalogando o VASP no diretório. Em seguida, envie {"action": "resend"} para o mesmo endpoint. O Didit reinicia o prazo limite de confirmação e coloca novamente a sequência de encaminhamento na fila desde o início, utilizando os dados armazenados na transferência: a resposta mostra a transferência novamente em AWAITING_COUNTERPARTY (com resend queued na sua timeline), e o resultado chega através de um webhook travel_rule.status.updated. Um reenvio submetido enquanto uma tentativa anterior ainda está em execução é enviado assim que essa tentativa for concluída. Qualquer outro estado, ou uma transferência de entrada, devolve 409.
Para indicar a contraparte manualmente quando a descoberta não o conseguiu fazer, envie {"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"} (o id obtido a partir de GET /v3/travel-rule/vasps/). A transferência é encaminhada para esse VASP e enviada novamente. Apenas uma transferência de saída em COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA a aceita; qualquer outro estado devolve 409, e um id desconhecido devolve 404.

Por que motivo uma transferência está bloqueada

Uma transferência em COUNTERPARTY_VASP_NOT_FOUND ou COUNTERPARTY_VASP_NOT_REACHABLE indica por que motivo está bloqueada e o que permite desbloqueá-la, em cada consulta da respetiva transação. O bloco travel_rule de GET /v3/transactions/{transaction_id}/, da resposta 201 de POST /v3/transactions/, e de cada linha de GET /v3/transactions/ inclui essa informação, assim como o objeto de transferência devolvido pelo endpoint de transferência:
  • reason é a causa legível por máquina, "" para qualquer outro estado.
  • next_actions lista o que faz a transferência avançar, [] para qualquer outro estado.
  • delivery é a mensagem mais recente que a transferência deve ao outro lado: kind, status (QUEUED, SENDING, RETRYING, DELIVERED ou FAILED), rail, attempts, last_error, next_attempt_at e delivered_at, ou null quando não tiver nenhuma mensagem pendente.
  • discovery indica onde a Didit procurou a contraparte, uma entrada por passo executado: step, outcome (match, miss ou skipped), reason, vasp, rail e at.
email_undeliverable e delivery_failed resultam de uma falha de entrega e aparecem apenas em COUNTERPARTY_VASP_NOT_REACHABLE. Uma falha de entrega define reason primeiro, pelo que uma contraparte que a Didit tenha encontrado nunca é reportada como uma que não conseguiu encontrar. Os outros quatro resultam do rastreio de descoberta, em qualquer um dos estados. Um reenvio faz a transferência avançar, pelo que o respetivo reason deixa de estar definido. A entrada na cronologia de uma transição causada por uma falha de entrega apresenta o mesmo valor em reason. Se o fornecedor de e-mail recusar o e-mail de conformidade da transferência de exemplo acima, o bloco travel_rule da respetiva transação apresentará, de forma abreviada:
Aqui delivery coincide com reason, porque o próprio envio foi recusado. Uma recusa num lembrete, ou uma devolução reportada posteriormente, mantém delivery.status como DELIVERED: o primeiro e-mail chegou a sair. Consulte reason, e não delivery, para saber por que razão uma transferência está bloqueada. Para corrigir, forneça novamente o e-mail de conformidade da contraparte e, em seguida, reenvie:
O update_compliance_email mantém o endereço como o beneficiary_data.counterparty_vasp_email desta transferência: pertence apenas a esta transferência e não é adicionado a nenhuma entrada do diretório nem a nenhuma lista de contactos. O estado não é alterado, a cronologia ganha compliance email updated e a transferência mantém reason: email_undeliverable até que o reenvio envie o pedido para o novo endereço. Apenas uma transferência de saída em COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA o aceita; qualquer outra transferência responde com 409, e um compliance_email em falta ou mal formatado responde com 400.

Carteiras autocustodiadas declaradas

Quando o seu cliente lhe informar que o destino é a sua própria carteira autocustodiada (não alojada), declare-o na transação em vez de permitir que o encaminhamento descubra que não existe nenhum VASP por trás dela: defina o tipo do método de pagamento da contraparte como unhosted_wallet.
A declaração contorna totalmente o encaminhamento:
  • Nenhum rail é tentado - não existe um VASP de contraparte com quem trocar dados - e a transferência é criada diretamente em UNCONFIRMED_OWNERSHIP.
  • Quando auto_wallet_verification está ativado (o valor predefinido), a Didit cria automaticamente uma sessão do widget de propriedade da carteira vinculada à transação e devolve-a no bloco action_required da transação; os SDKs iniciam-na automaticamente no envio do lado do cliente.
  • Assim que o cliente comprovar o controlo da carteira, a transferência executa a correspondência de nome do beneficiário e avança para COMPLETED (ou COUNTERPARTY_MISMATCHED_DATA se a correspondência falhar).
Esta é a obrigação da TFR da UE relativa a carteiras autocustodiadas em formato de API: verificar a propriedade da carteira não alojada em vez de trocar dados com um VASP de contraparte. A declaração é lida a partir do método de pagamento no lado de destino de uma transferência de saída e no lado de origem de uma de entrada - em ambos os casos, o participante da contraparte. Uma transferência declarada como não alojada já se encontra no seu caminho final sem rails, pelo que UNCONFIRMED_OWNERSHIP não é um estado passível de reenvio - conclua a comprovação de propriedade (ou cancele) em vez de chamar action: "resend".

Receber

Confirmar a propriedade da carteira

Uma transferência aguarda em UNCONFIRMED_OWNERSHIP em dois casos:
  • Uma transferência recebida corresponde a uma entrada do livro de endereços cuja propriedade ainda não foi verificada.
  • A carteira da contraparte foi declarada como autocustodiada (counterparty.payment_method.method_type: "unhosted_wallet"), num levantamento de saída ou num depósito recebido. Consulte Carteiras autocustodiadas declaradas.
A sua aplicação confirma ou rejeita a transferência:
O corpo aceita confirmed (obrigatório, booleano) e um wallet_address opcional. O endpoint aceita uma transferência em qualquer um destes estados e devolve 409 com {"detail": "Transfer is not awaiting ownership confirmation."} para qualquer outro:
  • UNCONFIRMED_OWNERSHIP, em qualquer uma das direções.
  • ON_HOLD numa transferência recebida.
  • UNCONFIRMED_OWNERSHIP, ON_HOLD ou COUNTERPARTY_MISMATCHED_DATA numa transferência TRP recebida, para que um responsável pela conformidade possa resolver uma consulta da contraparte manualmente.
Numa transferência que a própria Didit criou (via INTERNAL, registo sunrise ou uma carteira autocustodiada declarada):
  • confirmed: true marca a entrada correspondente no livro de endereços como tendo a propriedade verificada e, em seguida, faz a correspondência do nome com o holder_name dessa entrada - COMPLETED se passar, COUNTERPARTY_MISMATCHED_DATA se não passar. A contraparte da via INTERNAL, quando existir, obtém o mesmo resultado. Para uma carteira autocustodiada declarada, confirmed: true regista que o seu cliente verificou quem controla a carteira da contraparte e conclui a transferência (COMPLETED), enviada ou recebida. Uma transferência recebida cujo depósito já tenha sido liquidado avança então diretamente para FINISHED.
  • confirmed: false move ambos os lados da transferência para COUNTERPARTY_VASP_GENERAL_DECLINE.
  • A entrada correspondente é pesquisada no seu próprio livro de endereços apenas pelo endereço, sem a blockchain. Resolver um ON_HOLD recebido sem nenhuma entrada correspondente cria a entrada a partir do beneficiary_data.wallet_address da transferência e marca-a como verificada. Uma carteira autocustodiada declarada é a exceção: a carteira é registada no seu livro de endereços com a propriedade verificada, conforme descrito abaixo. Em todos os outros casos, uma entrada em falta devolve 409 com {"detail": "wallet address entry no longer available"}, que é também o que uma entrada eliminada devolve.
Numa transferência TRP recebida, a mesma chamada responde à consulta da contraparte:
  • confirmed: true necessita de um endereço de pagamento para devolver, obtido primeiro a partir de wallet_address do pedido, depois da entrada correspondente e, por fim, de beneficiary_data.wallet_address. Se nenhum dos três estiver presente, o pedido devolve 400 com {"wallet_address": ["wallet_address is required to approve."]}. A Didit cria ou verifica a entrada, envia o callback de resolução da consulta para a contraparte, define ownership_confirmed e move a transferência para COMPLETED.
  • confirmed: false envia uma resolução recusada e move a transferência para COUNTERPARTY_VASP_GENERAL_DECLINE.
  • Se o endpoint de callback da contraparte não puder ser alcançado, o pedido devolve 502 e a transferência mantém o seu estado atual. Numa aprovação, a entrada no livro de endereços continua a ser criada ou marcada como verificada.
Para uma carteira autocustodiada declarada, a carteira que você verifica é a da contraparte: o destino de um levantamento enviado ou a origem (a carteira do ordenante) de um depósito recebido. A Didit adiciona-a ao livro de endereços com a propriedade verificada sob o nome da contraparte, para que a carteira seja comparada com o nome da contraparte (o ordenante, no caso de um depósito). Se o livro de endereços já contiver essa carteira com um nome de titular diferente, a transferência move-se para COUNTERPARTY_MISMATCHED_DATA. Se a transferência não indicar nenhuma carteira da contraparte, transmita wallet_address no corpo do pedido. Quando nem a transferência nem o pedido fornecerem um endereço, o pedido é rejeitado com 400.
  • Uma transferência de rede já respondida através da respetiva rede (uma transferência VerifyVASP, ou uma transferência GTR ou Sygna Bridge já decidida) devolve 409 (consulte Transferências a partir de uma rede).
A resposta é o objeto de transferência mais completo descrito acima. Uma nova transferência INTERNAL nunca aguarda aqui: só chega a um cliente que já tenha comprovado a carteira. Uma transferência INTERNAL mais antiga que ainda esteja a aguardar desde antes dessa regra mantém os dados do remetente ocultos até que comprove o controlo da carteira (uma mensagem assinada ou um depósito de teste), e confirmá-la responde com 409 até que o faça. Recusá-la continua a funcionar. Quando a contraparte responder que a carteira é autocustodiada (atualmente, o Didit Test VASP dá essa resposta na sandbox), a confirmação adiciona a carteira ao seu livro de endereços sob o nome do beneficiário e executa a correspondência de nomes: uma correspondência conclui a transferência e marca a carteira como verificada.

Transferências a partir de uma rede

A Didit também pode receber transferências Travel Rule que uma contraparte envie através de GTR, VERIFYVASP ou SYGNA. A receção é ativada pela Didit para cada rede separadamente, e nenhuma está ativada hoje: também necessita do registo dos endpoints da Didit em cada rede, e a Didit ainda não é membro dessas redes. As transferências TRUST não podem ser recebidas. Assim que uma rede for ativada, uma mensagem entregue por ela é processada da seguinte forma:
  • Encaminhamento. A mensagem chega à sua aplicação quando identifica o código de participante da sua própria adesão ligada a essa rede. Uma mensagem endereçada à adesão da própria Didit só chega até si quando for o único cliente Didit em produção que comprovou o controlo da carteira do beneficiário. Qualquer outra mensagem é recusada, para que nenhum cliente receba a transferência de outro cliente.
  • Decisão. A Didit cria a transferência recebida na sua aplicação e decide-a como uma consulta TRP: correspondência da carteira, propriedade, correspondência de nomes e inbound_auto_accept.
  • Uma única vez. As redes reenviam uma mensagem até que seja respondida. Uma repetição obtém a resposta que a primeira cópia obteve, e nada é criado ou decidido duas vezes.
  • A sua revisão, através de GTR e SYGNA. Uma transferência que aguarde por si (UNCONFIRMED_OWNERSHIP, ON_HOLD ou COUNTERPARTY_MISMATCHED_DATA) é decidida com POST .../travel-rule/ownership/: confirmed: true aprova-a (transmita wallet_address quando a transferência não indicar nenhum) e confirmed: false recusa-a. A Didit responde à rede após a resposta, com as mesmas tentativas. Uma transferência que já tenha sido respondida devolve 409.
  • Sem resposta posterior através de VERIFYVASP. A VerifyVASP obtém a sua resposta no momento em que efetua o pedido, pelo que uma transferência que necessite da sua revisão é recusada de imediato e não pode ser decidida posteriormente (409).

Dados da contraparte mascarados

Até que a propriedade da carteira seja confirmada, os dados pessoais da contraparte numa transferência de entrada são devolvidos mascarados em vez de serem omitidos. A primeira letra de cada palavra é mantida, e o encaminhamento da carteira, da blockchain e do VASP permanece legível. data_masked é true, e a contraparte nos detalhes 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 regista a entrada de auditoria:
reason é ownership_confirmed, wallet_proof, address_book_match, own_verified_wallet, inquiry_approved (aprovou uma consulta TRP ou uma mensagem GTR ou Sygna), known_payment_method (a carteira do utilizador final nos seus próprios registos respondeu) ou travel_address (o Travel Address de cada carteira identificou a carteira). Uma transferência de entrada INTERNAL inclui data_unmasked com reason: wallet_proof desde o momento em que é criada, porque apenas um destinatário que comprovou a carteira recebe uma. actor é o e-mail do utilizador da consola ou a etiqueta da chave de API, ficando em branco para uma decisão automática. O relatório do Registo de transferências da Travel Rule (CSV e PDF) mascara os nomes de uma transferência de entrada da mesma forma até que a propriedade seja confirmada. Os relatórios que submete a um regulador, como o XML goAML e o PDF do relatório regulamentar, contêm os dados reais da contraparte.

Feedback de divergências

Uma transferência com COUNTERPARTY_MISMATCHED_DATA indica agora os campos que diferem. data_match contém a comparação e mismatched_fields lista os campos. Ambos contêm apenas os nomes dos campos e os resultados, nunca os valores, pelo que permanecem legíveis enquanto os dados estiverem mascarados:
A entrada na cronologia indica os campos, por exemplo “a data de nascimento do beneficiário não corresponde ao titular da carteira”. Uma rejeição TRP após uma divergência informa o VASP de origem sobre quais os campos que diferem, por exemplo “Os dados do beneficiário não correspondem ao titular da carteira: nome”. O que o outro VASP fica a saber é deliberadamente limitado: enquanto o nome estiver incorreto, o nome é o único campo comunicado (mismatched_fields: ["name"], todos os outros campos not_compared), e assim que o nome coincidir, todos os campos que diferem são indicados. Isto aplica-se ao lado do remetente de um intercâmbio INTERNAL e a uma rejeição TRP. Um nome em falta em ambos os lados é apresentado como not_compared e não constitui uma divergência, e um país coincide com base no código que o identifica, pelo que ES e ESP coincidem.

Pontuação de correspondência do nome

Cada transferência cujo nome foi comparado contém name_match, e a entrada na cronologia que a decidiu contém o mesmo objeto junto ao seu detail:
  • score é a semelhança dos dois nomes completos, de 0 a 100, e 0 quando qualquer um estiver em branco. matched é o resultado ao nível de rigor (strictness), pelo que os dois podem divergir: FUZZY decide com base no seu próprio rácio de semelhança de 0.85.
  • matched_names são as palavras do nome da transferência encontradas no outro nome; mismatched_names são as palavras que um dos lados tem e o outro não.
  • method é none, exact_token, token_subset, token_containment ou sequence_ratio, para NONE, STRICT, DEFAULT, CONTAINS e FUZZY.
  • compared_with é wallet_holder (o titular registado para a carteira) ou counterparty_vasp (o nome que a contraparte indicou na resposta através da página de resposta por e-mail, ou a resposta do Didit Test VASP).
  • O resultado da transferência depende de data_match, que compara todos os campos, pelo que uma transferência pode ter COUNTERPARTY_MISMATCHED_DATA enquanto name_match.matched é true.
  • name_match encontra-se no objeto de transferência devolvido pelos endpoints da Travel Rule e no travel_rule incorporado da transação, e é null até que um nome tenha sido comparado. A lista de transferências e os webhooks não o incluem.
  • Os nomes ficam ocultos enquanto as partes estiverem mascaradas, e na cópia do outro cliente de um intercâmbio INTERNAL.

Mensagens e pedidos de documentos

Dois VASPs podem resolver uma transferência contestada na Didit em vez de o fazerem por e-mail. GET e POST /v3/transactions/{transaction_id}/travel-rule/messages/ listam e enviam mensagens numa transferência:
  • kind é MESSAGE (predefinição) ou DOCUMENT_REQUEST. Um pedido de documentos necessita de pelo menos uma entrada em requested_documents (até 10); uma mensagem necessita de um body (até 5000 carateres) ou de um ficheiro.
  • reply_to faz referência a uma mensagem anterior da mesma transferência. Uma resposta do outro lado que inclua um documento cumpre o pedido de documentos a que responde, sendo definido fulfilled_at na mesma. A sua própria resposta nunca cumpre o seu próprio pedido.
  • Envie em formato multipart com files para anexar até 5 ficheiros de 10 MB cada, em PDF, PNG, JPEG ou WebP. A Didit verifica o conteúdo de cada ficheiro, não apenas o tipo declarado, e qualquer outro ficheiro faz com que o pedido responda com 400 no campo files (“Anexe apenas ficheiros PDF, PNG, JPEG ou WebP.”).
  • Uma transferência suporta até 100 mensagens, das quais até 20 podem conter anexos (cada uma com até 5 ficheiros), contabilizando ambos os lados; ultrapassar qualquer um dos limites faz com que o pedido responda com 400. Os anexos das mensagens não contam para os documentos da própria transação.
  • As mensagens funcionam através dos canais INTERNAL e EMAIL. Em INTERNAL, o outro cliente Didit vê a mensagem no seu lado do par. Em EMAIL, a contraparte recebe um e-mail e responde no portal de recolha. Se esse e-mail de notificação não puder ser enviado, a mensagem é guardada na mesma e o pedido responde com 201.
  • O pedido responde com 409 com um motivo em detail para uma transferência através de TRP, GTR, TRUST, VerifyVASP ou Sygna (esses protocolos não transmitem mensagens), uma transferência ainda sem contraparte, uma transferência INTERNAL cujos dados não coincidiram com o titular da carteira (nada chegou ao destinatário), uma transferência INTERNAL cujo destinatário ainda não comprovou o controlo da carteira (em ambos os lados, até que o faça), uma transferência EMAIL cuja contraparte já não possui um endereço de e-mail de conformidade e uma transferência EMAIL cuja ligação de recolha expirou ou cuja transferência se encontra encerrada.
  • Nenhum webhook é acionado quando a contraparte responde por escrito. Consulte o endpoint de mensagens.
  • O e-mail que informa a contraparte sobre uma nova mensagem é enviado em inglês.

Livro de endereços de carteiras

Registe as carteiras que controla para que as transferências de entrada (canal INTERNAL, consultas TRP de entrada e registos após depósito) possam ser associadas a essas carteiras, com 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 devolve apenas esses quatro campos. DELETE elimina a entrada (204) - o seu endereço fica disponível para novo registo e deixa imediatamente de corresponder a novas transferências.
A correspondência é insensível a maiúsculas e minúsculas no endereço, inclui o seu memo numa rede com memo e é limitada por chain. Quando uma transferência tem uma chain associada, uma entrada só corresponde se a sua chain tiver o mesmo valor (sem sensibilidade a maiúsculas e minúsculas) ou estiver vazia. Os nomes das chains são comparados como texto, não são traduzidos, pelo que uma entrada guardada como ethereum não corresponde a uma transferência cuja chain seja ETH. As transferências de saída obtêm a sua chain a partir de beneficiary_data.chain, depois de transaction_details.crypto_params.crypto_chain, depois de custom_properties.crypto_chain e, em seguida, da moeda (por exemplo ETH, ou para USDT e USDC a chain inferida de payment_reference_id), definida apenas quando for uma chain que a Didit reconhece, e os registos pós-depósito a partir do respetivo campo chain, em minúsculas. As consultas TRP de entrada ignoram a chain: correspondem por endereço ou, quando a consulta não indica nenhuma carteira, comparando o nome do beneficiário com as suas entradas verificadas. POST .../travel-rule/ownership/ também faz a correspondência apenas pelo endereço. Quando várias entradas correspondem, a via INTERNAL e os registos pós-depósito dão preferência a uma entrada cuja propriedade foi verificada e, de seguida, à mais antiga; e a pesquisa TRP de saída escolhe a entrada mais antiga que armazena um Travel Address. As consultas TRP de entrada e o endpoint de propriedade aceitam qualquer uma das entradas correspondentes, pelo que deve manter uma entrada por endereço sempre que possível. A via INTERNAL não faz corresponder nenhuma entrada se existirem entradas verificadas para o endereço em mais do que uma outra aplicação.

Importar carteiras em lote

Importe até 10,000 carteiras numa única chamada com POST /v3/travel-rule/wallet-addresses/import/, como JSON ({"entries": [...]} ou um array simples) ou como um ficheiro CSV em UTF-8 com um máximo de 5 MB com uma linha de cabeçalho. Uma linha identifica uma carteira pelo seu address, por address_hash (o SHA-256 do endereço em minúsculas, 64 carateres hexadecimais ou 44 carateres base64), ou ambos, além de qualquer um dos campos de entrada acima. Envie apenas o hash para registar uma carteira sem divulgar o seu endereço: corresponde a transferências para esse endereço como qualquer outra entrada e pode ser comprovada com o widget de propriedade de carteira.
A importação é idempotente e reporta cada linha na ordem enviada: created, existing (a mesma carteira, chain e memo já estão registados e não foram alterados), duplicate (repete uma linha anterior, indicada em duplicate_of_row) ou failed com os seus errors. Uma linha inválida nunca faz falhar as restantes: 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, pelo que uma exportação de outra ferramenta é importada tal como está. Em GET /v3/travel-rule/transfers/, cada linha inclui originator_memo e beneficiary_memo junto às duas carteiras.

Recolha por e-mail para contrapartes inacessíveis

Quando nenhuma via de protocolo consegue alcançar a contraparte, a Didit recorre a EMAIL: envia uma ligação de recolha de utilização única para beneficiary_data.counterparty_vasp_email (ou um e-mail resolvido a partir de beneficiary_data.counterparty_vasp_name face ao registo do diretório de VASPs). O destinatário não necessita de uma conta Didit nem de uma chave de API - o token da ligação é a autenticação. Como o pedido é enviado:
  • Para os endereços certos. Um counterparty_vasp_email que forneça é o único destinatário. Caso contrário, a Didit envia mensagens para até três endereços: os contactos da contraparte que não tenham sofrido bounce (primeiro os seus, depois os contactos da plataforma, dando prioridade aos que responderam anteriormente) e, se restar uma vaga, o e-mail de conformidade da entrada do diretório. Cada endereço recebe o seu próprio e-mail.
  • Em seu nome. O e-mail provém do endereço da Didit como “a sua denominação social via Didit”, no idioma da jurisdição da contraparte (inglês quando não for conhecida nenhuma), e a ligação abre a página de resposta nesse idioma. Não recebe nenhuma cópia: acompanhe a linha temporal da transferência.
  • Com lembretes. Até a contraparte responder, a Didit envia-lhe lembretes 72, 24 e 6 horas antes do prazo limite, pelo menos 12 horas após o pedido ou o último lembrete, e nunca após o prazo limite.
  • Com gestão de bounces. Um bounce ou uma denúncia de spam marca o contacto alcançado como inválido com o respetivo motivo, sendo registado na linha temporal da transferência. Um contacto da plataforma fica então inválido para todos os clientes da Didit; o contacto da sua própria aplicação apenas para a sua aplicação. Quando a entrega de e-mail da Didit deixa de enviar para um endereço (após um bounce permanente, uma denúncia de spam ou um cancelamento de subscrição), todos os contactos nesse endereço são marcados como inválidos (suppressed), voltando a ser válidos assim que o envio para o endereço for retomado. Quando já não resta nenhum endereço para o qual escrever, a transferência passa para COUNTERPARTY_VASP_NOT_REACHABLE com o motivo do servidor de correio recetor na respetiva linha temporal. Um bounce permanente ou uma denúncia de spam no counterparty_vasp_email que forneceu provoca isso de imediato, por ser o único destinatário; um bounce temporário (soft_bounce) no mesmo, ou no e-mail de conformidade da própria entrada do diretório, mantém o pedido aberto para os lembretes.
A ligação abre uma página alojada que mostra a troca pendente e chama estes dois endpoints públicos para o destinatário. Para a transferência de exemplo acima, os detalhes de recolha são:
reference é o uuid da transferência. originator_data e o ivms_request IVMS 101 construído a partir dele contêm apenas os campos do ordenante que partilhar em data_sharing_fields; o nome e a carteira estão sempre incluídos. fiat_amount e fiat_currency ficam vazios quando não enviou qualquer valor convertido, contact reflete o valor ?contact= da ligação e decline_reasons lista os valores que decline_reason aceita. join_invitation.eligible é true enquanto a contraparte tiver um convite ativo para aderir à Didit; a própria ligação de convite viaja apenas no e-mail. Este endpoint devolve o montante armazenado na íntegra, pelo que contém as 18 casas decimais completas em vez do formato truncado utilizado pelo objeto de detalhes da transação.
decision é accept ou decline. Em accept, o beneficiary_name fornecido é comparado com o beneficiary_data.name da transferência ao abrigo da sua regra de nomes - COMPLETED em caso de correspondência, COUNTERPARTY_MISMATCHED_DATA caso contrário. A contraparte pode, em alternativa, enviar uma resposta IVMS 101 completa como ivms_response; o seu nome de beneficiário prevalece então sobre beneficiary_name. Em decline, a transferência passa para COUNTERPARTY_VASP_GENERAL_DECLINE. A contraparte pode indicar um decline_reason a partir de decline_reasons, com um decline_detail (até 512 carateres, obrigatório para other), e a linha temporal da sua transferência regista-o, por exemplo, counterparty declined: The beneficiary is not our customer. A resposta é o {"status": "..."} resultante, mais decline_reason após uma recusa. Assim que a contraparte responder, ambos os endpoints devolvem 410. Ambos os endpoints devolvem 404 para um token desconhecido e 410 assim que a janela fecha - quer porque a transferência saiu de AWAITING_COUNTERPARTY, quer porque o respetivo prazo de confirmação (confirmation_timeout_hours após a criação ou o último reenvio) expirou. A contraparte consulta e responde através da ligação de recolha com GET e POST /v3/travel-rule/pickup/{token}/messages/. Não necessita de chave de API, aceita apenas anexos em PDF, PNG, JPEG ou WebP, e responde com 410 assim que a ligação expira ou a transferência é encerrada. Uma mensagem enviada por si apresenta o nome do seu VASP como author e como uploaded_by do anexo, nunca a pessoa ou a chave de API por trás da mesma.

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 em AWAITING_COUNTERPARTY ou NOT_ENOUGH_COUNTERPARTY_DATA até que os dados cheguem. Liste os depósitos que ainda estão a aguardar com uma chave de API que tenha o privilégio de transações:
A resposta utiliza as mesmas linhas que GET /v3/travel-rule/transfers/, limitada a depósitos de entrada que aguardam os dados do VASP de origem. Quando os dados tiverem chegado como uma mensagem recebida separada, emparelhe os dois manualmente:
{transaction_uuid} é o depósito. transaction_id é a transação da mensagem de Travel Rule recebida. A chamada devolve { "deposit": ..., "message": ... }. Responde com 404 quando qualquer uma das transações já não existir, e com 409 com travel_rule_match_conflict (“This deposit can no longer be matched.”) quando qualquer um dos lados já tiver avançado.

Registo sunrise posterior ao depósito

Quando um depósito de cripto é liquidado on-chain antes de qualquer troca de Travel Rule ter ocorrido - o VASP remetente estava inalcançável ou está a registar retroativamente depósitos históricos - registe-o posteriormente com POST /v3/travel-rule/inbound/.
originating_vasp.travel_address tem de ser um Travel Address real e com soma de verificação válida: um marcador de posição devolve 400 com "Invalid travel address.". originating_vasp.lei tem de estar vazio ou conter 20 carateres no formato LEI (18 letras ou dígitos, seguidos de 2 dígitos); qualquer outra coisa devolve 400 com "Invalid LEI: expected 20 alphanumeric characters (ISO 17442).". A Didit valida apenas este formato, e não os dígitos de controlo da ISO 17442. A Didit cria uma transação de entrada travelRule (ou reutiliza um depósito de entrada que já tenha submetido com o mesmo hash e carteira, se este ainda não tiver uma transferência da Travel Rule) e resolve a transferência em relação ao seu livro de endereços de carteiras, pelo endereço e respetivo memo:
  • Nenhuma entrada correspondente -> ON_HOLD. Resolva com POST .../travel-rule/ownership/: confirmed: true adiciona a carteira ao seu livro de endereços como verificada e executa a correspondência de nomes; havendo correspondência, a transferência avança para COMPLETED e depois para FINISHED.
  • A entrada existe, mas a propriedade não está comprovada -> UNCONFIRMED_OWNERSHIP.
  • O nome do beneficiário não corresponde ao holder_name da entrada -> COUNTERPARTY_MISMATCHED_DATA.
  • Entrada verificada e o nome corresponde -> COMPLETED e logo de seguida FINISHED (o depósito já foi liquidado).
Com a entrada verificada do livro de endereços registada no exemplo acima, a resposta é:
O txn_id da nova transação é tr-in-, os primeiros 80 carateres do txid e um hash de 12 carateres do txid e da carteira. created é true (HTTP 201) quando esta chamada registou o depósito, e false (HTTP 200) quando os mesmos txid e wallet_address já estavam registados, caso em que a transferência existente é devolvida sem alterações. No caminho de entrada verificada, ambas as transições ocorrem antes de o endpoint responder, pelo que a resposta síncrona já apresenta o estado terminal FINISHED - o passo intermédio COMPLETED continua registado na timeline da transferência. Cada transição aciona um webhook travel_rule.status.updated (COMPLETED e FINISHED acionam, cada um, um webhook). Quando a Didit cria uma nova transação, envia primeiro transaction.created e estes eventos a seguir. O registo não tem qualquer taxa de Travel Rule ou de monitorização. Quando a monitorização de criptoativos está ativada e a chain é uma das que a Didit consegue analisar, o depósito recém-criado também é analisado e faturado uma vez à tarifa de Verificação e Triagem de Carteiras.

Widget de propriedade da carteira

Para retirar uma transferência de UNCONFIRMED_OWNERSHIP - ou para pré-verificar uma carteira antes da chegada de qualquer transferência -, crie um widget alojado de propriedade da carteira com POST /v3/travel-rule/widget-session/ e encaminhe o seu cliente para o url retornado. O widget comprova o controlo da carteira através de assinatura de mensagens (incluindo contas de contratos inteligentes EVM, através de ERC-1271 e ERC-6492), um teste de Satoshi, uma captura de ecrã ou autodeclaração, e de seguida marca a entrada correspondente no livro de endereços como verificada para que a plataforma de câmbio possa prosseguir. A captura de ecrã é a exceção: nunca verifica a carteira por si só, pelo que a sua equipa de conformidade a revê e confirma uma transferência em UNCONFIRMED_OWNERSHIP com POST .../travel-rule/ownership/. Consulte Widget de propriedade da carteira para conhecer o fluxo completo, os métodos de comprovação e a nota importante de que o widget tem de ser aberto num 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 partilhadas do diretório mais os membros da rede Didit. Cada linha indica como a sua aplicação pode contactar esse VASP hoje.
search faz corresponder um fragmento de nome ou alias, um LEI exato ou um domínio (counterparty.example ou um URL nesse domínio). Filtre os resultados com: Os membros da rede Didit não são pontuados, pelo que risk e responsiveness devolvem apenas entradas do diretório. Os resultados são ordenados por nome e paginados com limit (predefinição 50) e offset. Uma rede, código de país, faixa de risco ou estado de capacidade de resposta desconhecido responde com 400 indicando o campo. GET /v3/travel-rule/vasps/{vasp_id}/ devolve uma linha pelo respetivo id. O perfil do seu próprio 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 contêm a avaliação partilhada de due diligence de uma entrada do diretório. decision, entity_screening e questionnaires são registos da própria aplicação sobre o VASP, e nenhum outro cliente os vê. Consulte Due diligence da contraparte para saber o que cada um significa, e aplique restrições com os campos de regras da contraparte em vez de criar ramificações em linha. Os membros da rede Didit não são pontuados: dd_status é COMPLETED, dd_score é null, risk_level está vazio e o detalhamento está vazio.

Rotas

routes lista as formas como a sua aplicação pode entregar ao VASP, pela ordem em que são tentadas pela hierarquia de encaminhamento, e reachable é true quando pelo menos uma está available:
  • TRP quando a entrada inclui um endpoint TRP verificado pelo diretório.
  • GTR, TRUST, VERIFYVASP, SYGNA quando uma rede lista o VASP sob um código. A rota está available apenas quando a sua aplicação pode enviar através dessa rede hoje (via: own_membership para a sua própria adesão ligada, via: didit_membership para a da Didit). Caso contrário, está unavailable com reason: no_membership ou reason: network_switched_off, nunca sendo apresentada como uma forma de alcançar o VASP. As adesões a redes da própria Didit ainda não estão ativas, pelo que hoje uma rota de rede está disponível apenas através de uma adesão que a sua aplicação associou no Marketplace.
  • EMAIL quando existe um contacto de conformidade para a entrada.
  • INTERNAL para um membro da rede Didit.
Uma listagem TRISA aparece em networks e indica quem é o VASP na TRISA, mas a Didit não tem um canal TRISA, pelo que nunca é uma rota. Uma aplicação de sandbox envia apenas para o Didit Test VASP, pelo que nenhuma rota do diretório está disponível para ela: todas as rotas estão unavailable com reason: sandbox_application, todas as linhas têm reachable: false, e reachable=true não devolve linhas.

Marcas e as respetivas entidades

Uma marca que opera através de várias entidades reguladas constitui uma linha cujas entities são as entidades legais que recebem as suas transferências; uma linha de entidade aponta de volta para a sua marca em umbrella. Uma transferência que indique a marca vai para uma das suas entidades, escolhida de entre todas elas: aquela na jurisdição indicada em beneficiary_data.counterparty_vasp_jurisdiction, caso contrário a entidade que a atribuição de análise de blockchain associou à carteira de destino, caso contrário a única entidade da marca quando nenhuma jurisdição for indicada. Só então essa entidade deve estar alcançável; se não estiver, a transferência nunca vai para outra entidade nem para a marca em substituição. Quando nenhuma entidade se adequa (duas adequam-se igualmente, ou uma jurisdição indicada na qual nenhuma delas se encontra), é utilizada a rota da própria marca e, sem ela, a transferência fica como COUNTERPARTY_VASP_NOT_FOUND. A escolha da entidade legal que recebe os dados do ordenante nunca é feita por suposição, e nunca é decidida com base em que entidade tem por acaso um contacto. Várias entradas com o mesmo nome, como empresas do grupo que partilham um nome comercial, são diferenciadas pela mesma regra: a que estiver na jurisdição indicada, caso contrário a que a atribuição de análise de blockchain tiver associado. Quando nenhuma das opções seleciona uma, nenhuma é utilizada, e os detalhes contam como não indicando qualquer entrada do diretório.

Contactos

contacts são os endereços para os quais o canal EMAIL escreve. Os contactos com scope: platform servem todos os clientes Didit: a Didit faz a sua curadoria (source: staff), ou um endereço num dos domínios do próprio VASP respondeu a um pedido através da sua ligação de resposta (source: learned). Os contactos com scope: application são privados para a sua aplicação: os que adiciona (source: application), e um endereço fora dos domínios do próprio VASP que respondeu a um dos seus pedidos (source: learned). Uma transferência envia um e-mail primeiro para o contacto da sua própria aplicação, depois para um contacto da plataforma que já tenha respondido anteriormente (verified_at definido) e, em seguida, para os restantes. Faça a gestão dos contactos da sua própria aplicação com a API de contactos de contrapartes:
  • GET /v3/travel-rule/counterparty-contacts/ lista todos os contactos para os quais a sua aplicação pode enviar, incluindo contactos da plataforma e contactos com mensagens devolvidas, os mais recentes primeiro, paginados com limit e offset. Filtre com ?counterparty= e um id de entrada do diretório; um valor que não seja um UUID responde com 400.
  • POST adiciona um contacto privado (counterparty, email, opcional name) e responde com 201. Adicionar um endereço que a entrada já tenha entre os seus próprios contactos devolve esse contacto. Uma entrada desconhecida responde com 400 ("No directory entry with this id.").
  • DELETE /v3/travel-rule/counterparty-contacts/{contact_uuid}/ elimina um dos seus próprios contactos (204). Os contactos da plataforma não podem ser eliminados e respondem com 404.
Um contacto cuja mensagem foi devolvida ou que apresentou uma reclamação tem is_invalid: true, com invalid_reason (hard_bounce, soft_bounce, spam_complaint ou suppressed), invalid_detail e invalid_at, e o canal EMAIL ignora-o. created_by está vazio em contactos da plataforma e em contactos adicionados por uma chave de API.

Como as entradas entram no diretório

  • O registo provisório MiCA da ESMA de prestadores de serviços de criptoativos, consultado semanalmente: o nome de cada prestador, LEI e Estado-Membro de origem.
  • O diretório público da TRISA, consultado semanalmente: a identidade de cada membro, o seu país e a sua listagem TRISA. Uma listagem que o diretório deixe de apresentar durante três semanas é removida.
  • O registo global de LEI preenche o LEI, outras denominações sociais e o país de uma entrada, e localiza o LEI de uma entrada pela sua denominação social exata no respetivo país.
  • A atribuição por análise de blockchain adiciona ou faz corresponder o VASP detentor de uma carteira de destino, mantendo o nome atribuído como um alias.
  • A equipa da Didit faz a curadoria das entradas: identificadores de encaminhamento e listagens de rede verificados por esta, contactos de conformidade, aliases, marcas e as respetivas entidades, duplicados fundidos e entradas ocultadas.
Os dados comunicados por um cliente sobre uma contraparte, tais como um originating_vasp recebido ou um Travel Address, permanecem na transferência desse cliente e nunca alteram uma entrada partilhada. As entradas são correspondidas primeiro pelo LEI, depois pelo nome exato ou alias, e são enriquecidas em vez de duplicadas.

A rede Didit

O perfil do seu VASP faz parte da rede Didit, pelo que outros clientes da Didit conseguem encontrá-lo no diretório e no seletor de VASP do utilizador final, apenas se todas as seguintes condições se verificarem:
  • a sua aplicação está em produção (não na sandbox) e a Travel Rule está ativa;
  • is_discoverable está a true e legal_name está definido;
  • compliance_email está definido e confirmado: envie a confirmação com POST /v3/travel-rule/settings/compliance-email/confirmation/ e abra a ligação enviada por e-mail. Alterar o endereço exige uma nova confirmação;
  • a Didit não marcou a aplicação como teste, demonstração ou aplicação interna.
O canal INTERNAL em si realiza a entrega numa carteira cuja posse comprovou, conforme descrito em Enviar uma transferência: apenas necessita que a sua aplicação esteja em produção, com a Travel Rule ativa e is_discoverable, dispensando o resto da lista. GET /v3/travel-rule/settings/ devolve didit_network: listed, compliance_email_confirmed, e em missing cada condição ainda não cumprida (travel_rule_off, sandbox_application, not_discoverable, legal_name_missing, compliance_email_missing, compliance_email_unconfirmed, excluded_by_staff, internal_organization).

Identificadores de encaminhamento

O encaminhamento de saída consulta uma entrada do diretório sempre que a sua transferência identifica a contraparte por counterparty_vasp_lei ou counterparty_vasp_name (um alias também funciona). Uma entrada inclui um identificador por rede na qual pode ser contactada, um endpoint TRP verificado e os seus contactos de conformidade, e routes mostra quais deles a sua aplicação pode utilizar. Pode sempre ignorar o diretório numa única transferência transmitindo os campos explícitos em Campos de resolução da contraparte.

Diligência devida da contraparte

Antes de os fundos dos seus clientes chegarem a outro VASP, precisa de saber quem é esse VASP e se o aceita. A diligência devida sobre uma contraparte tem duas camadas:
  • A avaliação partilhada. Cada entrada do diretório inclui uma pontuação de diligência devida, o respetivo nível de risco, um estado de capacidade de resposta e um relatório de verificações essenciais. A Didit calcula-os a partir dos dados da própria plataforma, para que todos os clientes vejam os mesmos valores.
  • Os seus próprios registos. A sua decisão sobre o VASP, a sua triagem de sanções e de notícias adversas do mesmo, e os questionários de diligência devida que trocou com ele pertencem unicamente à sua aplicação. Outro cliente nunca os vê e nunca alteram a entrada partilhada.
Os seus próprios registos funcionam de igual forma para uma entrada do diretório e para um membro da rede Didit: identifique ambos através do id que o diretório apresenta.

Pontuação e nível de risco

O dd_score varia de 0 a 100 e quanto mais elevado, mais seguro. Todos os resultados indicam-no em dd_score_semantic, que é sempre higher_is_safer. O risk_level é o intervalo em que a pontuação se enquadra: A pontuação é a soma de sete componentes. O dd_score_breakdown apresenta cada um como {points, max, reason, detail}: max é o peso do componente, reason um código legível por máquina que pode traduzir e detail uma explicação de uma linha em inglês. Os pontos são arredondados a uma casa decimal e o total a um número inteiro. O history avalia os mesmos pedidos que a capacidade de resposta, sem janela temporal: uma troca com o estado COMPLETED ou FINISHED é um sucesso, e uma troca com o estado EXPIRED, COUNTERPARTY_MISMATCHED_DATA ou COUNTERPARTY_VASP_GENERAL_DECLINE é uma falha. Um cancelamento é um ato do próprio remetente e nunca é contabilizado. A Didit recalcula a avaliação quando uma troca com a entrada é concluída, finalizada, expira, apresenta discrepâncias ou é recusada, quando atualiza ou faz a curadoria da entrada, e para cada entrada na atualização semanal do diretório. O dd_assessed_at indica quando foi executada pela última vez; uma entrada que ainda não tenha sido avaliada não tem dd_assessed_at, tem um dd_score de 0 e um risk_level vazio, pelo que deve ler o risk_level em vez da pontuação em bruto. Os membros da rede Didit não são pontuados: o respetivo dd_score é null, o respetivo risk_level está vazio e o respetivo dd_score_breakdown está vazio.

Verificações essenciais

O essential_checks é um breve relatório sobre quatro verificações que a Didit executa em cada entrada do diretório, apenas a partir de fontes verificadas da plataforma, nunca a partir de dados reportados por um cliente: Cada verificação em checks reporta o seu status (pass, fail, ou unknown quando nenhuma fonte registada o consegue decidir), um reason legível por máquina e um detail de uma linha em inglês. passed, failed, unknown e total contabilizam-nas, level é essential e checked_at indica quando o relatório foi gerado. O componente essentials pontua a percentagem de verificações decididas que são aprovadas, pelo que uma verificação com unknown não conta nem a favor nem contra a entrada. O relatório está vazio até que a atualização semanal do diretório verifique uma entrada pela primeira vez, e está sempre vazio para um membro da rede Didit.

Capacidade de resposta

O responsiveness indica se o VASP responde a pedidos de Travel Rule:
O total contabiliza os pedidos iniciados pelos clientes da Didit destinados ao VASP nos últimos 90 dias cujo resultado foi decidido, e o answered os pedidos aos quais este respondeu:
  • Contabilizados: pedidos enviados através de uma rede ou via de protocolo, e pedidos enviados por e-mail para um endereço partilhado, que seja o endereço de conformidade da entrada ou um contacto da plataforma.
  • Nunca contabilizados: um pedido enviado por e-mail para um endereço introduzido por um cliente ou para um contacto privado de um cliente. Essa troca permanece no histórico de transferências do próprio cliente e nunca rotula o VASP para todos os outros.
  • Respondidos: COMPLETED, FINISHED, COUNTERPARTY_VASP_GENERAL_DECLINE ou COUNTERPARTY_MISMATCHED_DATA. Uma recusa ou uma discrepância é uma resposta: o VASP interagiu.
  • Não respondidos: EXPIRED.
  • Nenhum dos dois: todos os restantes estados. Um pedido CANCELLED é um ato do próprio remetente, COUNTERPARTY_VASP_NOT_REACHABLE pode ser uma falha do lado do remetente e um pedido que ainda esteja em curso ainda não foi decidido.
Os membros da rede Didit respondem dentro da Didit e mostram sempre UNKNOWN com contagens a zero. Atue sobre uma contraparte que não responde com a política de não resposta ou com a predefinição travel-rule-counterparty-unresponsive.

A sua decisão sobre uma contraparte

Registe o veredito da sua equipa de conformidade sobre uma contraparte com PUT /v3/travel-rule/vasps/{vasp_id}/decision/:
  • A decisão é privada para a sua aplicação: outro cliente nunca a vê e nunca altera a entrada partilhada.
  • Uma decisão não altera nada por si só e nunca altera a forma como uma transferência é encaminhada. Chega às suas transações através do campo de regra counterparty_dd_status: instale as predefinições ou escreva a sua própria regra sobre o mesmo.
  • Uma decisão sobre uma marca abrange cada uma das suas entidades que não tenha uma decisão própria, e a entidade mostra a marca em inherited_from. Uma decisão sobre a entidade sobrepõe-se à da marca para essa entidade.
  • GET devolve a decisão aplicável ou {"decision": null}. DELETE limpa a sua própria decisão e devolve o que se aplica a seguir: a decisão da marca para uma entidade; caso contrário, null. Responde com 404 quando a sua aplicação não tem uma decisão própria sobre a contraparte.
  • reason é opcional, tem até 255 carateres e cada PUT substitui-o. decided_by é o utilizador da consola que tomou ou alterou pela última vez a decisão e fica vazio quando foi uma chave de API a fazê-lo.

Triagem de contrapartes

A triagem de contrapartes verifica o próprio VASP da contraparte, enquanto empresa, contra sanções e notícias adversas. É opcional e faturada: ative-a com counterparty_screening_enabled nas suas definições. Enquanto estiver desativada, nada é analisado ou faturado.
  • Faturação. Cada nova triagem custa o preço de Triagem AML de empresas da sua organização. O GET /v3/travel-rule/vasps/{vasp_id}/screening/ devolve esse price, fresh_days e se a triagem está enabled, sem custos. Uma triagem com menos de 30 dias é recente: o POST devolve-a novamente com 200 e outcome: reused e não fatura nada, a menos que envie refresh: true. Uma nova triagem devolve 201 com outcome: screened. As aplicações em sandbox nunca são analisadas nem faturadas.
  • Triagem automática. Com a triagem ativada, a Didit também analisa a contraparte que uma exchange de saída contacta quando a exchange se inicia, antes de as suas regras avaliarem a transação, com a mesma reutilização e faturação. Uma recusa ou falha nesse ponto nunca faz falhar a transferência.
  • Resultado. O status é Approved quando nenhuma correspondência potencial necessita de atenção, e In Review ou Declined para uma possível correspondência em sanções ou notícias adversas. flagged é true enquanto uma triagem recente estiver em In Review ou Declined.
  • Efeito. Enquanto a sua triagem mais recente de uma contraparte estiver sinalizada e a triagem permanecer ativada, counterparty_risk_level é HIGH nas suas regras, pelo que a predefinição travel-rule-counterparty-high-risk, depois de instalada, retém as suas transferências. O risk_level partilhado no diretório não muda.
  • Privacidade. A triagem é privada para a sua aplicação: outro cliente nunca a vê e nunca altera a entrada partilhada. O diretório mostra a sua mais recente como entity_screening.
  • Recusas. 409 quando a triagem está desativada, para uma aplicação sandbox, ou enquanto uma triagem da mesma contraparte já estiver em execução. 403 com code: insufficient_credits quando o seu saldo não cobrir o preço. 502 quando a triagem não pôde ser concluída. Nenhuma delas fatura nada.

Questionário de diligência devida

Peça a uma contraparte as suas respostas de diligência devida com o questionário padrão da Didit. O POST /v3/travel-rule/vasps/{vasp_id}/questionnaires/ envia-o por e-mail para um endereço de conformidade registado para a contraparte, com uma ligação de utilização única para uma página de resposta:
  • Para onde vai. sent_to deve ser um endereço de conformidade registado: para uma entrada de diretório, o seu endereço de conformidade ou um contacto que a sua aplicação veja em contacts; para um membro da rede Didit, o seu e-mail de conformidade confirmado. Omita-o para utilizar o endereço para o qual vai um e-mail de Travel Rule para a contraparte: primeiro o seu próprio contacto, depois um contacto da plataforma e, a seguir, o endereço de conformidade da entrada. A Didit nunca envia o questionário para nenhum outro local e responde com 400 quando a contraparte não tiver um endereço de conformidade registado.
  • Responder. A ligação abre /v3/travel-rule/questionnaires/{token}/, uma página para uma pessoa da contraparte que não necessita de conta nem de chave de API. Responde a cada pergunta, com até 2000 carateres cada (N/A onde não se aplique), e submete uma vez. Uma contraparte também pode enviar um pedido POST com {"answers": {"<question id>": "<answer>"}} para a mesma ligação. Uma ligação que tenha sido utilizada, substituída ou cujo prazo tenha expirado mostra, em vez disso, 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 o seu significado nunca mude entre idiomas.
  • Prazos. A contraparte tem 30 dias para responder (expires_at). As respostas permanecem válidas durante 365 dias (valid_until), e current é true até então. Um questionário sem resposta após o prazo, e respostas fora da sua validade, tornam-se EXPIRED.
  • Um questionário aberto por contraparte. Um novo envio substitui o seu questionário anterior sem resposta para a mesma contraparte: torna-se EXPIRED e a sua ligação deixa de funcionar. Pode ser enviado um e-mail por minuto para um endereço; um envio mais rápido responde com 429.
  • Ler as respostas. O GET /v3/travel-rule/vasps/{vasp_id}/questionnaires/ lista os seus questionários com a contraparte, dos mais recentes para os mais antigos, com answers organizadas por id de pergunta assim que respondidas. O diretório mostra-os como questionnaires. São privados para a sua aplicação.
A versão 1 do formulário faz estas doze perguntas:

Transferências com uma contraparte

O endpoint GET /v3/travel-rule/transfers/?counterparty={vasp_id} lista as transferências da Travel Rule da sua aplicação com uma contraparte, da mais recente para a mais antiga, pelo id que o diretório apresenta: as suas transferências cuja contraparte é essa entrada do diretório, ou os seus intercâmbios INTERNAL com esse membro da rede Didit. Um valor que não seja um ID válido devolve 400. Cada linha inclui reason logo após status: o próprio reason da transferência, para que a lista distinga um e-mail de conformidade devolvido de uma contraparte sem rota sem abrir cada transferência.

Políticas de sunrise e de não resposta

Quando uma transferência expira (confirmation_timeout_hours decorreu enquanto estava em AWAITING_COUNTERPARTY), o timeout_outcome decide o que acontece à sua transação. Duas definições permitem-lhe tratar duas causas comuns para um tempo limite excedido de forma diferente: Ambas aceitam HOLD, REJECT ou PROCEED, com o mesmo significado que para timeout_outcome, ou uma string vazia para seguir o timeout_outcome. Ambas estão vazias por predefinição, pelo que nada se altera até definir uma:
A primeira destas que se aplicar decide o resultado:
  1. sunrise_policy, quando estiver definida e a jurisdição da contraparte constar de sunrise_jurisdictions.
  2. non_responsive_policy, quando estiver definida e a contraparte for UNRESPONSIVE.
  3. timeout_outcome em todos os outros casos, incluindo uma transferência para um membro da rede Didit ou para uma contraparte sem entrada no diretório.
sunrise_jurisdictions é apenas de leitura e atualmente contém ["CO", "KH", "VN"]. Apenas estes países contam como estando num período de sunrise: qualquer outra jurisdição, bem como uma vazia ou desconhecida, segue o timeout_outcome, para que uma contraparte nunca receba a sua política de sunrise por acidente. A cronologia da transferência expirada indica o resultado aplicado, por exemplo sunrise_policy=PROCEED (counterparty jurisdiction CO does not enforce the Travel Rule yet). As suas regras continuam a ser executadas após a expiração, pelo que uma regra como a do TFR da UE tr_eu_expired_review ainda pode mover a transação para análise sob PROCEED.

Campos e predefinições de regras

Quatro campos de regra contêm o que a sua aplicação sabe sobre a contraparte que o intercâmbio de Travel Rule de uma transação alcançou: a sua entrada de diretório ou, no caso de um intercâmbio INTERNAL, o cliente da Didit que a recebeu. Cada campo fica vazio quando o intercâmbio não alcançou nenhuma contraparte conhecida. Cinco predefinições no pacote travel_rule atuam sobre eles. Instale-as a partir de Transactions → Rules → Library na Business Console ou com a API da biblioteca de regras: Todas as cinco aplicam-se apenas a transações da Travel Rule.

Webhooks

Subscreva um destino a travel_rule.status.updated para receber notificações em cada transição de estado de todas as transferências na sua aplicação, de saída e de entrada, incluindo os segmentos do rail INTERNAL. O encaminhamento é executado após o retorno da criação da transação, pelo que resultados como COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE, ou uma troca INTERNAL liquidada de imediato chegam até si através deste evento em vez de serem incluídos na resposta de criação.
O campo rail fica vazio até que um rail seja selecionado. Para uma transação, o Didit envia travel_rule.status.updated após transaction.created: quando o Didit cria a transação (o seu POST /v3/transactions/, um registo sunrise, um pedido TRP de entrada ou o segmento de entrada do rail INTERNAL), envia primeiro transaction.created. Cada evento é entregue e é feita uma nova tentativa de forma independente, pelo que um transaction.created que tenha necessitado de nova tentativa pode ainda chegar após um evento de estado: utilize transaction_id como chave no seu processador e leia a transação quando um evento de estado referenciar uma que ainda não tenha visto. Uma transferência enviada através da TRUST não recebe nenhum evento COMPLETED: a TRUST não devolve nada que o Didit possa ler, pelo que, a menos que o envio falhe ou que o cancele, o seu último evento é EXPIRED. Na GTR, VERIFYVASP e SYGNA, o evento segue a resposta que o Didit lê da rede. As aplicações sandbox também enviam este 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 da assinatura e a política de novas tentativas.

Preços

A taxa da Travel Rule é de $0.02 por troca de saída iniciada, cobrada uma vez aquando da criação da transação, independentemente de quantas transições de estado a troca atravesse posteriormente. Um resend nunca a cobra novamente.
  • Aplica-se a uma transação travelRule de saída numa aplicação com a Travel Rule ativada, cujo montante seja igual ou superior ao seu threshold_amount, para que o Didit inicie uma troca gerida para essa transação. Uma transferência para uma carteira autocustodiada, ou para a própria carteira verificada do seu utilizador, também conta: a prova de propriedade é a respetiva troca.
  • Todas as outras transações de saída que transportem dados da Travel Rule são faturadas como Triagem de transações padrão, que o seu plano inclui até ao respetivo limite mensal de transações e tem o preço de $0.001 para além desse limite: uma transferência abaixo do seu limiar, um pagamento Lightning ao qual a Travel Rule não se aplica e uma transferência registada passivamente enquanto a Travel Rule está desativada. Uma transação é faturada numa das duas linhas, nunca em ambas.
  • As transações travelRule de entrada não têm taxa da Travel Rule ou de monitorização: o segmento de entrada que o Didit cria na aplicação do beneficiário através do rail INTERNAL, pedidos TRP de entrada e registos após depósito.
  • Uma aplicação que tenha aderido gratuitamente à Travel Rule não paga nenhuma das taxas em transações travelRule de saída até ativar a faturação de saída com POST /v3/travel-rule/workspace/billing/; a receção permanece gratuita.
  • As aplicações sandbox nunca são cobradas.
  • A taxa da Travel Rule é de $0.02 e a Triagem de transações é de $0.001 para além do seu limite incluído. Cada transação é cobrada pelo preço da linha em que é faturada.
  • Se a triagem AML de cripto/carteiras também for executada na mesma transação (por exemplo, um depósito de entrada com currency_kind: "crypto" e monitorização ativada), isso é faturado separadamente à taxa padrão de Verificação e Triagem de Carteiras - não está incluído na taxa da Travel Rule.
  • A triagem de contrapartes é opcional e faturada separadamente, ao preço de Triagem AML de empresas por triagem; uma triagem com menos de 30 dias é reutilizada sem custos. Decisões, questionários e a avaliação de diligência devida do diretório não têm custos.

Preços de atribuição

A atribuição por análise de blockchain necessita de uma consulta de carteira junto do fornecedor de análise, e você obtém sempre o valor total dessa consulta:
  • A monitorização de 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 (aquela que a monitorização de cripto já efetuou). A atribuição não acrescenta custos.
  • A monitorização de cripto não foi executada - o Didit faz a chamada de análise necessária uma única vez e transmite o seu valor total: a transação é cobrada à taxa padrão de Verificação e Triagem de Carteiras ($0.15 com análise gerida pelo Didit) e recebe em troca o resultado completo da triagem de cripto - pontuação de risco, categoria de risco da carteira, instantâneo da rede - e não apenas o nome do VASP. O item de utilização é marcado com o acionador travel_rule_attribution para que a cobrança seja explicável.
  • Chave de análise própria - a mesma taxa de plataforma que se aplica à monitorização de cripto com a sua própria chave aplica-se aqui ($0.02 por chamada). O seu fornecedor fatura-lhe diretamente a consulta subjacente.
  • As consultas falhadas nunca são cobradas, os reenvios reutilizam a atribuição registada sem uma nova chamada ou cobrança, e as aplicações sandbox nunca são cobradas.
Portanto, uma transferência de saída que necessitou de atribuição custa $0.02 (Travel Rule) + uma cobrança de Verificação e Triagem de Carteiras - e quando ambos os produtos estão ativados, a chamada de análise e a respetiva cobrança ocorrem apenas uma vez.

Pacote de regras TFR da UE

Quatro regras pré-definidas são fornecidas no pacote travel_rule_eu_tfr, concebidas especificamente para as obrigações do TFR da UE. Tal como qualquer outro pacote pré-definido, ative-o a partir da Business Console em Transactions → Rules → Library. Estas regras são acionadas em todas as transições relevantes - na criação da transferência, na confirmação de propriedade, na resposta à recolha por e-mail e através do processo de limpeza de transferências expiradas - para que uma transferência que nunca seja concluída continue a surgir para revisão de conformidade em vez de ser liquidada silenciosamente.

Por que motivo funciona melhor numa única plataforma

A conformidade com a Travel Rule é um problema de identidade disfarçado de pagamentos - e a Didit já detém a identidade:
  • Dados verificados disponíveis. A pessoa associada a cada transferência está associada através de vendor_data ao perfil de KYC que a Didit verificou no onboarding (OCR de documentos, prova de vida, correspondência facial), para que possa construir originator_data a partir de campos verificados na mesma plataforma. Para um utilizador com uma verificação de KYC aprovada, a Didit transmite a identidade verificada em vez dos valores que introduziu (consulte Dados verificados e proveniência).
  • Biometria adicional para transferências de risco. Uma regra pode reter qualquer transferência de valor elevado até que o utilizador passe por uma nova verificação biométrica contra o rosto capturado no onboarding - a resposta mais forte possível à tomada de controlo de conta no momento do levantamento. Consulte o exemplo prático.
  • Um único grafo de dispositivos. As transferências submetidas através do SDK contêm os mesmos dados de inteligência sobre o dispositivo que as sessões de KYC, pelo que “novo dispositivo + montante elevado + beneficiário pela primeira vez” é uma única regra, e não uma junção no armazém de dados.
  • Triagem, regras, casos e a troca num único local. A triagem de carteiras que atribui o VASP da contraparte é a mesma triagem que as suas regras e analistas veem - uma cobrança, uma consola, um registo de auditoria.
  • Preços públicos. $0.02 por troca de saída, sem níveis de volume, sem chamadas de vendas.

FAQ

Como funciona a troca

A Didit executa a troca diretamente. Quando submete uma transferência travelRule, a Didit realiza a descoberta de contrapartes em tempo real, envia os dados do ordenante e do beneficiário para o VASP recetor nos canais que os transportam e marca a transferência como COMPLETED apenas quando a contraparte a confirmar - trata-se de um handshake gerido, não de um registo pós-liquidação. A resposta de uma contraparte é processada em todos os canais, exceto no TRUST, que apenas envia, pelo que uma transferência através dele expira em vez de ser concluída. No GTR, VERIFYVASP e SYGNA, a Didit lê a resposta a partir da resposta da rede ou consultando-a a cada 5 minutos, e nenhuma troca através destes foi ainda concluída contra uma rede em produção; no TRP, uma resposta que a contraparte não forneça de imediato requer o anfitrião público TRP da Didit, que ainda não está ativo (consulte Redes da Travel Rule). A Didit também mantém o registo completo e o estado de conformidade de cada troca (um ciclo de vida de 13 estados, webhooks e um registo de auditoria). Se preferir executar a Travel Rule através do seu próprio processo, a Didit pode, em alternativa, registar os dados passivamente como o seu sistema único de registo (consulte a pergunta sobre registo passivo abaixo). Ambos os modos estão disponíveis: a troca ativa é executada assim que definir is_enabled: true nas definições (está como false por predefinição) e, até lá, a Didit regista os dados de forma passiva.
É nativa. A Didit executa a sua própria implementação do Travel Rule Protocol (TRP), disponibilizada em trp.didit.me assim que esse anfitrião público estiver ativo (ainda não responde, pelo que as contrapartes não conseguem contactá-lo por TRP hoje), e implementa diretamente os protocolos de rede da indústria - GTR (Global Travel Rule), TRUST, VerifyVASP e Sygna Bridge (falado nativamente, incluindo o IVMS 101 encriptado com ECIES da Sygna e pedidos de permissão assinados). A Didit não é um revendedor de uma única camada de interoperabilidade de terceiros. Contactar uma contraparte que pertença a uma rede de adesão específica ocorre necessariamente através dessa rede - não existe um canal universal único na Travel Rule - mas a descoberta, o handshake, a verificação e a conservação de registos são todos executados pela Didit. Atualmente, cada canal de rede requer a sua própria adesão, e o TRUST apenas envia: consulte Visão geral.
Implementados nativamente, tentados por ordem estrita de prioridade: INTERNAL (ambos os VASP na Didit), TRP (OpenVASP Travel Rule Protocol), GTR, TRUST, VerifyVASP, Sygna Bridge e um recurso de contingência por EMAIL para contrapartes sem ferramentas. Os canais de rede requerem a sua própria adesão atualmente, o TRUST apenas envia e a receção através de uma rede ainda não está ativada: consulte Redes da Travel Rule. CODE, TRISA, Notabene e Veriscope surgem no Marketplace da Didit como mosaicos para solicitar acesso, ainda sem integração. Consulte Como a Didit encaminha uma troca para a tabela de encaminhamento completa e Redes da Travel Rule para saber o alcance atual de cada uma.
O TRP é a base que recomendamos: não requer qualquer adesão partilhada - partilhar o seu Travel Address permite que qualquer VASP compatível com TRP o contacte - e quando uma contraparte é conhecida apenas pelo endereço da carteira, a atribuição por análise de blockchain encaminha-a através de TRP apenas se a entrada correspondente no diretório já tiver um endpoint TRP. No envio, a Didit envia os ativos listados em Identificadores de ativos TRP através dele, e uma contraparte que não responda de imediato requer o anfitrião público TRP da Didit, que ainda não está ativo. Para redes de adesão, escolha em função do local onde as suas contrapartes operam: a GTR oferece uma cobertura global alargada, a TRUST está orientada para VASP dos EUA e a VerifyVASP (que agora também opera a Sygna Bridge) tem uma forte cobertura na Ásia. Sim, atualmente necessita da sua própria adesão: a Didit ainda não detém uma adesão de plataforma nestas redes e está em processo de integração como fornecedor. Ligue a sua adesão no Marketplace; não está limitado a uma única rede. Lembre-se de que o TRUST apenas envia, pelo que uma transferência através dele não fica concluída, e que nenhuma troca através de uma rede foi ainda concluída contra uma rede em produção.
Através de uma cadeia de resolução: outro cliente Didit que tenha comprovado o controlo da carteira (o canal INTERNAL), o seu próprio livro de endereços de carteiras para um Travel Address guardado, depois os canais de protocolo e de rede e, por fim, a atribuição por análise de blockchain. Se a transferência incluir apenas uma carteira de destino, a Didit resolve-a através de dados de análise de blockchain para atribuir a exchange ou serviço de custódia da contraparte e cataloga-a no diretório de VASP. A transferência é depois encaminhada automaticamente apenas se essa entrada do diretório já tiver uma rota, como um endpoint TRP; caso contrário, termina em COUNTERPARTY_VASP_NOT_FOUND com o nome da contraparte registado, e pode reenviar assim que existir uma rota, por exemplo após guardar o travel_address da contraparte na entrada do seu livro de endereços para essa carteira (para os ativos listados em Identificadores de ativos TRP).

Preços e licenciamento

A Travel Rule é um produto separado, baseado na utilização. Não está incluída na verificação de identidade. Custa **$0.02 por troca de saída iniciada** ([tabela de preços publicada](#preços), sem escalões de volume, sem chamadas comerciais). Quando o encaminhamento necessita de uma consulta de análise de blockchain para identificar o VASP da contraparte, essa consulta é cobrada uma vez à [taxa de atribuição](#preços-de-atribuição): a partir de $0.15 com gestão, ou $0.02 com uma chave de fornecedor existente. Não é faturada novamente se a monitorização de cripto já tiver analisado a mesma carteira. Uma transferência abaixo do seu limiar, ou uma registada enquanto a Travel Rule está desativada, é faturada como triagem de transações; as transferências recebidas, como os fluxos que a Didit cria no lado do beneficiário, não pagam a taxa da Travel Rule.
Não. Uma transação travelRule é faturada numa única linha: a taxa da Travel Rule ($0.02) quando inicia uma troca enviada; caso contrário, como triagem de transações padrão. A consulta de análise de blockchain é cobrada uma vez: se a monitorização de cripto já tiver analisado a carteira de destino na transação, a atribuição reutiliza esse resultado guardado sem custos adicionais. Os fluxos recebidos que a Didit cria no lado do beneficiário nunca são faturados com a taxa da Travel Rule.
Sim. O KYT e a monitorização de transações, triagem AML e de sanções, risco de carteira por análise de blockchain e as capacidades da Travel Rule da Didit estão todos documentados publicamente em docs.didit.me, e pode citar livremente estas páginas num processo regulatório. Para uma declaração formal de capacidades do produto adaptada a uma submissão específica - por exemplo, um pedido de licença VASP no âmbito da AIFC/AFSA, MiCA ou outro -, contacte a equipa responsável pela sua conta Didit com o formato exigido pelo seu regulador.

Operações e dados

Resolvem-se imediatamente para NOT_APPLICABLE: nenhum canal é utilizado e nenhum dado de identidade sai da Didit. A transação é faturada como Triagem de transações padrão, e não com a tarifa da Travel Rule. A Didit compara o limiar com o montante convertido para a moeda predefinida da sua aplicação. Se a Didit não conseguir converter o montante, o limiar não é aplicado e a transferência é trocada. O TFR da UE não tem valor mínimo, pelo que os CASP da UE devem manter threshold_amount em 0.00.
A transferência permanece em AWAITING_COUNTERPARTY até que confirmation_timeout_hours decorra, momento em que um processo de limpeza move-a para EXPIRED e aplica o seu timeout_outcome à transação subjacente - HOLD para revisão, REJECT para recusar ou PROCEED para a deixar inalterada. A regra predefinida tr_eu_expired_review apresenta adicionalmente cada expiração aos seus analistas. Uma contraparte que nunca chega a receber a mensagem é um caso diferente: a Didit tenta novamente e, após a sexta tentativa falhada, a transferência passa para COUNTERPARTY_VASP_NOT_REACHABLE (consulte Entrega e tentativas).
Sim - esse é o canal EMAIL. O respetivo contacto de conformidade recebe uma ligação de recolha de utilização única e pode confirmar ou recusar a troca a partir de uma página alojada sem conta Didit, sem chave de API e sem integração. Para depósitos que já tenham sido liquidados antes de qualquer troca ser possível, utilize o registo sunrise pós-depósito.
Declare o destino como autocustodiado (payment_method.method_type: "unhosted_wallet"). A Didit ignora o encaminhamento do VASP e, em alternativa, recolhe a prova de que o seu cliente controla a carteira - assinatura de mensagens, teste Satoshi, captura de ecrã ou autodeclaração - através do widget de propriedade da carteira. Essa é a obrigação de carteira autocustodiada do TFR da UE em formato de API.
Sim. Até que a propriedade da carteira seja confirmada do seu lado, os dados pessoais da contraparte numa transferência de entrada são mascarados, tanto no objeto da transferência como na parte da contraparte da transação (consulte Dados mascarados da contraparte). As páginas de recolha por e-mail mostram apenas o resumo da transferência (nome do VASP ordenante, montante, carteira de destino), nunca os payloads relativos às pessoas. As trocas através de canais são realizadas através de HTTPS, e os canais de rede (GTR, TRUST, VERIFYVASP, SYGNA) encriptam adicionalmente o payload IVMS com a chave pública do VASP destinatário.
Sim. Com a Travel Rule desativada, quaisquer travel_rule_details que submeta (incluindo um status fornecido pelo chamador, atual ou legado) são registados passivamente na transação - nenhum canal é acionado, nada é negociado. Utilize isto para preenchimento retroativo ou para executar o seu próprio processo mantendo um único sistema de registo.
Utilize uma aplicação sandbox com a Travel Rule ativada. O ambiente sandbox ignora regras, faturação e os webhooks transaction.created e transaction.status.updated, e cada troca de saída segue para o Didit Test VASP no canal TEST_VASP, que responde no interior da Didit com o cenário que selecionar: aceitar, recusar, divergência de nomes, não acessível, tempo limite excedido ou autocustodiada. 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 lhe envie uma transferência com Acionar transferência de entrada do Test VASP, ou registe uma com POST /v3/travel-rule/inbound/; ambas são avaliadas com base no seu livro de endereços de carteiras - ON_HOLD, UNCONFIRMED_OWNERSHIP, COUNTERPARTY_MISMATCHED_DATA, ou COMPLETED e depois FINISHED. Para uma troca entre duas partes com outra aplicação real, utilize duas das suas próprias aplicações de produção no canal INTERNAL: a que recebe tem de estar disponível para descoberta e provar o controlo da carteira de destino com uma mensagem assinada ou um depósito de teste.

Passos seguintes

Widget de propriedade da carteira

Comprove que um cliente controla uma carteira através de assinatura, teste Satoshi, captura de ecrã ou autodeclaração.

Interoperabilidade

Os endpoints destinados às contrapartes, que outros VASP utilizam para comunicar consigo: TRP, callbacks, recolha por e-mail, sunrise.

Redes

O alcance atual de cada canal e rede e o que ainda aguarda adesão.

Testar em sandbox

Teste todos os resultados com o Didit Test VASP antes de avançar para produção.

Submeter transações

Como incluir dados da Travel Rule no payload do Create Transaction.

Biblioteca de regras

O catálogo completo de regras predefinidas, incluindo o pacote da Travel Rule.

Webhooks

Subscreva travel_rule.status.updated e todas as outras famílias de eventos.

Guia da consola

Visualizar o estado da Travel Rule na vista de detalhe da transação.
Última modificação em 7 de novembro de 2026