Escáner de Documentos de Identidad
Aplicación de escaneo de documentos que captura automáticamente la zona MRZ (Machine Readable Zone) de pasaportes, cédulas y visas, valida su autenticidad mediante checksums ICAO 9303 y, opcionalmente, lee el chip NFC de pasaportes electrónicos. Toda la información se puede exportar a tu backend a través de una API REST con imágenes en formato multipart.
Producto independiente de la plataforma Faacil
El Escáner de Documentos es una aplicación aparte, con su propia adquisición en la App Store y su propio alcance. No forma parte de la suscripción de la plataforma de gestión inmobiliaria ni se integra con ella: los datos que captura viajan al punto final que configure tu empresa.
Tipos de Documentos Soportados
- Pasaportes (TD3): 2 líneas de 44 caracteres. Compatible con cualquier país que siga el estándar ICAO 9303. Soporte para lectura NFC (BAC/PACE).
- Cédulas de Identidad (TD1): 3 líneas de 30 caracteres. Ej: cédula colombiana moderna, DNI de varios países.
- Visas (TD2): 2 líneas de 36 caracteres.
- Documentos sin MRZ (fallback): Mediante OCR libre se pueden extraer datos de licencias de conducción, cédulas antiguas y otros documentos colombianos (heurísticas específicas).
Proceso de Escaneo
- Detección inteligente: La cámara detecta rectángulos con dimensiones de documento y utiliza una ventana deslizante de 4 frames para estabilizar la captura.
- Auto‑captura: Cuando se confirma la presencia del documento, se captura automáticamente el frame con mayor calidad.
- Procesamiento de imagen: Corrección de perspectiva, escala de grises, ajuste de exposición y contraste, y aumento de nitidez para optimizar el OCR.
- OCR con Vision Framework: Extracción de las líneas MRZ (modo preciso) o búsqueda de texto libre en modo fallback.
- Parsing y validación: El MRZ se descompone según el formato (TD1/TD2/TD3). Se calculan los 5 checksums (pesos 7‑3‑1) y se valida cada campo contra el dígito verificador.
- Multi‑captura y consenso: Se toman entre 3 y 8 fotos en rápida sucesión. Los resultados se combinan mediante un sistema de votación ponderada por calidad de imagen para maximizar la precisión.
- Lectura NFC (solo pasaportes): Utilizando la librería NFCPassportReader, se conecta al chip del pasaporte, lee los Data Groups (DG1, DG2, DG11, DG12, SOD) y compara los datos del chip con el MRZ escaneado.
Exportación de Datos al API
Una vez finalizado el escaneo, la aplicación puede enviar los datos extraídos y las imágenes a tu servidor mediante una petición POST con contenido multipart/form-data. A continuación se detalla el formato.
Endpoint
POST https://tu-servidor.com/api/documents
Estructura del Body (multipart/form-data)
--MRZScannerBoundary-<UUID>
Content-Disposition: form-data; name="document_data"
Content-Type: application/json
{ ... JSON payload ... }
--MRZScannerBoundary-<UUID>
Content-Disposition: form-data; name="front_image"; filename="front.jpg"
Content-Type: image/jpeg
<JPEG binario>
--MRZScannerBoundary-<UUID>
Content-Disposition: form-data; name="back_image"; filename="back.jpg"
Content-Type: image/jpeg
<JPEG binario> (solo para documentos de doble cara)
--MRZScannerBoundary-<UUID>--Campo document_data (JSON)
Objeto con la siguiente estructura (basada en el modelo MRZDocument):
{
"document_type": "P" | "I" | "V" | "O", // Tipo según MRZ
"scanned_type": "PASAPORTE" | "CEDULA_MODERNA" | "LICENCIA" | ...,
"data_source": "MRZ" | "OCR_FREE" | "NFC",
"format": "TD3 (2 líneas - Pasaporte)" | "TD1 (3 líneas - Cédula)" | "OCR Libre",
// Datos personales
"document_number": "string",
"first_name": "string",
"last_name": "string",
"full_name": "string",
"nationality": "string (ISO 3166-1 Alpha-3)",
"date_of_birth": "dd/MM/yyyy" | null,
"sex": "Masculino" | "Femenino" | "<",
"issuing_country": "string",
"expiration_date": "dd/MM/yyyy" | null,
"personal_number": "string" | null,
// Estado y metadatos
"is_expired": boolean,
"overall_validity": boolean, // true si todos los checksums son válidos
"confidence_score": number, // 0.0 - 1.0
"capture_date": "2026-02-17T10:30:00Z", // ISO 8601 UTC
"mrz_lines": ["línea1", "línea2", ...],
// Datos extendidos para Colombia (solo si aplica)
"colombian_data": {
"nuip": "string" | null,
"blood_type": "string" | null, // ej: "O+"
"place_of_birth": "string" | null,
"height": "string" | null, // ej: "175 cm"
"license_category": "string" | null,
"restrictions": "string" | null
} | null,
// Validaciones de checksums ICAO
"checksums": [
{
"field": "Número de Documento",
"valid": boolean,
"expected": number | null,
"calculated": number | null
},
// ... más campos (fecha nacimiento, expiración, personal, compuesto)
]
}Campos de Imagen
- front_image: Siempre incluida. Imagen del anverso del documento en formato JPEG, calidad 60% (tamaño aproximado 150‑400 KB).
- back_image: Incluida solo si el documento tiene reverso (cédulas, licencias) y fue escaneado. Mismas características que front_image.
Ejemplo de Petición (con cédula colombiana)
POST /api/documents HTTP/1.1
Host: tu-servidor.com
Content-Type: multipart/form-data; boundary=xxx
--xxx
Content-Disposition: form-data; name="document_data"
Content-Type: application/json
{
"document_type": "I",
"scanned_type": "CEDULA_MODERNA",
"data_source": "MRZ",
"format": "TD1 (3 líneas - Cédula)",
"document_number": "1020304050",
"first_name": "JUAN CAMILO",
"last_name": "GARCIA LOPEZ",
"full_name": "JUAN CAMILO GARCIA LOPEZ",
"nationality": "COL",
"date_of_birth": "15/03/1990",
"sex": "Masculino",
"issuing_country": "COL",
"expiration_date": "15/03/2030",
"personal_number": null,
"is_expired": false,
"overall_validity": true,
"confidence_score": 0.95,
"capture_date": "2026-02-17T10:30:00Z",
"mrz_lines": [
"IDCOL1020304050<<<<<<<<<<<<<<<",
"9003150M3003159COL<<<<<<<<<<<6",
"GARCIA<LOPEZ<<JUAN<CAMILO<<<<<"
],
"colombian_data": {
"nuip": "1020304050",
"blood_type": "O+",
"place_of_birth": "BOGOTA D.C.",
"height": "175 cm",
"license_category": null,
"restrictions": null
},
"checksums": [
{ "field": "Número de Documento", "valid": true, "expected": 5, "calculated": 5 },
{ "field": "Fecha de Nacimiento", "valid": true, "expected": 0, "calculated": 0 },
{ "field": "Fecha de Expiración", "valid": true, "expected": 9, "calculated": 9 },
{ "field": "Checksum Compuesto", "valid": true, "expected": 6, "calculated": 6 }
]
}
--xxx
Content-Disposition: form-data; name="front_image"; filename="front.jpg"
Content-Type: image/jpeg
<... binario JPEG ...>
--xxx
Content-Disposition: form-data; name="back_image"; filename="back.jpg"
Content-Type: image/jpeg
<... binario JPEG ...>
--xxx--Respuesta Esperada
La aplicación considera exitosa cualquier respuesta con código HTTP 2xx. El cuerpo de la respuesta es ignorado. Se recomienda devolver un JSON con confirmación, por ejemplo:
{
"status": "received",
"document_id": "uuid-generado-por-servidor",
"message": "Documento procesado correctamente"
}Integración Empresarial
La funcionalidad de escaneo es una aplicación adicional que se encuentra en la App Store, tiene un costo único independiente por país.
Correo: contacto@faacil.com