Your user takes three photos. You run seven verifications that chain together on their own: INE, QR, face, Lista Nominal, CURP-RFC and CSF —straight from the official sources.
Fraud in car rental is almost always impersonation: a borrowed identity or someone else's ID. Here's how the full verification comes together: each wave uses the previous one's response. You fire the calls and OrigoID answers; the cross-checks between responses are an if in your backend.
addressNormalized.OCR INEINE QRFace Matchif in your backend — both responses are already in your hands.your codeFace MatchCURP validationLista NominalSAT CSFif in your backend.your codeThe envelope tells you exactly what failed —FACE_MISMATCH if the face isn't the one on the ID, IMAGE_UNREADABLE if the photo came out blurry, a back that doesn't line up with the front— and you ask for just that photo or that value again. The rest of the flow doesn't repeat, and the legitimate driver passes without friction.
You send the INE image; you get the data already structured and the address already split into fields in the same envelope as every endpoint. Learn the contract once and it works for every step of the flow.
status, type, data— across INE, QR, face, Lista Nominal, CURP and CSF.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: ineFrontBase64 }), }); const result = await res.json();
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": ine_front_base64}, timeout=30, ) result = res.json()
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 of the INE (JPG or PNG)>"}'
{
"status": "OK",
"type": "SUCCESS",
"data": {
"documentType": "INE",
"personalInfo": { "givenNames": "ANA SOFIA", "curp": "GOSA880718MNLNLN07", … },
"addressNormalized": {
"geocodingStatus": "VERIFIED",
"street": "Avenida Lago Alberto", "zipCode": "11320",
"municipality": "Miguel Hidalgo", "state": "Ciudad de México"
}
},
"billable": true
}
Renting a car puts a full identity and an expensive asset on the line. The verification has to be real, thorough and leave no trace of your customer's data.
Your user takes three photos: the front and back of their INE, and a selfie. With that you run the OCR with a normalized, catalog-validated address, the read of the back, the face comparisons, Lista Nominal and the CURP and RFC cross-check against RENAPO and SAT — each response feeds the next call.
It's the sum of the layers: the data the OCR read is cross-checked against what's extracted from the back —two independent readings that must match—; the face pulled from the front is compared against the one on the back; and Lista Nominal confirms the ID exists and is current in the INE's roll. A tampered ID fails at one of those layers.
It's on our roadmap, with no committed date yet. Today we verify the driver's identity —INE, QR, face, CURP, RFC—, which is the layer that prevents most impersonation fraud in car rental.
The envelope tells you exactly what failed —FACE_MISMATCH, IMAGE_UNREADABLE, a back that doesn't line up with the front— and you ask for just that photo or that value again. The rest of the flow doesn't repeat.
No. Every query is validated, answered and discarded, without storing the data.
Try the full flow in production with courtesy credits. Access is enabled after a short verification of your company.