Verificação Server-to-Server
Quando você já tem uma interface de captura — ou está verificando imagens coletadas anteriormente — envie-as diretamente e receba o resultado na própria resposta. Sem sessão, sem widget, sem link para o cliente.
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 com o mesmo resultado normalizado que o widget produz.
Idempotency-Key é obrigatório
Toda chamada deve carregar um cabeçalho Idempotency-Key. Uma requisição sem ele é rejeitada com 422.
Este endpoint executa a extração do documento, a revisão de autenticidade, a triagem de sanções e as checagens faciais de forma síncrona, então uma única chamada pode levar vários segundos. Tempo suficiente para que um timeout do cliente seja um evento comum, não exótico — e uma nova tentativa cega executaria tudo isso de novo, e cobraria você por isso.
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 o derive de algo que se repete, como apenas o userRef — duas verificações legítimas da mesma pessoa colidiriam, e a segunda retornaria o resultado da primeira.
| Situação | Resposta |
|---|---|
| Primeira chamada com uma chave | 201 com o resultado |
| Mesma chave, primeira chamada concluída | 201 com o resultado atual daquela verificação — não uma cópia congelada, então uma decisão de revisão posterior é refletida |
| Mesma chave, primeira chamada ainda em execução | 409 carregando o sessionId, para que você possa consultar GET /v1/sessions/{session_id} e obter o desfecho |
| Mesma chave, tenant diferente | Sem relação — as chaves têm escopo do seu tenant |
O 409 importa mais do que parece. Se a sua requisição sofreu timeout, você nunca recebeu um sessionId, então não tem como perguntar sobre o trabalho já em andamento. A resposta de conflito o devolve:
{
"detail": {
"code": "IDEMPOTENCY_KEY_IN_FLIGHT",
"message": "A request with this Idempotency-Key is still being processed. Poll GET /v1/sessions/{sessionId} for the outcome.",
"sessionId": "81e04c30-2620-42f1-a3e0-68aef1f84043"
}
}
Portanto o comportamento correto em um timeout é: repita a mesma chamada com a mesma chave. Você receberá o resultado ou um 409 dizendo onde olhar. Nunca repita com uma chave nova — isso inicia uma segunda verificação cobrada da mesma pessoa.
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 nova sessão; uma duplicata custa um link não utilizado, não uma verificação repetida.
Campos do Formulário
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
userRef | texto | Sim | Seu identificador para a pessoa sendo verificada |
frontImage | arquivo | Sim | Frente do documento — a página da foto de um passaporte, a frente de um cartão |
backImage | arquivo | Não | Verso do documento. Para carteiras de motorista e identidades estaduais dos EUA, contém o código de barras |
selfieImage | arquivo | Não | Omita para executar apenas as verificações de documento — veja Verificação apenas de documento |
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 |
Observe que aqui o 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
Envie o Verso do Cartão
Nas carteiras de motorista e identidades estaduais dos EUA, o verso contém um código de barras PDF417 que codifica os dados do titular. A Inyo o decodifica no recebimento e, como o código de barras é autoverificável — a simbologia carrega sua própria correção de erros — ele prevalece sobre o OCR da zona visual para os campos que contém. A decodificação é independente de rotação, portanto um verso de cabeça para baixo ainda é lido.
Um verso ausente, ilegível ou sem código de barras é um no-op silencioso: os valores do OCR permanecem e nenhuma verificação muda. Não há desvantagem em enviá-lo, e há um ganho mensurável de precisão quando ele é decodificado. Os passaportes trazem uma zona de leitura mecânica na página da foto, de modo que frontImage sozinho é suficiente para eles.
Verificação Apenas de Documento
Omita selfieImage para verificar o documento sem biometria. As verificações de documento são executadas — legibilidade, formato, validade, autenticidade, jurisdição — e nenhuma verificação facial aparece em checks[].
Uma consequência a considerar: uma verificação apenas de documento não possui pontuação biométrica. Se você tiver um limiar de revisão configurado, não há nada para ser comparado, e uma verificação não medida é tratada como não medida, não confiável — portanto é encaminhada para in_review em vez de ser aprovada automaticamente. Envie uma selfie, ou deixe o limiar de revisão sem configurar, se precisar que verificações apenas de documento sejam decididas de forma síncrona.
in_review Não É uma Resposta Final
POST /v1/verifications retorna o resultado de forma síncrona, mas uma resposta 201 não garante uma decisão terminal. O status pode ser in_review, o que significa que um analista ainda vai decidir.
Isso acontece quando você configurou um limiar de revisão, ou quando rejeições retidas estão habilitadas e as verificações rejeitaram o documento. Sem nenhuma das duas configurações, toda verificação retorna decidida.
Quando isso acontece:
| Canal | Comportamento |
|---|---|
| Webhook | Com um webhookUrl configurado, o resultado decidido é enviado via POST como qualquer outro resultado — veja Notificações de resultado |
| Polling | GET /v1/sessions/{sessionId} retorna o status e o result atuais, atualizados no próprio recurso, com result.manualReview indicando quem decidiu e por quê |
Use o sessionId do corpo da resposta como identificador para ambos. Nenhum webhook é enviado para a resposta síncrona original — o 201 já a entregou. Veja Revisão Manual para o quadro completo.
Respostas de Erro
| Status | Causa | Como tratar |
|---|---|---|
401 / 403 | Token ausente ou inválido, ou token sem o scope verifications | Veja Autenticação |
422 | prefill não é um JSON válido ou viola o schema de prefill (incluindo o formato do número de documento) | Corrija o payload — o detail indica o problema |
422 | dataCheck=true sem prefill | Forneça um payload de prefill para comparação |
502 | O serviço de verificação estava indisponível | Transitório — tente novamente. Trata-se de falha de infraestrutura, não de uma recusa. Não trate como um resultado negativo para o cliente |
Widget ou Server-to-Server?
Os dois pontos de entrada compartilham o mesmo pipeline e o mesmo formato de resultado, e seus limiares, roteamento de revisão, jurisdições aceitas e opções de enriquecimento se aplicam de forma idêntica. Duas configurações são, por natureza, de nível de sessão e não têm efeito aqui: os tipos de documento permitidos e o travamento de prefill.documentType restringem o que o widget oferece ao cliente, portanto, neste endpoint, o tipo de documento é simplesmente o que as imagens revelarem ser.
As diferenças que importam:
| Widget hospedado | Server-to-server | |
|---|---|---|
| Qualidade da captura | Guiada, com enquadramento ao vivo e feedback de reflexo | Sob seu controle |
| Captura com falha | O cliente é orientado e tenta novamente | Retorna um resultado; tentar novamente é decisão sua |
| Entrega do resultado | Webhook ou redirecionamento assinado | O corpo da resposta, mais alterações posteriores via webhook |
| Defesa contra ataques de apresentação | Mesmas verificações | Mesmas verificações, mas sem contexto de captura ao vivo para se apoiar |
| Evidência de conformidade | A Inyo retém a captura guiada e o vídeo opcional da selfie | Apenas as imagens que você envia |
A diferença de retentativa diz respeito a orientar um cliente ao vivo — ela não muda o que sua configuração significa nem como a decisão é tomada.
Próximos Passos
- Verificações e Decisões — o payload de resultado completo
- Revisão Manual — tratamento de
in_review - Recebendo Resultados — notificações via webhook para alterações posteriores
