Solo en la V2
/v2/validations/basic — no disponible en la V1 (síncrona ni asíncrona) ni en las validaciones ligeras.
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 de la selfie (si la enviaste). 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 a la V2:
{ "ine_front": "data:image/png;base64,iVBORw0KGgoAAAANS....", "ine_back": "data:image/png;base64,iVBORw0KGgoAAAANS....", "selfie": "data:image/png;base64,iVBORw0KGgoAAAANS....", "qr_validation": true}curl -X POST https://api.verificamex.com/identity/v2/validations/basic \ -H "Authorization: Bearer {TU_TOKEN}" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{ "ine_front": "data:image/png;base64,...", "ine_back": "data:image/png;base64,...", "selfie": "data:image/png;base64,...", "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 validació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 cambia 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.
El resultado incluye el campo qrValidation dentro de data de la respuesta de la
Validación completa de INE (V2). Es null si no pediste esta
validación.
| Campo | Tipo | Descripción |
|---|---|---|
| attempted | Boolean | Siempre true cuando pediste 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 la selfie enviada — 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, no
enviaste selfie, o no se detectó rostro en el anverso, compared es false y no se hizo la
comparación —tampoco es un fallo—.
documentVerificationsAdemás del bloque qrValidation, la validación de QR agrega 4 renglones a
data.documentInformation.documentVerifications (categoría "Qr") — el mismo lugar donde ya ves los
renglones de MRZ y biometría:
| key | Qué revisa |
|---|---|
| QrCodeRead | Si los códigos QR del reverso se pudieron leer y decodificar. |
| QrDataMatch_Curp | Si el CURP leído del QR coincide con el CURP del OCR. |
| QrDataMatch_Nombre | Si el nombre leído del QR coincide con el nombre del OCR. |
| QrFaceMatch | Si el rostro embebido en el QR coincide con el del documento. |
Cada uno trae result en "Ok", "Failed" o "NotApplicable" (cuando esa comprobación puntual no
tenía datos suficientes para ejecutarse), igual que el resto de documentVerifications.
qrValidation solo pesa en status/message 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.
qr_validation, no aplica a la credencial, o el QR no se pudo leer — no afecta el
resultado en ningún sentido.data.status pasa a
false, sin importar que Lista Nominal/RENAPO/biometría hayan pasado. data.message explica cuál
de las tres comprobaciones falló.Los mensajes que puedes recibir en data.message cuando el QR reprueba la validación:
| Mensaje | Motivo |
|---|---|
| El CURP leído del código QR no coincide con el CURP del OCR | El CURP leído del QR no coincide con el OCR del anverso. |
| El nombre leído del código QR no coincide con el nombre del OCR | El nombre leído del QR no coincide con el OCR del anverso. |
| El rostro leído del código QR no coincide con el del documento | 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 validación termina con "status": false y
"message": "El CURP leído del código QR no coincide con el CURP del OCR" (se reporta el primer
cotejo que falla: CURP, luego nombre, luego rostro).
{ "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. El resultado depende solo del resto de las validaciones.
Solo en la V2
/v2/validations/basic — no disponible en la V1 (síncrona ni asíncrona) ni en las validaciones ligeras.
Solo pagas si se lee
5 tokens extra con selfie (10 sin ella), 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 cambia el resultado; un QR leído que no coincide, sí.