Mandas la imagen y recibes nombre, CURP, clave de elector, CIC y OCR ya separados. Y el domicilio —que en la INE viene abreviado y en una sola línea— te llega desarmado en campos y validado contra el catálogo oficial.
¿Dudas técnicas? Habla con un ingeniero por WhatsApp — 0% bots.
Viene en tres renglones de texto libre, en mayúsculas, con abreviaturas —C por calle, AV por avenida, FRACC por fraccionamiento, COL por colonia— y muchas veces sin separar dónde termina la calle y empieza el número. La mayoría de los OCR te lo devuelven así, tal cual, y el trabajo de desarmarlo queda de tu lado.
Y no te lo entrega a ciegas: el campo geocodingStatus te dice hasta dónde llegó el match —VERIFIED a nivel de calle o domicilio, PARTIAL cuando solo se pudo confirmar la localidad o el código postal, UNVERIFIED cuando no hubo coincidencia confiable—. Con eso tu código decide si el domicilio sirve para el expediente o si conviene pedir un comprobante.
El frente es obligatorio; el reverso es opcional y agrega las claves y las validaciones cruzadas. Ambas imágenes van en Base64 (JPG o PNG).
personalInfoNombre y apellidos por separado, fecha de nacimiento, sexo, CURP y clave de elector. Sin transcripción manual y sin partir cadenas de nombres a mano.addressNormalizedEl domicilio desarmado en campos y validado contra el catálogo, con su geocodingStatus. Junto al texto impreso original en address, por si lo necesitas tal cual.securityLas claves del reverso: cic, ocr, citizenIdentifier, el mrz completo y el qr cuando el modelo lo trae. Son las que necesitas para validar contra la Lista Nominal.validityAños de registro, emisión y vigencia, más el número de emisión. Lo impreso en el documento — la vigencia real la confirma la Lista Nominal.electoralGeographyEntidad, municipio, sección y localidad electoral. Sirve para cruzar contra la respuesta de la Lista Nominal.files[]La fotografía del titular recortada del documento, en Base64. Es la que le pasas a comparación facial para confirmar que quien la presenta es la persona del documento.También llega el model de la credencial —D, E, F, G, H o I— porque cada modelo trae distintos elementos de seguridad y distintas claves. Tu código no tiene que adivinar con cuál está tratando.
Una credencial guarda los mismos datos en tres lugares: impresos al frente, codificados en la zona de lectura mecánica del reverso y, según el modelo, en el código QR. Cuando mandas el reverso, leemos los tres y los contrastamos.
| Campo | Qué contrasta |
|---|---|
mrzValidation.dateOfBirth | La fecha de nacimiento impresa contra la codificada en la MRZ. |
mrzValidation.sex | El sexo impreso contra el de la MRZ. |
mrzValidation.validity | El año de vigencia impreso contra el de la MRZ. |
mrzValidation.emission | El número de emisión impreso contra el de la MRZ. |
mrzValidation.cic | El CIC impreso contra el de la MRZ. |
mrzValidation.name | El nombre impreso contra el de la MRZ. |
qrValidation.* | CIC, OCR e identificador de ciudadano del QR contra lo impreso. Llega en null si el modelo no tiene QR legible. |
Cada bandera llega en true o false. Un false no dictamina por sí solo que la credencial sea falsa —un OCR puede equivocarse con un apellido borroso—, pero te señala exactamente qué campo no cuadra para que lo revises en vez de rechazar el documento completo a ciegas.
Hay dos categorías, y la diferencia importa para tu factura: los límites duros se rechazan antes de procesar y no se cobran; las recomendaciones no se imponen —una foto imperfecta se procesa igual—.
| Qué | Límite | Si no se cumple |
|---|---|---|
| Formato | JPEG · PNG | INVALID_REQUEST, sin cobro |
| Peso por imagen | hasta 12 MB en Base64 | INVALID_REQUEST, sin cobro |
| Peso total de la petición | hasta 28 MB | INVALID_REQUEST, sin cobro |
| Resolución, encuadre e iluminación | recomendación, no se impone | se procesa igual; si no se puede leer, IMAGE_UNREADABLE y sí se cobra |
Ojo con el peso: el límite de 12 MB es sobre la cadena ya codificada en Base64, y Base64 infla el archivo alrededor de un tercio. Un JPG de 9 MB en disco ronda los 12 MB codificado. En la práctica no te acercas: una foto de teléfono bien tomada pesa entre 1 y 3 MB, y mientras más liviana, menos tarda el viaje.
Nada de esto se impone —una foto que no cumpla se procesa igual—, pero es lo que sube la tasa de lectura al primer intento.
| Parámetro | Objetivo | Por qué |
|---|---|---|
| Resolución | 1280 px de ancho o más mínimo 1024 px | Con ese ancho el texto de la credencial se lee sin problema. Cualquier teléfono actual lo supera de sobra. |
| La credencial en el encuadre | más del 90% | Lo que importa no son los píxeles de la foto, sino los que caen sobre la credencial. Una foto de 4000 px donde la credencial ocupa un quinto del cuadro tiene menos detalle útil que una de 1280 px donde la llena. |
| Formato y peso | JPG · 1–3 MB | El JPG que sale de la cámara basta. Reguardarlo varias veces lo degrada en cada paso; mándalo tal cual salió. |
IMAGE_UNREADABLE, no datos inventados. Ese caso sí consumió cómputo y se cobra — pero te dice qué pasó para que pidas exactamente esa foto otra vez.Mismo envelope que todos los servicios de OrigoID: status, type, data. El frente es obligatorio; manda también el reverso si quieres las claves y las validaciones cruzadas.
const res = await fetch("https://api.origoid.com/mex/id/v1/voter-id-extractions", { method: "POST", headers: { "x-api-key": process.env.ORIGOID_API_KEY, "content-type": "application/json", }, body: JSON.stringify({ front: frenteBase64, back: reversoBase64, // opcional: agrega claves y cruces }), }); const { data } = await res.json(); const dom = data.addressNormalized; if (dom.geocodingStatus === "VERIFIED") guardarEnExpediente(dom);
import os, requests res = requests.post( "https://api.origoid.com/mex/id/v1/voter-id-extractions", headers={ "x-api-key": os.environ["ORIGOID_API_KEY"], "content-type": "application/json", }, json={"front": frente_base64, "back": reverso_base64}, timeout=30, ) data = res.json()["data"] domicilio = data["addressNormalized"]
curl -X POST https://api.origoid.com/mex/id/v1/voter-id-extractions \ -H "x-api-key: $ORIGOID_API_KEY" \ -H "content-type: application/json" \ -d '{"front": "<base64>", "back": "<base64>"}'
{
"status": "OK",
"type": "SUCCESS",
"data": {
"model": "E",
"address": { "addressLine1": "AV LAGO ALBERTO 320 TORRE CENTRAL 503", … },
"addressNormalized": {
"geocodingStatus": "VERIFIED",
"street": "Avenida Lago Alberto",
"exteriorNumber": "320",
"interiorNumber": "Torre Central 503",
"neighborhood": "Anáhuac",
"zipCode": "11320",
"municipality": "Miguel Hidalgo",
"state": "Ciudad de México"
},
"mrzValidation": { "cic": false, "name": true, … }
},
"billable": true
}
| type | Qué significa | Decisión |
|---|---|---|
SUCCESS | El documento se leyó. Revisa geocodingStatus y las banderas de MRZ/QR para decidir si el expediente queda completo. | Avanza |
IMAGE_UNREADABLE | La imagen está borrosa u obstruida. Pide solo esa foto de nuevo, con mejor luz y sin reflejos. | Analiza |
DOCUMENT_NOT_IDENTIFIED | Lo que llegó no es una credencial de elector reconocida. Suele ser otra identificación o una foto equivocada. | Rechaza |
Los errores técnicos llegan aparte con status: "ERROR": una imagen que no es JPG/PNG, un archivo mayor a 12 MB o un cuerpo que pasa de 28 MB se rechazan como INVALID_REQUEST con billable: false — sin cobro. En cambio, si la imagen se procesó y salió ilegible, sí consumió cómputo y se cobra: preferimos decírtelo antes que sorprenderte en la factura.
El OCR digitaliza el documento y resuelve el domicilio; la Lista Nominal confirma que la credencial es válida; la comparación facial confirma que es la persona. Mismo envelope en las tres.
Del frente: nombre y apellidos por separado, fecha de nacimiento, sexo, CURP, clave de elector, el domicilio y la fotografía del titular. Del reverso: cic, ocr, citizenIdentifier, la MRZ y el QR según el modelo. Más los años de registro, emisión y vigencia, la geografía electoral y el modelo detectado (D, E, F, G, H o I).
Doble: el texto impreso tal cual en address, y en addressNormalized separado en calle, número exterior e interior, colonia, CP, municipio, estado y país, con abreviaturas expandidas y validado contra el catálogo oficial. El geocodingStatus te dice la confianza del match: VERIFIED, PARTIAL o UNVERIFIED. Son componentes del domicilio, no coordenadas.
No es obligatorio. Con el frente ya obtienes los datos impresos y la foto. El reverso agrega las claves (CIC, OCR, identificador) y habilita las validaciones cruzadas de MRZ y QR contra lo impreso.
Señala inconsistencias. Con el reverso, contrasta lo impreso contra la MRZ y el QR y marca campo por campo en mrzValidation y qrValidation. Un false te dice qué no cuadra; no es un dictamen de falsedad por sí solo, es la señal para revisar.
No. Se procesan para la extracción y se descartan al responder: sin base de datos de documentos, sin rastro en logs. Cero retención en todas nuestras regiones.
Una extracción = 1 crédito, mandes solo el frente o frente y reverso. Empiezas gratis con créditos de cortesía, sin tarjeta, y el precio baja con tu volumen. Todos los planes publicados.
Créditos de cortesía para probar el OCR con credenciales reales en producción. El acceso se habilita tras una breve validación de tu empresa.