Riv.IA EYE API

Verificación visual de identidad por API REST. Un único endpoint ejecuta cualquier combinación de checks sobre la misma imagen, autenticado con Bearer Token.

Producción
https://api.riv.ia.br
Dev
https://dev.riv.ia.br

Cómo usar la API

Todos los endpoints exigen un Bearer Token. Genera el token primero e inclúyelo en el header de cada petición.

  1. 1

    Generar token

    Autentícate con client_id y client_secret para recibir el Bearer Token.

  2. 2

    Enviar imagen

    Haz POST en /eye/v1/verify con la imagen y los checks deseados.

  3. 3

    Recibir veredicto

    Respuesta JSON explicable con el veredicto agregado approved.

¿Necesitas credenciales? Para obtener tu client_id y client_secret, escríbenos al email contato@riviadev.com.br.

Autenticación

Usa tus credenciales para generar un Bearer Token de corta duración. Inclúyelo en el header Authorization: Bearer <token> en todas las llamadas siguientes.

POST/auth/v1/tokens/generate

Cambia tus credenciales por un Bearer Token de acceso.

Body (application/json)

client_idstringobligatorio
Identificador del cliente proporcionado por RiviaDev.
client_secretstringobligatorio
Secreto del cliente. Guárdalo bien — nunca lo expongas en código del lado del cliente.
Petición
curl -X POST https://api.riv.ia.br/auth/v1/tokens/generate \
  -H "Content-Type: application/json" \
  -d '{"client_id":"SEU_CLIENT_ID","client_secret":"SEU_CLIENT_SECRET"}'
Respuesta200 OK
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Endpoint /verify

Punto de entrada único para la verificación visual. Combina los checks que necesites en checks — el veredicto approved es la conjunción de todos los checks solicitados.

POST/eye/v1/verify

Headers

Authorizationstringobligatorio
Bearer Token obtenido en /auth/v1/tokens/generate. Formato: Bearer <token>.

Body (multipart/form-data)

checksstringobligatorio
Lista de checks a ejecutar, separados por comas: liveness, face_match, authenticity, element_detection, text_extraction, qr_code, document_extraction.
selfiefile
Imagen a verificar: el selfie de la persona o, en qr_code, la foto con el código QR. Formatos: JPG, JPEG, PNG, GIF, BMP, WEBP, DNG (máx. 10MB). Obligatorio con todos los checks, salvo cuando solo se pide document_extraction.
documentfile
Imagen del documento. Obligatorio con face_match y document_extraction. En document_extraction acepta también PDF de 1 página.
detection_requeststring (JSON)
JSON con los elementos a detectar. Obligatorio con element_detection.
extraction_requeststring (JSON)
JSON con los campos de texto a leer. Obligatorio con text_extraction; opcional con qr_code, donde habilita el fallback a OCR.

Respuesta

Cada check solicitado vuelve como un objeto con su propio nombre; los no solicitados vuelven como null. El esquema de cada objeto está en la sección del check.

successboolean
Indica si la llamada se procesó correctamente.
approvedboolean
Veredicto agregado: true cuando todos los checks solicitados pasaron.
checksstring[]
Lista de los checks realmente ejecutados, en orden.
<check>object | null
Resultado de cada check solicitado. null para los no solicitados.
messagestring | null
Mensaje complementario legible sobre el resultado.

Los textos legibles de la respuesta (message, details, reasons, resúmenes) se devuelven en portugués, como en los ejemplos.

Varios checks en una llamada

Combina los checks en la misma petición — se ejecutan en paralelo.

Petición
curl -X POST https://api.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "selfie=@selfie.jpg" \
  -F "document=@rg.jpg" \
  -F 'detection_request={"elements":[{"type":"object","description":"crachá","required":true}]}' \
  -F "checks=liveness,face_match,authenticity,element_detection"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["liveness", "face_match", "authenticity", "element_detection"],
  "liveness": { "resultado": true, "confidence": 0.93, ... },
  "face_match": { "same_person": true, "confidence": 0.88, ... },
  "authenticity": { "is_authentic": true, "confidence": 0.9, ... },
  "element_detection": { "all_required_found": true, ... },
  "message": "Verificação aprovada"
}

Checks

liveness

Prueba de vida

Verifica si la imagen es un selfie real de una persona viva — no una foto de pantalla, impresa o generada por IA.

Enviar: checks=liveness + selfie

Objeto liveness

resultadoboolean
true cuando la imagen es un selfie real de un ser humano. Es lo que entra en approved.
person_presentboolean | null
Si hay una persona física en la imagen.
confidencefloat | null
Confianza del veredicto.
detalhesstring[]
Motivos del rechazo. Vacío cuando se aprueba.
authenticityobject | null
Veredicto antisuplantación calculado en la misma inferencia. Mismo esquema que el check authenticity.

Comportamiento

  • Pedir liveness junto con authenticity consume una única inferencia: el resultado antisuplantación se reutiliza.

Selfie real de una persona viva.

Petición
curl -X POST https://api.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "selfie=@selfie.jpg" \
  -F "checks=liveness"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["liveness"],
  "liveness": {
    "resultado": true,
    "person_present": true,
    "confidence": 0.93,
    "detalhes": [],
    "authenticity": { "is_authentic": true, ... }
  },
  "message": "Verificação aprovada"
}
face_match

Comparación facial

Compara el rostro del selfie con la foto del documento e indica si son la misma persona.

Enviar: checks=face_match + selfie + document

Objeto face_match

same_personboolean
true cuando el selfie y el documento son de la misma persona.
confidencefloat
Confianza de la comparación, de 0 a 1.
detailsstring[]
Detalles estructurales del análisis (ojos, nariz, contorno).

Comportamiento

  • Sin document la API responde 422.

Selfie y documento de la misma persona.

Petición
curl -X POST https://api.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "selfie=@selfie.jpg" \
  -F "document=@rg.jpg" \
  -F "checks=face_match"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["face_match"],
  "face_match": {
    "same_person": true,
    "confidence": 0.88,
    "details": ["Estrutura facial compatível."]
  },
  "message": "Verificação aprovada"
}
authenticity

Autenticidad / antisuplantación

Detecta foto de pantalla, foto impresa o imagen generada por IA. Funciona con cualquier imagen, con persona u objeto.

Enviar: checks=authenticity + selfie

Objeto authenticity

is_authenticboolean
true cuando la imagen no es una suplantación.
is_screen_photoboolean
Foto de pantalla o monitor.
is_printed_photoboolean
Foto de material impreso.
is_ai_generatedboolean
Imagen generada por IA.
confidencefloat
Confianza del veredicto.
signalsstring[]
Señales estructurales observadas (ej.: moiré, rejilla de píxeles, borde del monitor).
reasonsstring[]
Justificación legible del veredicto.

Comportamiento

  • Los reflejos y brillos por sí solos nunca clasifican la imagen como foto de pantalla: hacen falta al menos 2 artefactos estructurales.

Sin evidencia de suplantación.

Petición
curl -X POST https://api.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "selfie=@selfie.jpg" \
  -F "checks=authenticity"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["authenticity"],
  "authenticity": {
    "is_authentic": true,
    "is_screen_photo": false,
    "is_printed_photo": false,
    "is_ai_generated": false,
    "confidence": 0.9,
    "signals": [],
    "reasons": ["Sem evidência de spoof."]
  },
  "message": "Verificação aprovada"
}
element_detection

Detección de elementos

Verifica si los elementos esperados están en la imagen: ropa, accesorios, objetos, textos, logos, colores o personas.

Enviar: checks=element_detection + selfie + detection_request

detection_requeststring (JSON)obligatorio
Hasta 5 elementos. type: clothing, accessory, object, text, logo, color_scheme o person. expected_count (1–10) es opcional, útil para personas. Ej.: {"elements":[{"type":"object","description":"crachá","required":true}]}.

Objeto element_detection

all_required_foundboolean
true cuando se encontraron todos los elementos obligatorios.
detection_summarystring
Resumen legible del análisis.
detected_elementsobject[]
Resultado de cada elemento solicitado. Esquema abajo.
blocked_by_authenticityboolean
true cuando la lista vino vacía porque la imagen no superó el filtro antisuplantación, y no por un fallo en la detección.

Cada ítem de detected_elements

typestring
Tipo del elemento solicitado.
descriptionstring
Descripción del elemento solicitado.
foundboolean
Si se encontró el elemento.
confidencefloat
Confianza de la detección.
detailsstring
Detalles sobre la detección o la ausencia.
quantity_foundinteger | null
Cantidad encontrada, cuando se envió expected_count.

Comportamiento

  • Sin detection_request la API responde 422.
  • La detección pasa por el filtro antisuplantación aunque no se pida authenticity.

Credencial obligatoria encontrada.

Petición
curl -X POST https://api.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "selfie=@selfie.jpg" \
  -F 'detection_request={"elements":[{"type":"object","description":"crachá","required":true}]}' \
  -F "checks=element_detection"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["element_detection"],
  "element_detection": {
    "all_required_found": true,
    "detection_summary": "Crachá detectado na imagem.",
    "detected_elements": [{
      "type": "object",
      "description": "crachá",
      "found": true,
      "confidence": 0.92,
      "details": "Crachá visível no peito.",
      "quantity_found": null
    }],
    "blocked_by_authenticity": false
  },
  "message": "Verificação aprovada"
}
text_extraction

Extracción de texto

Lee campos de texto concretos de la imagen, como un código impreso en una etiqueta, con validación de formato opcional.

Enviar: checks=text_extraction + selfie + extraction_request

extraction_requeststring (JSON)obligatorio
Hasta 5 campos. expected_format es una regex RE2 opcional (full match; sin backreference ni lookaround). Ej.: {"fields":[{"name":"codigo_bag","description":"código impresso abaixo do QR","expected_format":"^[A-Z]{3}[0-9]{5}$","required":true}]}.

Objeto text_extraction

all_required_foundboolean
true cuando se leyeron y validaron todos los campos obligatorios.
extraction_summarystring
Resumen legible de la extracción.
extracted_fieldsobject[]
Resultado de cada campo solicitado. Esquema abajo.
blocked_by_authenticityboolean
true cuando la lista vino vacía porque la imagen no superó el filtro antisuplantación, y no por un fallo en la lectura.

Cada ítem de extracted_fields

namestring
Nombre del campo solicitado.
valuestring | null
Texto leído. null cuando no se leyó.
foundboolean
Si el valor se leyó y, si hay formato, se validó.
confidencefloat
Confianza de la lectura.
matches_formatboolean | null
Si el valor coincidió con el expected_format. null cuando no hay formato.
detailsstring
Detalles sobre la lectura o la ausencia.

Comportamiento

  • Sin extraction_request, o con JSON inválido, la API responde 422.
  • La lectura pasa por el filtro antisuplantación aunque no se pida authenticity.

Campo leído y validado por el formato.

Petición
curl -X POST https://api.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "selfie=@bag.jpg" \
  -F 'extraction_request={"fields":[{"name":"codigo_bag","description":"código impresso abaixo do QR","expected_format":"^[A-Z]{3}[0-9]{5}$","required":true}]}' \
  -F "checks=text_extraction"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["text_extraction"],
  "text_extraction": {
    "all_required_found": true,
    "extraction_summary": "Código lido abaixo do QR.",
    "extracted_fields": [{
      "name": "codigo_bag",
      "value": "ABC12345",
      "found": true,
      "confidence": 0.95,
      "matches_format": true,
      "details": "Código impresso legível."
    }],
    "blocked_by_authenticity": false
  },
  "message": "Verificação aprovada"
}
qr_code

Lectura de código QR

Lee el código QR de la foto. Con extraction_request, lee el código impreso cuando el QR falta, está ilegible o vacío.

Enviar: checks=qr_code + selfie (+ extraction_request opcional)

Objeto qr_code

foundboolean
true cuando se leyó un valor y, si hay expected_format, coincidió con él.
valuestring | null
Texto leído del QR o por OCR. null cuando no hay una lectura válida.
source"qr" | "ocr" | null
Origen del valor.
status"read" | "ocr_fallback" | "not_found"
read: leído del QR. ocr_fallback: leído por OCR porque no había un QR legible. not_found: no se leyó nada válido.
confidencefloat | null
Confianza de la lectura. 1.0 en el camino QR — el decode se valida con Reed-Solomon, así que o sale el valor grabado o no sale nada. En el fallback, la confianza del campo leído por el OCR. null cuando no se leyó nada.
matches_formatboolean | null
Si el valor coincidió con el expected_format. null cuando no hay formato. Un QR leído que no coincide con el formato devuelve not_found con matches_format=false, sin activar el OCR.
qr_countinteger
Cantidad de códigos QR con texto detectados en la foto. Con más de uno, gana el de mayor área.
detailsstring
Motivo legible de la lectura (ej.: QR sin texto, timeout en la decodificación, DNG leído directamente por OCR). Texto libre: no lo uses en lógica.
blocked_by_authenticityboolean
true cuando la imagen no superó el filtro antisuplantación (foto de pantalla, impresa o generada por IA). En ese caso found=false, value=null y status=not_found.

Comportamiento

  • approved exige código leído e imagen auténtica — la lectura pasa por el filtro antisuplantación aunque no se pida authenticity.
  • No leer nada es 200 con approved=false y status=not_found, no 400.
  • Los archivos DNG van directo al OCR, así que solo se leen con extraction_request.

Con varios QR, gana el de mayor área. Sin extraction_request no hay fallback.

Petición
curl -X POST https://api.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "selfie=@bag.jpg" \
  -F "checks=qr_code"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["qr_code"],
  "qr_code": {
    "found": true,
    "value": "ABC12345",
    "source": "qr",
    "status": "read",
    "confidence": 1.0,
    "matches_format": null,
    "qr_count": 2,
    "details": "QR code lido",
    "blocked_by_authenticity": false
  },
  "message": "Verificação aprovada"
}
document_extractiondev

Extracción de documento

Identifica si la imagen es un documento y, si es un RG o una CNH brasileños, devuelve los campos extraídos con confianza por campo.

Enviar: checks=document_extraction + document (sin selfie)

documentfileobligatorio
Imagen JPEG, PNG o WebP, o PDF de 1 página (ej.: CNH digital exportada de la app Carteira Digital de Trânsito), hasta 10MB. Una cara por llamada — anverso o reverso; la CNH digital trae las dos en la misma página.

Objeto document_extraction

type"rg" | "cnh" | "not_a_document" | "unsupported_document" | "unreadable_document"
rg y cnh aprueban. not_a_document, unsupported_document (ej.: pasaporte, CRLV, diploma) y unreadable_document rechazan: approved=false, fields=null y message explica el motivo.
model"legacy" | "cin" | "physical" | "digital" | null
Modelo del documento: legacy o cin para RG, physical o digital para CNH. null cuando no se determina.
side"front" | "back" | "both" | null
Cara enviada: front, back o both. null cuando no se determina.
classification_confidencefloat
Confianza de la clasificación del tipo de documento.
fieldsobject | null
Campos extraídos, cada uno como {value, confidence}. Todas las claves del tipo vienen siempre; un campo ilegible viene como {value: null, confidence: 0} — nunca un valor inventado, así que tú decides qué va a revisión humana. null en los tipos de rechazo.
messagestring | null
Motivo del rechazo. null cuando el documento es RG o CNH.

Campos por tipo

rgtype = "rg"
numero_rg, orgao_expedidor, uf_expedidor, data_expedicao, nome, data_nascimento, filiacao_1, filiacao_2, naturalidade, cpf.
cnhtype = "cnh"
numero_registro, nome, data_nascimento, filiacao_1, filiacao_2, cpf, doc_identidade_numero, doc_identidade_orgao, doc_identidade_uf, categoria, data_primeira_habilitacao, data_emissao, validade, local_emissao, observacoes.
valuestring | null
Fechas en YYYY-MM-DD. CPF en formato 000.000.000-00, validado por el dígito verificador. Nombres sin tildes y en mayúsculas. Filiación en el orden impreso, sin distinguir padre y madre.

Comportamiento

  • Un rechazo también es 200, con approved=false.
  • Combinable: liveness,face_match,document_extraction hace el KYC completo en una llamada — entonces selfie vuelve a ser obligatorio.
  • No hay retención: la imagen y los campos extraídos no se almacenan ni se registran en logs.
  • Sin document la API responde 422; un PDF de más de 1 página responde 400.

Reverso de un RG. Un campo ilegible viene con value null y confidence 0.Disponible solo en el entorno dev mientras está en validación; aún no está en producción.

Petición
curl -X POST https://dev.riv.ia.br/eye/v1/verify \
  -H "Authorization: Bearer $RIVIA_KEY" \
  -F "document=@rg_verso.jpg" \
  -F "checks=document_extraction"
Respuesta200 OK
{
  "success": true,
  "approved": true,
  "checks": ["document_extraction"],
  "document_extraction": {
    "type": "rg",
    "model": "legacy",
    "side": "back",
    "classification_confidence": 0.96,
    "fields": {
      "numero_rg": { "value": "12.345.678-9", "confidence": 0.95 },
      "orgao_expedidor": { "value": "SSP", "confidence": 0.94 },
      "uf_expedidor": { "value": "SP", "confidence": 0.96 },
      "data_expedicao": { "value": "2015-03-12", "confidence": 0.93 },
      "nome": { "value": "MARIA DA SILVA", "confidence": 0.97 },
      "data_nascimento": { "value": "1990-07-04", "confidence": 0.96 },
      "filiacao_1": { "value": "JOSE DA SILVA", "confidence": 0.92 },
      "filiacao_2": { "value": null, "confidence": 0.0 },
      "naturalidade": { "value": "SAO PAULO-SP", "confidence": 0.9 },
      "cpf": { "value": "123.456.789-09", "confidence": 0.95 }
    },
    "message": null
  },
  "message": "Verificação aprovada"
}

Códigos de estado

200OK
Verificación procesada. Un rechazo de negocio también es 200 con approved=false.
400Bad Request
Parámetros inválidos, archivo en un formato no aceptado, de más de 10MB o dañado (la imagen no se puede abrir). En document_extraction, también PDF de más de 1 página.
401Unauthorized
Bearer Token ausente, inválido o caducado.
422Validation Error
Payload válido sintácticamente pero semánticamente incorrecto: falta el archivo o el JSON que exige el check, o el JSON es inválido.
500Internal Server Error
Fallo interno. Inténtalo de nuevo; si persiste, contacta con soporte.
503Service Unavailabledev
Proveedor de IA temporalmente no disponible en document_extraction. Inténtalo de nuevo en unos instantes.

Notas de comportamiento

  • checks es una lista (CSV) de lo que quieres ejecutar. Solo los checks pedidos vuelven rellenos; el resto vuelve como null.
  • approved es el AND lógico de los checks solicitados.
  • Los checks se ejecutan en paralelo sobre la misma imagen.
  • Formatos de imagen aceptados: JPG, JPEG, PNG, GIF, BMP, WEBP, DNG (máx. 10MB cada uno).

¿Listo para integrar?

Habla con nuestro equipo para recibir credenciales de sandbox y empezar tu integración con Riv.IA EYE.