Skip to main content
Ao final deste guia o fluxo abre dentro do seu app iOS, com câmera e microfone liberados e os eventos chegando ao seu código Swift. A SDK não cria a verificação. Ela renderiza uma que já existe, a partir do embed URL que o seu backend recebe em entry.url ao chamar criar verificação.

Pré-requisitos

  • Xcode 26 ou superior. A interface de módulo Swift é compatível só para frente: o piso é a versão que compilou o release, então Xcode mais antigo não compila.
  • iOS 17 ou superior, como deployment target.
  • Um embed URL emitido pelo seu backend, como em emitir a credencial.
  • O .xcframework da versão que você vai usar. Peça ao suporte qual versão indicar.
A chave de API (lz_...) nunca vai para o app. Ela fica no seu servidor. O app recebe apenas o embed URL, que vale para uma verificação e expira.

Confira o exemplo

Os arquivos desta integração, com o destino de cada um.

Configure o projeto

1

Embuta o .xcframework

A SDK é distribuída como .xcframework fechado. Não há SPM nem CocoaPods.Cada versão fica num caminho fixo e imutável, com o SHA-256 ao lado:
Confira a integridade antes de embutir:
Conferir o SHA-256
No Xcode, vá ao target do app em General → Frameworks, Libraries, and Embedded Content, clique em +, escolha Add Other → Add Files… e selecione o .xcframework. Confirme que o Embed está como Embed & Sign.
2

Declare as três permissões

A verificação usa câmera para o documento e a selfie, microfone para a prova de vida e localização para antifraude. O seu app, não a SDK, declara as três chaves. Sem elas o processo é encerrado quando o widget tenta acessar o hardware.
Info.plist
Se o target usa GENERATE_INFOPLIST_FILE = YES e não tem Info.plist físico, declare as mesmas chaves como build settings, com o prefixo INFOPLIST_KEY_.Escreva o texto para o titular, não para a App Review. É ele que aparece no alerta.
3

Valide o embed URL

LegitimuzEmbedURL.parse(_:) aceita https:// ou http://localhost — é o que o WebKit exige para liberar câmera e microfone.
VerificationFlow.swift
Este passo é opcional: o init da sessão valida de novo e lança LegitimuzEmbedURL.ValidationError. Ele existe para dar o retorno ao titular mais cedo.
4

Crie a sessão

VerificationFlow.swift
Por padrão a SDK pede câmera, microfone e localização assim que a tela aparece: os três alertas do sistema saem em sequência, antes de a página carregar. Se o seu app já pede essas permissões numa tela anterior, desligue:
Pedir as permissões por conta própria
5

Apresente a verificação

LegitimuzVerificationView não tem NavigationStack nem toolbar próprios. Você decide como apresentá-la: sheet, fullScreenCover ou push.
VerificationScreen.swift
6

Observe os eventos e o desfecho

session.events é um AsyncStream. session.outcome() suspende até a verificação chegar a um estado terminal.
VerificationFlow.swift
O @unknown default não é opcional. A SDK é compilada com library evolution, então os enums públicos são resilientes e o switch não compila sem ele. Vale para LegitimuzVerificationOutcome, LegitimuzEventType, LegitimuzURLOpenReason, LegitimuzCompleteResult.Status e LegitimuzEmbedURL.ValidationError. A exceção é JSONValue, que é @frozen.

Confira que funcionou

O fluxo abre na primeira etapa e o console registra session.started. No dashboard, a verificação sai de not_opened e passa a started.

Eventos

Não intercepte terms.open nem redirect.open: a LegitimuzVerificationView já apresenta essas URLs num Safari embutido. event.payload é um JSONValue?, um envelope JSON genérico para as etapas que emitem dados extras:
Ler o payload
Não decida nada a partir de .completed. isSuccessfulSubmission confirma que o titular enviou os dados, não que a verificação foi aprovada. O desfecho chega ao seu backend por verification.decided, onde o titular não pode interferir.

Tratamento de erros

LegitimuzEmbedURL.ValidationError, devolvido por parse(_:). O errorDescription já vem em pt-BR, pronto para exibir.
LegitimuzPublicError chega em session.outcome() como .failed(error).Exiba sempre displayMessage: ele já resolve a prioridade entre userMessage, message e o texto genérico.Só erro com recoverable == false encerra a sessão. Erro recuperável aparece em session.events como session.error e o fluxo continua. O catálogo de códigos está em tratamento de erros.
.loadFailed(message) é problema de rede, DNS ou TLS ao abrir o embed URL, não erro da verificação. A própria view já mostra a tela de “Não foi possível abrir a verificação” com botão de tentar de novo.outcome() pode ser chamado de novo depois disso, por causa desse retry.

Casos de borda

No iOS a negativa é definitiva dentro do app: só os Ajustes resolvem. Explique por que a câmera é necessária e leve o titular para lá.
Abrir os Ajustes
O embed URL vale até o expires_at da verificação. Expirado, peça um novo ao seu backend e crie outra sessão. Não reaproveite o antigo.

Próximo passo

Android

O mesmo fluxo em Java.

Receber a decisão

Onde o desfecho realmente chega.