Solo V3
Esta validación no existe en las sesiones creadas con la V2.
Las credenciales para votar modelo G/H (2019 en adelante) incluyen dos códigos QR en el reverso, firmados digitalmente por el INE, que guardan los mismos datos que el frente de la credencial —CURP, nombre, vigencia— y una fotografía del titular en baja resolución.
La validación de QR lee esos códigos, verifica su firma digital y coteja lo que dicen contra el resto del documento: el CURP y el nombre extraídos por OCR del anverso, y el rostro capturado durante la video-identificación. Es una comprobación adicional para detectar una credencial alterada: alguien pudo modificar el anverso (foto, nombre, CURP) dejando intacto el reverso original, o viceversa.
Envía qr_validation: true en el cuerpo de la solicitud al crear la sesión:
{ "validations": ["INE", "CURP"], "qr_validation": true}curl -X POST https://api.verificamex.com/identity/v3/identity/sessions \ -H "Authorization: Bearer {TU_TOKEN}" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{ "validations": ["INE", "CURP"], "qr_validation": true }'Solo el modelo G/H trae los dos códigos QR en el reverso. Las credenciales modelo DEF (anteriores a esa generación) no los incluyen — no hay nada que leer.
Cuando esto ocurre, el campo qr_not_applicable viene en true dentro del resultado, y la sesión no
se penaliza por ello: es una comprobación que no aplica a ese documento, no un fallo.
Tampoco se penaliza cuando el QR sí existe pero no se pudo leer bien (foto borrosa, mala iluminación, reflejo): eso no es evidencia de fraude, así que no baja el resultado. Solo cuenta cuando el QR se leyó con éxito y sus datos no coinciden con el resto del documento — ver Cómo afecta el resultado.
Tanto el detalle de la sesión como el
webhook incluyen el campo qr_validation. Es null si la sesión
no pidió esta validación.
| Campo | Tipo | Descripción |
|---|---|---|
| attempted | Boolean | Siempre true cuando la sesión pidió qr_validation. |
| ok | Boolean | true si los códigos QR se leyeron y decodificaron correctamente. |
| qr_not_applicable | Boolean | true si la credencial es modelo DEF y no trae los 2 QR del reverso. |
| stage | String | Etapa alcanzada por el proceso de lectura ("done" cuando terminó sin problema). |
| error | String | Motivo de la falla de lectura, o null si no hubo. |
| modelo | String | Formato de cifrado detectado en el QR ("G/H"). |
| signature_checked | Boolean | Si se verificó la firma digital del QR. |
| signature_valid | Boolean | Si la firma digital es válida. |
| fields | Object | Datos decodificados del QR: curp, nombres, primer_apellido, segundo_apellido, cic, vigencia, sexo, numero_emision, fecha, entre otros. |
| data_match | Object | Cotejo del QR contra el OCR del anverso — ver abajo. |
| face_match | Object | Cotejo del rostro embebido en el QR contra el rostro capturado — ver abajo. |
data_match trae una llave por cada dato cotejado (curp, nombre). Cada una es un objeto
{ qr, ocr, match } con el valor leído del QR, el valor leído por OCR, y si coinciden. Si no hubo datos
suficientes para comparar un campo, esa llave no aparece —no es lo mismo que un match: false—.
face_match es { compared, confidence, matched, threshold }. Si el QR no traía fotografía o no se
detectó rostro en el anverso, compared es false y no se hizo la comparación —tampoco es un fallo—.
threshold es la similitud mínima con la que se calificó: el qr_face_match_threshold que enviaste al
crear la sesión, u 80 por defecto. Ver Umbrales de biometría.
qr_validation solo pesa en el result final (y en el arreglo errors) cuando el QR se pudo leer
con éxito y sí aplica a esa credencial. En ese caso, un dato que no coincida es una señal real de
fraude —alguien pegó un QR ajeno, válido en sí mismo, sobre una credencial distinta— y pesa igual que un
fallo de MRZ o de biometría: el resultado de la sesión pasa a 0.
qr_validation, no aplica a la credencial, o el QR no se pudo leer — no afecta el
resultado en ningún sentido.errors y el result de la sesión pasa a 0, sin importar que Lista Nominal/RENAPO/biometría hayan
pasado.Cuando el QR sí hace fallar la sesión, errors trae una entrada por cada comprobación que no pasó, con
esta forma:
{ "Key": "QR-KYC-001", "Name": "CURP del QR contra OCR", "Category": "KycQrValidation", "Result": false, "Output": "qr=HEHJ050803HDFRRHA9 ocr=CURL041004HVZRSNA3", "Message": "El CURP leído del QR no coincide con el OCR"}| Key | Motivo |
|---|---|
| QR-KYC-001 | El CURP leído del QR no coincide con el OCR del anverso. |
| QR-KYC-002 | El nombre leído del QR no coincide con el OCR del anverso. |
| QR-KYC-003 | El rostro embebido en el QR no coincide con el rostro capturado. |
{ "attempted": true, "ok": true, "stage": "done", "error": null, "modelo": "G/H", "qr_not_applicable": false, "signature_checked": true, "signature_valid": true, "fields": { "curp": "GALJ900101HDFRRN05", "nombres": "JUAN CARLOS", "primer_apellido": "GARCIA", "segundo_apellido": "LOPEZ", "vigencia": "2019-2029" }, "data_match": { "curp": { "qr": "GALJ900101HDFRRN05", "ocr": "GALJ900101HDFRRN05", "match": true }, "nombre": { "qr": "JUAN CARLOS GARCIA LOPEZ", "ocr": "GARCIA LOPEZ JUAN CARLOS", "match": true } }, "face_match": { "compared": true, "confidence": 99.87, "matched": true, "threshold": 80 }}{ "attempted": true, "ok": true, "stage": "done", "error": null, "modelo": "G/H", "qr_not_applicable": false, "signature_checked": true, "signature_valid": true, "fields": { "curp": "HEHJ050803HDFRRHA9", "nombres": "JOHANN EBLEM", "primer_apellido": "HERNANDEZ", "segundo_apellido": "HERRERIAS", "vigencia": "2024-2034" }, "data_match": { "curp": { "qr": "HEHJ050803HDFRRHA9", "ocr": "CURL041004HVZRSNA3", "match": false }, "nombre": { "qr": "JOHANN EBLEM HERNANDEZ HERRERIAS", "ocr": "CRUZ ROSAS LEONARDO DANIEL", "match": false } }, "face_match": { "compared": true, "confidence": 0.0, "matched": false, "threshold": 80 }}En este caso la sesión termina con "result": 0 y errors trae las tres entradas
QR-KYC-001, QR-KYC-002 y QR-KYC-003.
{ "attempted": true, "ok": false, "stage": null, "error": null, "modelo": null, "qr_not_applicable": true, "signature_checked": false, "signature_valid": false, "fields": {}, "data_match": {}, "face_match": { "compared": false, "confidence": 0.0, "matched": false, "threshold": 80 }}La credencial es modelo DEF: no hay QR que leer. errors no incluye ninguna entrada de QR y el
resultado depende solo del resto de las validaciones.
Solo V3
Esta validación no existe en las sesiones creadas con la V2.
Solo pagas si se lee
5 tokens extra con INE y CURP (10 sin ambas), solo cuando el QR se pudo leer.
No todo INE aplica
Solo credenciales modelo G/H (2019+) traen los 2 QR del reverso.
Solo penaliza fraude real
Un QR ilegible no baja el resultado; un QR leído que no coincide, sí.