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_requireddo tipowallet_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çãoverification_sessionobrigató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 comPOST /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/.
Envio a partir do dispositivo
Os SDKs fazem umPOST /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:
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: opaymentMethod.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_verificationestá ativado nas suas configurações da Travel Rule (o padrão), uma sessão do widget de propriedade da carteira é criada automaticamente e retornada emaction_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 paraCOUNTERPARTY_MISMATCHED_DATAquando o nome não corresponde ao titular registrado no catálogo de endereços da carteira.
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.externalUserIddo payload é ignorado e substituído pelovendor_datado 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.
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.
/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 blocoaction_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 paraSFSafariViewController/ 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.
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.
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
Quandoaction_required.type for verification_session, leia o bloco em result.actionRequired e entregue-o à sua integração de verificação da Didit já existente:
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.SDK web
submitTransaction já está disponível no singleton do SDK web:
{ 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.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 comPOST /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, etravel_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_requiredvolta a sernullapós a resolução, estatus/travel_rule.statustrazem o resultado.
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.