Verificação Server-to-Server
Quando você já tem uma interface de captura — ou está verificando imagens coletadas anteriormente — envie-as diretamente. Sem sessão, sem widget, sem link para o cliente.
A chamada aceita a verificação e responde com o identificador dela. A avaliação roda por trás da resposta.
Criar uma Verificação
Endpoint: POST /v1/verifications
Autenticação: token Bearer com o scope verifications
Content-Type: multipart/form-data
curl --request POST \
--url https://{FQDN}/v1/verifications \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "Idempotency-Key: $(uuidgen)" \
--form userRef=user-123 \
--form [email protected] \
--form [email protected] \
--form [email protected]
Retorna 201:
{
"sessionId": "81e04c30-2620-42f1-a3e0-68aef1f84043",
"status": "pending"
}
Esse é o corpo inteiro. Não há resultado nele — a extração do documento, a revisão de autenticidade, a triagem de sanções e as verificações faciais rodam todas depois que você é respondido. Guarde o sessionId: é com ele que você lê o resultado e reconhece o webhook quando chegar.
Obtendo o Resultado
Dois canais, e você pode usar os dois.
| Canal | Como |
|---|---|
| Webhook | Com um webhookUrl configurado para a sua conta, o resultado é enviado por POST quando a verificação atinge um estado terminal — veja Recebendo Resultados |
| Leitura | GET /v1/verifications/{verificationId} devolve o estado atual, para confirmar ou recuperar um desfecho |
Uma verificação é aceita independentemente de você ter um destino registrado — ela roda, conclui e o desfecho fica recuperável de qualquer forma. Um destino de webhook é combinado com o seu contato na Inyo, não definido pela API, então este endpoint não tem como informar se existe um. Registre um: um laço de consulta apertado não é o uso pretendido da leitura.
Recuperar uma Verificação
Endpoint: GET /v1/verifications/{verificationId}
Autenticação: token Bearer com o scope verifications
curl --request GET \
--url https://{FQDN}/v1/verifications/$VERIFICATION_ID \
--header "Authorization: Bearer $ACCESS_TOKEN"
{
"sessionId": "81e04c30-2620-42f1-a3e0-68aef1f84043",
"userRef": "user-123",
"status": "completed",
"step": "done",
"result": { "…": "o resultado normalizado, atualizado no lugar" },
"createdAt": "2026-09-14T14:02:11.481Z",
"updatedAt": "2026-09-14T14:02:58.902Z"
}
| Campo | Descrição |
|---|---|
status | pending, completed, failed ou errored — a posição no ciclo de vida, nunca um veredito. O desfecho, quando existe, é result.decision |
result | O resultado normalizado completo assim que a avaliação termina, null antes disso. Atualizado no lugar quando um analista decide |
Este caminho serve apenas as suas verificações. O identificador de uma sessão de widget retorna 404 aqui, e o identificador de uma verificação retorna 404 em GET /v1/sessions/{sessionId} — cada porta lê no seu próprio caminho, com o scope que aquela porta emite.
O registro de uma verificação não carrega deliveryMode. Numa sessão de widget esse campo distingue um push de um redirecionamento no navegador; uma verificação não tem nenhum dos dois, e informar webhook nela soaria como a promessa de que existe um destino — o que é a sua configuração a saber, não algo que cabe a nós afirmar.
Idempotency-Key é obrigatório
Toda chamada precisa carregar o header Idempotency-Key. Uma requisição sem ele é recusada com 422.
Uma avaliação é trabalho real — a extração, a revisão de autenticidade, a triagem e as verificações faciais rodam todas contra provedores externos. Se uma resposta se perder no caminho e você tentar de novo às cegas, é a chave que impede cada uma delas de rodar uma segunda vez e deixar você com dois registros de verificação para uma pessoa.
Use um valor que o seu próprio código consiga reproduzir para a mesma verificação lógica: um UUID que você gera e armazena, ou um identificador do seu sistema. Não derive de algo que se repete, como o userRef sozinho — duas verificações legítimas da mesma pessoa colidiriam, e a segunda devolveria o identificador da primeira.
| Situação | Resposta |
|---|---|
| Primeira chamada com uma chave | 201 com um sessionId novo |
| Mesma chave, mesma requisição | 201 com o mesmo sessionId, em qualquer estado em que o trabalho esteja. Nada é iniciado duas vezes |
| Mesma chave, imagens ou pessoa diferentes | 422 IDEMPOTENCY_KEY_REUSED. Repetir devolveria a verificação de outra pessoa, então a recusa é deliberada |
Uma repetição não distingue mais trabalho em andamento de trabalho concluído, porque não precisa: a primeira resposta já lhe deu o identificador, então uma nova tentativa não tem mais nada a dizer que você não tenha. Leia o status se quiser saber onde ela chegou.
POST /v1/sessionsnão aceitaIdempotency-Key. Sua resposta contém um link de widget de uso único que não pode ser reemitido, então uma nova tentativa ali cria uma sessão nova; uma duplicata custa um link não usado, não uma verificação repetida.
Quando uma chave nova é o caminho certo
Repetir com a mesma chave é o que você quer para uma resposta perdida ou falha — é gratuito e devolve o identificador que você não recebeu.
Gere uma chave nova em um caso: a verificação terminou em errored. Isso é uma falha de plataforma do nosso lado, não uma decisão sobre o seu cliente. A chave antiga está permanentemente gasta nela e continuará devolvendo esse desfecho, então uma chave nova é o que roda uma verificação nova da mesma pessoa.
Fora disso, uma chave nova inicia uma segunda verificação de alguém que você já verificou.
Campos do Formulário
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
userRef | texto | Sim | Seu identificador para a pessoa verificada |
frontImage | arquivo | Sim | Frente do documento — a página de foto de um passaporte, a frente de um cartão |
backImage | arquivo | Não | Verso do documento. Em carteiras e IDs estaduais dos EUA é onde fica o código de barras |
selfieImage | arquivo | Não | Omita para rodar apenas as verificações documentais — veja Verificação apenas documental |
dataCheck | texto | Não | true compara os dados extraídos com o prefill |
prefill | texto | Não | Uma string JSON com o mesmo schema do prefill de sessão |
Note que aqui prefill é uma string JSON dentro de um campo multipart, não um objeto aninhado:
--form 'prefill={"firstName":"Ana","lastName":"Silva","dateOfBirth":"1988-03-04"}' \
--form dataCheck=true
Todos os campos são lidos antes de você ser respondido, então um prefill malformado continua sendo um 422 na própria chamada, e não algo que você descobre depois.
Envie o Verso do Cartão
Em carteiras de motorista e IDs estaduais dos EUA, o verso carrega um código de barras PDF417 com os dados do portador. A Inyo o decodifica ao receber e, como o código de barras é autoverificável — a simbologia carrega a própria correção de erros —, ele tem precedência sobre o OCR da zona visual para os campos que contém. A decodificação independe da rotação, então um verso de cabeça para baixo ainda é lido.
Os valores de OCR prevalecem quando o verso não decodifica, então não há desvantagem em enviá-lo e há ganho mensurável de precisão quando ele decodifica. Um verso ilegível publica document_barcode_valid como not_evaluated com motivo no_barcode, o que não custa nada; um verso com um código de barras que não é um registro de identidade o publica como failed. Passaportes carregam uma zona legível por máquina na página de foto, então frontImage sozinho basta para eles.
Verificação Apenas Documental
Omita selfieImage para verificar o documento sem biometria. As verificações documentais rodam — legibilidade, formato, validade, autenticidade, jurisdição — e nenhuma verificação facial aparece em checks[].
Uma consequência a planejar: uma verificação apenas documental não carrega nenhuma evidência biométrica e é decidida somente pelas verificações do documento. Se o seu modelo de risco precisa do rosto comparado ao documento, envie uma selfie.
in_review Não É uma Resposta Final
Sob decisionamento gerenciado, decision pode ser in_review, significando que um analista ainda vai decidir. status é completed de qualquer forma — é a posição no ciclo de vida, não um veredito.
Quais faixas de score vão para revisão é definido para a sua conta, então trate inconclusive e in_review também neste ponto de entrada.
O desfecho da própria avaliação e a decisão posterior do analista chegam até você do mesmo jeito: um webhook se você tiver um destino, e a leitura de qualquer forma. Não existe mais uma primeira resposta que chega de um jeito diferente das seguintes. Veja Revisão Manual para o quadro completo.
Quando a Plataforma Falha
Uma verificação cuja avaliação não consegue rodar termina em errored. Ela carrega as verificações que concluíram antes da falha, não publica decision e não chega a nenhum revisor — não há nada sobre o que agir.
errored é distinto de failed, e a diferença é quem tenta de novo:
| Status | Significado | O que fazer |
|---|---|---|
failed | A captura nunca foi utilizável — no widget, o cliente esgotou as tentativas | A pessoa tenta de novo |
errored | Uma falha do nosso lado interrompeu a avaliação | Você repete a chamada, com uma Idempotency-Key nova |
Você nunca precisa ler as linhas de checks para distinguir os dois.
Respostas de Erro
| Status | Causa | Como tratar |
|---|---|---|
401 / 403 | Token ausente ou inválido, ou um token sem o scope verifications | Veja Autenticação |
404 | Nenhuma verificação sua carrega esse id — incluindo o id de uma sessão de widget | Leia uma sessão de widget em GET /v1/sessions/{sessionId} |
422 | prefill não é JSON válido ou viola o schema de prefill (incluindo o formato do número do documento) | Corrija o payload — errors[] nomeia cada campo e o motivo da recusa |
422 | dataCheck=true sem prefill | Forneça um payload de prefill para comparar |
422 | errorCode: "IDEMPOTENCY_KEY_REUSED" — a chave já foi usada para uma requisição diferente | Use uma chave nova |
502 | Não conseguimos aceitar a verificação | Transitório — repita com a mesma chave. Nada foi decidido sobre o seu cliente |
503 | Verificações demais já em andamento | Transitório — repita com a mesma Idempotency-Key. Nada foi iniciado, então a chave continua livre e a nova tentativa não é uma segunda verificação. Espere antes o número de segundos do header Retry-After |
Uma avaliação que falha depois de você ter sido respondido não produz uma resposta de erro — você já tem um 201. Ela termina a verificação em errored, o que você vê na leitura ou no webhook.
Widget ou Server-to-Server?
Os dois pontos de entrada compartilham o mesmo pipeline e o mesmo formato de resultado, e os seus limiares, roteamento de revisão, jurisdições aceitas e opções de enriquecimento se aplicam de forma idêntica. Os tipos de documento permitidos são, por natureza, de nível de sessão e não têm efeito aqui — eles restringem o que o widget oferece ao cliente. prefill.documentType tem efeito: é o tipo contra o qual document_type_match julga as imagens, então declarar um e enviar outro documento reprova essa verificação. Omita-o e a verificação publica not_evaluated, e o tipo do documento passa a ser o que as imagens indicarem, sem nada comparando.
As diferenças que importam:
| Widget hospedado | Server-to-server | |
|---|---|---|
| Qualidade da captura | Guiada, com enquadramento ao vivo e retorno sobre reflexos | Sob o seu controle |
| Captura reprovada | O cliente é orientado e tenta de novo | Termina em failed; repetir é decisão sua |
| Entrega do resultado | Webhook ou redirecionamento assinado | Webhook quando configurado, e a leitura de qualquer forma |
| Leitura do registro | GET /v1/sessions/{sessionId} | GET /v1/verifications/{verificationId} |
| Defesa contra ataques de apresentação | As mesmas verificações | As mesmas verificações, mas sem contexto de captura ao vivo para apoiá-las |
| Evidência de compliance | A Inyo retém a captura guiada e o vídeo de selfie opcional | Apenas as imagens que você enviar |
A diferença de repetição é sobre orientar um cliente ao vivo — ela não muda o que a sua configuração significa nem como a decisão é tomada.
Próximos Passos
- Verificações e Decisões — o payload de resultado por completo
- Revisão Manual — tratando uma decisão
in_review - Recebendo Resultados — notificações por webhook
