INE Fingerprint Validation

Incode's INE Fingerprint Validation lets you verify a user's identity against Mexico's Instituto Nacional Electoral (INE) using fingerprint biometrics captured at a branch or kiosk. You supply fingerprint scans from your existing hardware; Incode forwards them to INE for matching and returns a per-finger confidence score alongside the standard government validation result.

This feature must be enabled for your account before use. Contact your Incode representative if you are interested in this feature.

How It Works

Fingerprint validation is a two-step flow:

  1. Collection — your app uploads fingerprints to the active session using /omni/add/fingerprints.
  2. Validation — your app calls /omni/process/government-validation. Incode selects the best available fingerprints, sends them to INE alongside face and ID data, and returns a combined result.

Fingerprints can also be passed inline in the validation request instead of pre-uploading them. See Sample Request below.

Supported Fingerprint Formats

Value Format
1 ANSI
2 WSQ
3 RAW

All formats submitted in a single session must use the same type. If you upload fingerprints with a different type than what is already stored in the session, all previously stored fingerprints are deleted before the new ones are saved.

The most common format in production is WSQ (type: 2).

Finger Index Mapping

Use the index field to identify which finger was scanned.

Index Finger Hand
1 Thumb Right
2 Index Right
3 Middle Right
4 Ring Right
5 Pinky Right
6 Thumb Left
7 Index Left
8 Middle Left
9 Ring Left
10 Pinky Left

The most common submission in production is the right index finger (index: 2) in WSQ format.

If a user cannot provide a specific finger, submit whichever finger is available. A single fingerprint is sufficient — there is no minimum beyond one.

API Reference

POST /omni/add/fingerprints

Upload one or more fingerprints to the active session.

Request body:

{
  "type": 2,
  "fingerprints": [
    {
      "index": 2,
      "base64Fingerprint": "<base64-encoded image>",
      "fingerprintMetadata": {
        "device": "scanner_device",
        "resolution": "500x500",
        "qualityScore": "95"
      }
    }
  ]
}

Fields:

Field Type Required Description
type integer Yes Fingerprint format: 1 = ANSI, 2 = WSQ, 3 = RAW
fingerprints array Yes Array of fingerprint objects
fingerprints[].index integer (1–10) Yes Which finger was scanned
fingerprints[].base64Fingerprint string Yes Base64-encoded fingerprint image
fingerprints[].fingerprintMetadata.device string No Scanner device identifier
fingerprints[].fingerprintMetadata.resolution string No Image resolution
fingerprints[].fingerprintMetadata.qualityScore string No Quality score reported by the scanner

Response:

{ "success": true }

Behavior notes:

GET /omni/get/fingerprints?interviewId={id}

Retrieve the fingerprints stored for a session. Returns the same structure as the add request, with base64Fingerprint populated from storage.

POST /omni/process/government-validation

Trigger INE identity validation. Incode selects the best available fingerprints from the session and sends them to INE alongside face and ID data.

Fingerprints can be passed inline in this request using the fingerprintsData field, or omitted entirely if they were already uploaded via /omni/add/fingerprints — the service retrieves them from storage automatically. Inline fingerprints take precedence over stored ones.

Finger Selection Logic

INE accepts a maximum of 2 fingerprints per validation request. Incode automatically selects the best available fingerprints from the session before forwarding to INE.

Selection priority:

  1. A matched pair (same finger position, both hands) is preferred over a single finger.
  2. Pairs are evaluated in this order: Index (2/7) → Thumb (1/6) → Middle (3/8) → Ring (4/9) → Pinky (5/10).
  3. If no matched pair is available, the highest-priority single finger is sent.
  4. If no fingerprints are available, the request proceeds without fingerprint data.

Sample Request

Full example calling /omni/process/government-validation with fingerprints passed inline:

curl -X POST "https://<host>/omni/process/government-validation?interviewId=<interviewId>" \
  -H "Content-Type: application/json" \
  -H "X-Incode-Hardware-Id: <apiKey>" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "cic": "1234567890",
    "claveElector": "ABCDEF123456789012",
    "nombre": "JUAN",
    "apellidoPaterno": "GARCIA",
    "apellidoMaterno": "LOPEZ",
    "curp": "GALJ800101HDFRCN09",
    "anioRegistro": "2010",
    "anioEmision": "2020",
    "numeroEmisionCredencial": "01",
    "base64Image": "<base64-encoded face template>",
    "fingerprintsData": {
      "type": 2,
      "fingerprints": [
        {
          "index": 2,
          "base64Fingerprint": "<base64-encoded fingerprint image>",
          "fingerprintMetadata": {
            "device": "Suprema BioMini",
            "resolution": "500x500",
            "qualityScore": "92"
          }
        },
        {
          "index": 7,
          "base64Fingerprint": "<base64-encoded fingerprint image>",
          "fingerprintMetadata": {
            "device": "Suprema BioMini",
            "resolution": "500x500",
            "qualityScore": "88"
          }
        }
      ]
    }
  }'

Sample Success Response

{
  "governmentValidationStatus": "OK",
  "governmentRecognitionConfidence": 97.3,
  "governmentRecognitionConfidence2": 95.1,
  "governmentFingerprintConfidence": {
    "finger1": null,
    "finger2": 98.5,
    "finger3": null,
    "finger4": null,
    "finger5": null,
    "finger6": null,
    "finger7": 96.2,
    "finger8": null,
    "finger9": null,
    "finger10": null
  },
  "comparisonResults": {
    "nombre": true,
    "apellidoPaterno": true,
    "apellidoMaterno": true,
    "claveElector": true,
    "curp": true,
    "ocr": true,
    "anioRegistro": true,
    "anioEmision": true,
    "numeroEmisionCredencial": true
  },
  "registralSituation": {
    "tipoSituacionRegistral": "VIGENTE",
    "tipoReporteRoboExtravio": null
  }
}

null values for fingers not submitted are expected. INE only scores the fingers it received.

Response Fields

Fingerprint Confidence

governmentFingerprintConfidence contains per-finger similarity scores returned by INE. Scores range from 0–100. Only fingers included in the request will have non-null values.

Face Confidence

Field Description
governmentRecognitionConfidence Primary face match score
governmentRecognitionConfidence2 Secondary face match score

Comparison Results

INE validates whether the data on the ID card matches its records. Each field returns true or false.

Field What is validated
nombre First name
apellidoPaterno Paternal last name
apellidoMaterno Maternal last name
claveElector Voter key
curp CURP
ocr OCR data
anioRegistro Registration year
anioEmision Issuance year
numeroEmisionCredencial Credential emission number

Registral Situation

INE returns the current status of the credential.

tipoSituacionRegistral:

Value Meaning
VIGENTE ID is current and valid
NO_VIGENTE ID is no longer valid
DATOS_NO_ENCONTRADOS No data found

tipoReporteRoboExtravio:

Value Meaning
null No report on file
REPORTE_DE_EXTRAVIO ID reported lost
REPORTE_DE_ROBO ID reported stolen

Status Codes

Status Code Internal Status Meaning
0 OK Identity verified successfully
-1 PROCESSING_INE Result pending (async)
112, 113 INE_SIGNATURE_ERROR Signature validation error
204 INE_CONNECTION_ERROR Connection error to INE
205 NOT_ENOUGH_DATA Insufficient data provided
1403 USER_NOT_FOUND_IN_INE_DB Person not found in INE database
1404 INE_NOT_CURRENT ID card is not current
1405 INE_REPORTED_LOST ID reported lost
1406 INE_REPORTED_STOLEN ID reported stolen
1505 INE_NOT_VALID ID is not valid
1506 PROVIDER_UNAVAILABLE INE provider is unavailable
1507 MODULE_NOT_SUPPORTED Module not supported
2336 TRANSACTION_LIMIT_REACHED Rate limit exceeded

Dashboard

When fingerprint validation is enabled, the Gov Verification section in the single session view displays:

Only fingers that were actually submitted appear in the dashboard — all 10 slots are not shown by default.