Inyo

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.

CanalComo
WebhookCom um webhookUrl configurado para a sua conta, o resultado é enviado por POST quando a verificação atinge um estado terminal — veja Recebendo Resultados
LeituraGET /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"
}
CampoDescrição
statuspending, completed, failed ou errored — a posição no ciclo de vida, nunca um veredito. O desfecho, quando existe, é result.decision
resultO 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çãoResposta
Primeira chamada com uma chave201 com um sessionId novo
Mesma chave, mesma requisição201 com o mesmo sessionId, em qualquer estado em que o trabalho esteja. Nada é iniciado duas vezes
Mesma chave, imagens ou pessoa diferentes422 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/sessions não aceita Idempotency-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

CampoTipoObrigatórioDescrição
userReftextoSimSeu identificador para a pessoa verificada
frontImagearquivoSimFrente do documento — a página de foto de um passaporte, a frente de um cartão
backImagearquivoNãoVerso do documento. Em carteiras e IDs estaduais dos EUA é onde fica o código de barras
selfieImagearquivoNãoOmita para rodar apenas as verificações documentais — veja Verificação apenas documental
dataChecktextoNãotrue compara os dados extraídos com o prefill
prefilltextoNãoUma 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:

StatusSignificadoO que fazer
failedA captura nunca foi utilizável — no widget, o cliente esgotou as tentativasA pessoa tenta de novo
erroredUma falha do nosso lado interrompeu a avaliaçãoVocê repete a chamada, com uma Idempotency-Key nova

Você nunca precisa ler as linhas de checks para distinguir os dois.


Respostas de Erro

StatusCausaComo tratar
401 / 403Token ausente ou inválido, ou um token sem o scope verificationsVeja Autenticação
404Nenhuma verificação sua carrega esse id — incluindo o id de uma sessão de widgetLeia uma sessão de widget em GET /v1/sessions/{sessionId}
422prefill 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
422dataCheck=true sem prefillForneça um payload de prefill para comparar
422errorCode: "IDEMPOTENCY_KEY_REUSED" — a chave já foi usada para uma requisição diferenteUse uma chave nova
502Não conseguimos aceitar a verificaçãoTransitório — repita com a mesma chave. Nada foi decidido sobre o seu cliente
503Verificações demais já em andamentoTransitó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 hospedadoServer-to-server
Qualidade da capturaGuiada, com enquadramento ao vivo e retorno sobre reflexosSob o seu controle
Captura reprovadaO cliente é orientado e tenta de novoTermina em failed; repetir é decisão sua
Entrega do resultadoWebhook ou redirecionamento assinadoWebhook quando configurado, e a leitura de qualquer forma
Leitura do registroGET /v1/sessions/{sessionId}GET /v1/verifications/{verificationId}
Defesa contra ataques de apresentaçãoAs mesmas verificaçõesAs mesmas verificações, mas sem contexto de captura ao vivo para apoiá-las
Evidência de complianceA Inyo retém a captura guiada e o vídeo de selfie opcionalApenas 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