# Validación de QR (V2) Fuente: /ine-validation/qr-validation/ 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. > **Nota** > > Es una validación **opcional y con costo adicional** — no se ejecuta a menos que la pidas > explícitamente al llamar a [Validación completa de INE (V2)](/ine-validation/complete-validation-v2/). > **Solo disponible en la V2** > > Solo aplica a `/v2/validations/basic`. La [V1](/ine-validation/complete-validation/) (y su > [versión asíncrona](/ine-validation/complete-validation-async/)) no la soporta de forma confiable — > depende de qué proveedor de OCR esté activo en ese momento en el backend— por lo que no la documentamos > ahí. Las validaciones "ligeras" (`/v1/validations/light` y su v2) tampoco la soportan todavía. ## Cómo activarla Envía `qr_validation: true` en el cuerpo de la solicitud a la [V2](/ine-validation/complete-validation-v2/): **JSON** ```json { "ine_front": "data:image/png;base64,iVBORw0KGgoAAAANS....", "ine_back": "data:image/png;base64,iVBORw0KGgoAAAANS....", "selfie": "data:image/png;base64,iVBORw0KGgoAAAANS....", "qr_validation": true } ``` **cURL** ```bash 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 }' ``` > **Consejo** > > `validacion_qr` funciona como alias del mismo parámetro, por si ya lo usas así en tu integración > (es el mismo nombre que usaba este endpoint antes de que existiera `qr_validation`). Si mandas los > dos, gana `qr_validation`. Ambos aceptan `true`/`false` o `"1"`/`"0"`. > **Tiene un costo adicional** > > La validación de QR consume **5 tokens extra** por validación cuando envías `selfie`, y **10 tokens > extra** cuando no la envías. Solo se cobra **si el QR se pudo leer**: si la credencial no trae QR o > no se pudo leer, no se cobra. Aun así, considera que no toda credencial la soporta —lee la siguiente > sección antes de habilitarla para todos tus usuarios. ## No todas las credenciales tienen QR 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](#cómo-afecta-el-resultado-de-la-validación). ## Estructura de la respuesta El resultado incluye el campo `qrValidation` dentro de `data` de la respuesta de la [Validación completa de INE (V2)](/ine-validation/complete-validation-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—. ### También aparece desglosado en `documentVerifications` Ademá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`. > **Diferencia con la V3** > > En las [sesiones de verificación V3](/identity-verification-v3/qr-validation/) el mismo resultado se > expresa distinto: ahí un QR que no coincide agrega entradas a `errors` y el `result` de la sesión pasa > a `0`. Aquí, al no existir un campo `result` numérico, un QR que no coincide reprueba la validación > directamente en `status`/`message` — ver la siguiente sección. ## Cómo afecta el resultado de la validación `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. 1. **No pediste `qr_validation`, no aplica a la credencial, o el QR no se pudo leer** — no afecta el resultado en ningún sentido. 2. **El QR se leyó bien y todo coincide** — no cambia nada; el resultado depende del resto de las validaciones como siempre. 3. **El QR se leyó bien pero el CURP, el nombre o el rostro no coinciden** — `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. | ## Ejemplo completo **QR válido (status: true)** ```json { "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 } } ``` **QR alterado (status: false)** ```json { "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). **Credencial sin QR (no afecta el resultado)** ```json { "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í.