Pular para o conteúdo principal
Os SDKs da Didit podem enviar transações monitoradas diretamente do dispositivo do usuário final, incluindo transferências sujeitas à Travel Rule e triagem de cripto. Seu backend emite um token de curta duração e escopo restrito, e o SDK cuida do resto. Ele anexa a inteligência de dispositivo automaticamente e, quando uma transferência sujeita à Travel Rule exige prova de controle da carteira, inicia esse fluxo automaticamente na hora. Uma sessão de verificação obrigatória nunca é iniciada automaticamente: ela é retornada na resposta para que seu app a inicie com a sua própria integração de verificação da Didit. Veja Ações obrigatórias do usuário abaixo.

Visão geral

O envio pelo cliente se apoia em três garantias:
  • Vinculação do titular à prova de falsificação. No momento da emissão, o token fica restrito a um único vendor_data (o ID do seu usuário). A identidade do titular de cada transação enviada com ele é imposta no servidor a partir dessa vinculação. Assim, um cliente adulterado não consegue enviar em nome de outro usuário, e o payload nunca precisa carregar credenciais.
  • Inteligência de dispositivo automática. O SDK coleta uma impressão digital do dispositivo e a envia junto com a transação, e a Didit obtém o endereço IP e o user agent no servidor. O contexto de dispositivo combinado é anexado ao titular da transação sem biblioteca extra, sem token de dispositivo separado e sem nenhuma integração adicional do seu lado. Ele alimenta regras baseadas em dispositivo e a correlação por dispositivo entre sessões e transações.
  • Prova de propriedade da carteira iniciada automaticamente. Quando a transação criada exige que o usuário final prove o controle de uma carteira, a resposta traz um bloco action_required do tipo wallet_ownership. O SDK abre esse fluxo imediatamente e atualiza a transação quando ele termina, sem que você precise criar loops de polling ou a entrega de links. Uma ação verification_session obrigatória é diferente: ela nunca é iniciada automaticamente e volta no mesmo bloco para que seu app a inicie com sua própria integração de verificação da Didit.
O POST /v3/transactions/ no servidor continua sendo a escolha certa quando não há um usuário final presente: transferências de back-office, importações em lote ou eventos reportados pelos seus próprios sistemas. Os dois caminhos criam os mesmos registros de transação, executam as mesmas regras e emitem os mesmos webhooks.

Fluxo

1

Emita um token de transação

Seu backend chama POST /v3/transactions/sdk-token/ com a sua chave de API e o vendor_data do usuário, e entrega o sdk_token retornado ao seu app.
2

Envie pelo dispositivo

O app chama submitTransaction no SDK, que envia o payload para POST /v1/transactions/ com o cabeçalho X-Transaction-Token e o enriquecimento automático de dados do dispositivo.
3

Trate qualquer ação obrigatória

Se action_required.type for wallet_ownership, o SDK inicia o widget automaticamente e depois atualiza a transação via GET /v1/transactions/{transaction_id}/. Se for verification_session, o SDK não inicia nada: leia action_required e inicie seu próprio fluxo de verificação com o session_token (ou a url, na web).

Emissão de um token de transação

Emita tokens a partir do seu backend com POST /v3/transactions/sdk-token/, usando a mesma autenticação por chave de API dos demais endpoints de transação /v3/.
Aliases em camelCase (vendorData, ttlSeconds, maxUses) também são aceitos, como no restante da API /v3/.
Nunca inclua sua chave de API em um app. A chave de API fica no seu backend e emite os tokens; apenas o sdk_token de curta duração vai para o dispositivo. Emita um token novo por sessão de usuário em vez de reutilizar tokens de longa duração, e mantenha max_uses limitado quando o número de envios esperados for conhecido.

Envio a partir do dispositivo

Os SDKs fazem um POST /v1/transactions/ com o token no cabeçalho X-Transaction-Token. O payload enviado usa camelCase. Os métodos submitTransaction o montam para você, então você só precisa lidar com ele diretamente ao chamar o endpoint a partir do seu próprio cliente HTTP:
Cada campo de nível superior corresponde ao seu equivalente em POST /v3/transactions/: A resposta traz o mesmo detalhe da transação em snake_case dos endpoints /v3/, além do bloco action_required:

Como declarar uma carteira autocustodiada

O exemplo acima declara o destino como a carteira autocustodiada do próprio usuário: o paymentMethod.type da contraparte é unhosted_wallet. Essa declaração muda a forma como a troca da Travel Rule acontece:
  • A Didit ignora totalmente o roteamento para o VASP da contraparte, já que não há VASP por trás de uma carteira autocustodiada, e cria a transferência diretamente em UNCONFIRMED_OWNERSHIP.
  • Quando auto_wallet_verification está ativado nas suas configurações da Travel Rule (o padrão), uma sessão do widget de propriedade da carteira é criada automaticamente e retornada em action_required, exatamente como na resposta acima.
  • O SDK abre o widget automaticamente. Assim que o usuário comprova o controle da carteira, a transferência executa a verificação de nome e avança para COMPLETED, ou para COUNTERPARTY_MISMATCHED_DATA quando o nome não corresponde ao titular registrado no catálogo de endereços da carteira.
Sem a declaração, a Didit tenta os canais em ordem e só recorre ao fluxo de propriedade se nenhum VASP da contraparte for encontrado. Declare a carteira sempre que o seu produto já souber que o destino do saque é a carteira do próprio usuário. Isso evita a tentativa de roteamento que falharia e leva o usuário imediatamente ao fluxo de comprovação.

Controle do titular

Três coisas são sempre definidas pelo token, nunca pelo payload:
  • A aplicação na qual a transação é criada.
  • A identidade do titular: o subject.externalUserId do payload é ignorado e substituído pelo vendor_data do token.
  • O contexto do dispositivo do titular (veja abaixo). Os campos derivados pelo servidor prevalecem em caso de conflito com qualquer dado enviado em subject.device.
Um 401 deste endpoint significa que o token foi rejeitado: ausente, desconhecido, revogado, acima do seu max_uses ou expirado. As respostas de token expirado sempre contêm a palavra expired no detalhe do erro. É assim que os SDKs distinguem erros expired_token de erros invalid_token.

Como consultar a transação novamente

GET /v1/transactions/{transaction_id}/ retorna o mesmo detalhe com a mesma autenticação X-Transaction-Token. Os SDKs o chamam automaticamente depois que um fluxo de ação iniciado é concluído ou que sua janela é fechada, de modo que o estado final nunca depende de um único evento ou notificação. Você também pode usá-lo para verificar novamente status e action_required a qualquer momento enquanto o token for válido. No seu backend, GET /v3/transactions/{transaction_id}/ retorna o mesmo registro.

Inteligência de dispositivo automática

Todo envio inclui inteligência de dispositivo sem nenhum trabalho de integração da sua parte:
  • O SDK coleta uma impressão digital do dispositivo que preserva a privacidade (o esquema didit-fp-v2: sinais da plataforma e do navegador, um ID persistente do dispositivo, uma pontuação de bot e um hash composto) e a envia com a requisição.
  • A Didit obtém o endereço IP, o user agent e o accept-language no servidor, a partir da própria conexão, de modo que eles não podem ser falsificados pelo payload.
O resultado combinado é normalizado no contexto de dispositivo do participante titular e inserido ou atualizado no grafo de dispositivos, que também é alimentado pelas sessões de KYC. Isso permite correlacionar transações por dispositivo em toda a sua base de usuários (“relacionadas por dispositivo”), alimenta regras e o enriquecimento de IP com sinais de dispositivo e de rede, e aparece no detalhe da transação no Console. As transações /v3/ enviadas pelo servidor podem continuar passando objetos device_context explícitos por participante. Ao usar o SDK, você recebe uma versão mais robusta dos mesmos dados sem nenhum esforço adicional.

Ações exigidas do usuário

Algumas transações exigem que o usuário final faça algo antes de serem liquidadas: uma regra pode exigir uma sessão de verificação, ou uma transferência sujeita à Travel Rule pode exigir a comprovação de que a carteira de destino pertence de fato ao usuário. Os dois casos aparecem no mesmo lugar, o bloco action_required da resposta do envio (e de toda leitura posterior da transação):
Se os dois tipos puderem se aplicar à mesma transação, wallet_ownership tem prioridade, porque a falta da comprovação de propriedade bloqueia a própria troca de dados da Travel Rule. action_required passa a ser null assim que a ação pendente é resolvida. O campo remediation existente é mantido para compatibilidade com versões anteriores; action_required é o bloco canônico.

Contrato de abertura automática

autoLaunchAction (padrão true) abre automaticamente apenas a ação wallet_ownership:
  • Web: aberta no modal sobreposto do próprio SDK, com a conclusão detectada por mensagens com validação de origem mais uma consulta periódica limitada da transação (nunca dependendo de um único evento).
  • iOS / Android (e os wrappers React Native e Flutter, que delegam aos SDKs nativos): apresentada como a experiência nativa de propriedade de carteira do SDK (SwiftUI / Jetpack Compose) quando useNativeWalletOwnership é true (o padrão), com fallback para SFSafariViewController / uma Chrome Custom Tab e, por último, para o navegador padrão. Depois que o fluxo é fechado ou a aplicação volta ao primeiro plano, o SDK consulta novamente a transação automaticamente.
Uma ação verification_session nunca é aberta automaticamente: ela sempre retorna em action_required para que sua aplicação a inicie com a sua própria integração de verificação da Didit.
O widget de propriedade de carteira nunca deve ser renderizado dentro de uma webview móvel incorporada: os deep links de carteira não conseguem sair dela e o fluxo de comprovação fica sem saída. Os SDKs já usam a interface de navegador correta ao abrir automaticamente; mantenha essa regra se você mesmo tratar a url. Consulte o guia do widget de propriedade de carteira para mais detalhes.
Depois que o fluxo de propriedade de carteira aberto automaticamente pelo SDK é concluído ou fechado, o SDK consulta novamente a transação e entrega o resultado atualizado ao seu callback onActionCompleted. Uma ação verification_session não faz parte desse ciclo, já que é a sua aplicação que a inicia. Veja a próxima seção.

Iniciando uma sessão de verificação

Quando action_required.type for verification_session, leia o bloco em result.actionRequired e entregue-o à sua integração de verificação da Didit já existente:
Quando seu fluxo de verificação terminar, chame GET /v1/transactions/{transaction_id}/ (ou aguarde o webhook de transação) para obter o status atualizado da transação.

Exemplo: biometria adicional para um saque de alto valor

Este é o uso ideal desse fluxo: condicionar transações de risco (valores altos, novos beneficiários, novos dispositivos) a uma nova checagem biométrica da mesma pessoa que você verificou no onboarding. Uma tomada de controle de conta se parece exatamente com isto: senha correta, código 2FA correto (obtido por phishing ou SIM swap) e um saque para uma carteira que você nunca viu. Nesse ponto, todas as defesas baseadas em credenciais já falharam. A verificação facial não: o invasor não consegue passar por uma selfie com prova de vida que precisa corresponder ao rosto capturado durante o onboarding KYC do titular legítimo.
1

Crie a regra uma única vez, no console

Transactions → Rules → Create Rule: condição amount gte 5000, ação Change status → AWAITING_USER, e selecione seu fluxo de Biometric Authentication na ação. Adicione as outras condições de risco que quiser (contraparte nova, nova impressão digital do dispositivo, mudança de país do IP) como condições ou regras adicionais.
2

Envie o saque normalmente

Nada muda no seu código de envio. Quando a regra é acionada, a resposta retorna com status: "AWAITING_USER" e um bloco action_required do tipo verification_session:
3

Inicie a nova checagem

Entregue o session_token (ou a url) à sua integração de verificação da Didit já existente, exatamente como em Iniciando uma sessão de verificação. Como a sessão é criada para o mesmo vendor_data do titular da transação, a Didit já tem o rosto de referência verificado do usuário desde o onboarding: a selfie aprovada na prova de vida, a foto do chip do passaporte ou o retrato do documento. O usuário tira uma única selfie ao vivo; a Didit executa a prova de vida mais uma correspondência facial 1:1 com essa referência armazenada. Sem nova leitura de documento, sem refazer o onboarding: alguns segundos de fricção, apenas nas transações que merecem.
4

Liquide conforme o resultado

Quando a sessão é concluída, a transação é reavaliada automaticamente: APPROVED se a nova checagem foi aprovada, DECLINED se falhou, com um webhook transaction.status.updated em ambos os casos (reason: remediation_completed na linha do tempo da transação). Sua aplicação obtém o resultado por callbacks semelhantes a onActionCompleted, por GET /v1/transactions/{transaction_id}/ ou pelo webhook.
Isso funciona porque o onboarding de KYC, a reverificação biométrica e a decisão sobre a transação rodam em uma única plataforma: o rosto capturado no onboarding serve de referência para a verificação adicional, o grafo de dispositivos vincula a sessão à transação e o motor de regras une tudo isso. Não há integração entre fornecedores, nem exportação de imagens faciais, nem contrato separado de biometria. A reverificação é cobrada como um recurso padrão de Autenticação biométrica ($0.10) somente quando de fato é executada.

SDK web

submitTransaction já está disponível no singleton do SDK web:
O resultado é { transactionId, status, travelRuleStatus?, actionRequired? }. No payload do SDK, você informa category, details e customProperties, e o SDK os mapeia para os aliases usados na transmissão (type, info, props) por você. Os erros são tipados por meio de DiditTransactionError:

SDKs nativos

A API nativa submitTransaction é distribuída com os SDKs de iOS e Android 4.1.0 (e com as versões de React Native e Flutter que fixam essa versão). Ao contrário do SDK web, os payloads nativos usam diretamente os nomes de campo usados na transmissão: type, info e props.
Todos os SDKs também expõem getTransaction(transactionToken, transactionId) para consultar novamente a transação com o mesmo token. Os SDKs fazem essa chamada por você depois de um fluxo de ação iniciado, e você também pode chamá-la a qualquer momento. No mobile, o transporte da impressão digital do dispositivo já é aplicado a todas as chamadas de rede dos SDKs, então os envios de transações levam automaticamente a mesma inteligência de dispositivo.

Sem os SDKs

Tudo o que os SDKs fazem é HTTPS simples, e nada aqui exige o uso deles. Há dois formatos de integração equivalentes: Somente no servidor (sem nenhum token). Envie com POST /v3/transactions/ a partir do seu backend usando sua chave de API. A resposta (e cada GET /v3/transactions/{transaction_id}/ subsequente) traz o mesmo bloco action_required. Você também pode passar um contexto device explícito por participante, já que não há SDK para coletá-lo por você. No cliente, com sua própria pilha HTTP. Gere um token com POST /v3/transactions/sdk-token/ e depois chame POST /v1/transactions/ e GET /v1/transactions/{transaction_id}/ a partir do dispositivo com o cabeçalho X-Transaction-Token. Aplicam-se a mesma vinculação ao titular e a mesma derivação de IP/user-agent no servidor. Em seguida, trate action_required você mesmo: E detecte a conclusão sem nenhum callback no cliente:
  • Webhooks (recomendado). transaction.status.updated é disparado quando a ação pendente conclui a transação, e travel_rule.status.updated é disparado a cada transição de intercâmbio. Ambos trazem informações suficientes para atualizar seus registros sem polling.
  • Polling. Releia a transação (/v3/ a partir do seu backend ou /v1/ com o token enquanto ele for válido): action_required volta a ser null após a resolução, e status / travel_rule.status trazem o resultado.
Não há dependências de uso único neste design: o widget, a sessão de verificação e o seu backend convergem para o mesmo estado durável da transação, então uma aba fechada ou um webhook perdido sempre pode ser recuperado relendo a transação.

Webhooks

Seu backend não depende de um retorno do app. Quando uma transação enviada exige uma ação do usuário, o webhook de transação, transaction.created ou transaction.status.updated, inclui o mesmo bloco action_required, para que seus sistemas saibam da ação pendente mesmo se o app for fechado antes de o fluxo terminar. Uma ação verification_session vem com o status AWAITING_USER, mas uma ação wallet_ownership não altera o status da transação por si só, então leia action_required em vez do status. As transições da Travel Rule também emitem travel_rule.status.updated.

Próximos passos

Envio de transações

A API Create Transaction do lado do servidor e a referência completa do payload.

Travel Rule

A troca gerenciada entre remetente e beneficiário, as configurações e o ciclo de vida.

Widget de propriedade de carteira

O fluxo hospedado de comprovação de controle por trás das ações wallet_ownership.

Webhooks

transaction.created, transaction.status.updated e verificação de assinatura.

Regras

Ações de regras, incluindo as que criam sessões de verificação.

Status

O que AWAITING_USER significa no ciclo de vida da transação.
Última modificação em 1 de novembro de 2026