Mexican Government Services API

The Mexican Government Services API provides integration with official Mexican government data sources through certified third-party providers. These APIs enable identity verification, CURP validation, and voter credential authentication.

Overview

All Mexican government service endpoints are:

  • Credit-based: Each API call consumes credits from your account

  • Authenticated: Requires valid API key with read permissions

  • Rate-limited: Subject to your plan's rate limits

  • Audited: All requests are logged for compliance and security

  • Proxy-based: Uses certified providers (Veriqo) to access government databases

RENAPO - CURP Validation

The RENAPO (Registro Nacional de Población) API allows you to obtain and validate CURP (Clave Única de Registro de Población) information based on personal identification data.

What is CURP?

CURP (Unique Population Registry Code) is an 18-character alphanumeric code that uniquely identifies every person living in Mexico. It's similar to a Social Security Number in the US.

Example CURP: GOMC850315HDFRRL09

Get CURP from Personal Data

Retrieve CURP information by providing personal identification details.

Endpoint: POST /v1/mex/renapo/get-curp

Authentication: Required (API Key)

Content-Type: application/json

Request Parameters

Parameter
Type
Required
Description

nombres

string

Yes

First name(s) of the person

primerApellido

string

Yes

First (paternal) last name

segundoApellido

string

No

Second (maternal) last name

sexo

string

Yes

Gender: "H" (Hombre/Male) or "M" (Mujer/Female)

fechaNacimiento

string

Yes

Date of birth in format YYYY-MM-DD

claveEntidad

string

Yes

State code (2 digits). See state codes below

State Codes (claveEntidad)

Code
State
Code
State

01

Aguascalientes

17

Morelos

02

Baja California

18

Nayarit

03

Baja California Sur

19

Nuevo León

04

Campeche

20

Oaxaca

05

Coahuila

21

Puebla

06

Colima

22

Querétaro

07

Chiapas

23

Quintana Roo

08

Chihuahua

24

San Luis Potosí

09

Ciudad de México

25

Sinaloa

10

Durango

26

Sonora

11

Guanajuato

27

Tabasco

12

Guerrero

28

Tamaulipas

13

Hidalgo

29

Tlaxcala

14

Jalisco

30

Veracruz

15

México

31

Yucatán

16

Michoacán

32

Zacatecas

Request Example

curl -X POST https://api.yourdomain.com/v1/mex/renapo/get-curp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nombres": "MARIA GUADALUPE",
    "primerApellido": "GONZALEZ",
    "segundoApellido": "MARTINEZ",
    "sexo": "M",
    "fechaNacimiento": "1985-03-15",
    "claveEntidad": "09"
  }'
// JavaScript/Node.js
const response = await fetch('https://api.yourdomain.com/v1/mex/renapo/get-curp', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    nombres: 'MARIA GUADALUPE',
    primerApellido: 'GONZALEZ',
    segundoApellido: 'MARTINEZ',
    sexo: 'M',
    fechaNacimiento: '1985-03-15',
    claveEntidad: '09'
  })
});

const data = await response.json();
console.log(data);
# Python
import requests

response = requests.post(
    'https://api.yourdomain.com/v1/mex/renapo/get-curp',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
    },
    json={
        'nombres': 'MARIA GUADALUPE',
        'primerApellido': 'GONZALEZ',
        'segundoApellido': 'MARTINEZ',
        'sexo': 'M',
        'fechaNacimiento': '1985-03-15',
        'claveEntidad': '09'
    }
)

data = response.json()
print(data)

Success Response

{
  "success": true,
  "status": "OK",
  "data": {
    "curp": "GOMC850315MDFRRL09",
    "nombres": "MARIA GUADALUPE",
    "primerApellido": "GONZALEZ",
    "segundoApellido": "MARTINEZ",
    "sexo": "M",
    "fechaNacimiento": "1985-03-15",
    "entidadNacimiento": "DISTRITO FEDERAL",
    "nacionalidad": "MEXICANA",
    "estatus": "VIGENTE"
  },
  "processing_time": 1.234
}

Error Responses

Missing Parameter (400)

{
  "success": false,
  "status": "ERROR",
  "type": "MISSING_PARAMETER",
  "message": "The parameter 'nombres' is required"
}

Service Unavailable (503)

{
  "success": false,
  "status": "ERROR",
  "type": "SERVICE_UNAVAILABLE",
  "message": "RENAPO service is currently unavailable. Please try again later.",
  "error_code": "SERVICE_UNAVAILABLE",
  "details": {
    "service": "Veriqo RENAPO API",
    "error_message": "Connection timeout"
  }
}

Insufficient Credits (402)

{
  "success": false,
  "error": "Insufficient credits",
  "credits_required": 1,
  "credits_available": 0
}

INE - Voter Credential Validation

The INE (Instituto Nacional Electoral) API allows you to validate voter credentials against the official Lista Nominal (voter registry).

What is INE?

INE is the official voter credential issued by Mexico's National Electoral Institute. It's one of the most trusted identity documents in Mexico and is used for voting, banking, and official procedures.

Validate Voter Credential

Verify if an INE credential is valid and registered in the Lista Nominal.

Endpoint: POST /v1/mex/ine/validate-voter-list

Authentication: Required (API Key)

Content-Type: application/json

Request Parameters

Parameter
Type
Required
Description

cic

string

Yes

CIC (Clave de Identificación de Credencial) - 9 digits

identificadorCiudadano

string

No

Citizen identifier - 9 digits

ocr

string

No

OCR code from the back of the credential - 13 digits

Note: Providing additional parameters (identificadorCiudadano and/or ocr) increases validation accuracy.

Where to Find These Values

On the INE credential:

  • CIC: 9-digit number on the front, below the photo

  • Identificador Ciudadano: 9-digit number on the front, top right

  • OCR: 13-digit code on the back, bottom section

Request Example

curl -X POST https://api.yourdomain.com/v1/mex/ine/validate-voter-list \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cic": "123456789",
    "identificadorCiudadano": "987654321",
    "ocr": "1234567890123"
  }'
// JavaScript/Node.js
const response = await fetch('https://api.yourdomain.com/v1/mex/ine/validate-voter-list', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    cic: '123456789',
    identificadorCiudadano: '987654321',
    ocr: '1234567890123'
  })
});

const data = await response.json();
console.log(data);
# Python
import requests

response = requests.post(
    'https://api.yourdomain.com/v1/mex/ine/validate-voter-list',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
    },
    json={
        'cic': '123456789',
        'identificadorCiudadano': '987654321',
        'ocr': '1234567890123'
    }
)

data = response.json()
print(data)

Success Response

{
  "success": true,
  "status": "OK",
  "data": {
    "valid": true,
    "cic": "123456789",
    "identificadorCiudadano": "987654321",
    "ocr": "1234567890123",
    "estatus": "VIGENTE",
    "seccion": "0123",
    "municipio": "MIGUEL HIDALGO",
    "entidad": "DISTRITO FEDERAL",
    "fechaVigencia": "2025-12-31",
    "message": "Credential is valid and registered in Lista Nominal"
  },
  "processing_time": 0.987
}

Error Responses

Missing Parameter (400)

{
  "success": false,
  "status": "ERROR",
  "type": "MISSING_PARAMETER",
  "message": "The parameter 'cic' is required"
}

Invalid Format (400)

{
  "success": false,
  "status": "ERROR",
  "type": "INVALID_PARAMETER",
  "message": "The parameter 'cic' must be 9 digits"
}

Not Found in Registry (200)

{
  "success": true,
  "status": "OK",
  "data": {
    "valid": false,
    "cic": "123456789",
    "message": "Credential not found in Lista Nominal or has been invalidated"
  },
  "processing_time": 0.876
}

Service Unavailable (503)

{
  "success": false,
  "status": "ERROR",
  "type": "SERVICE_UNAVAILABLE",
  "message": "INE voter validation service is currently unavailable. Please try again later.",
  "error_code": "SERVICE_UNAVAILABLE",
  "details": {
    "service": "Veriqo INE API",
    "error_message": "Connection timeout"
  }
}

Use Cases

1. Digital Onboarding (KYC)

Verify customer identity during account creation:

async function verifyMexicanCustomer(customerData) {
  // Step 1: Validate CURP
  const curpResponse = await fetch('https://api.yourdomain.com/v1/mex/renapo/get-curp', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      nombres: customerData.firstName,
      primerApellido: customerData.paternalLastName,
      segundoApellido: customerData.maternalLastName,
      sexo: customerData.gender,
      fechaNacimiento: customerData.birthDate,
      claveEntidad: customerData.birthState
    })
  });

  const curpData = await curpResponse.json();

  if (!curpData.success) {
    throw new Error('CURP validation failed');
  }

  // Step 2: Validate INE credential
  const ineResponse = await fetch('https://api.yourdomain.com/v1/mex/ine/validate-voter-list', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      cic: customerData.ineCIC,
      identificadorCiudadano: customerData.ineIdentifier,
      ocr: customerData.ineOCR
    })
  });

  const ineData = await ineResponse.json();

  if (!ineData.success || !ineData.data.valid) {
    throw new Error('INE credential validation failed');
  }

  // Both validations passed
  return {
    verified: true,
    curp: curpData.data.curp,
    ineStatus: ineData.data.estatus
  };
}

2. Employee Verification

Verify employee identity before hiring:

def verify_employee_identity(employee):
    """Verify employee identity using RENAPO CURP"""

    response = requests.post(
        'https://api.yourdomain.com/v1/mex/renapo/get-curp',
        headers={'Authorization': f'Bearer {API_KEY}'},
        json={
            'nombres': employee['first_name'],
            'primerApellido': employee['paternal_last_name'],
            'segundoApellido': employee['maternal_last_name'],
            'sexo': employee['gender'],
            'fechaNacimiento': employee['birth_date'],
            'claveEntidad': employee['birth_state']
        }
    )

    data = response.json()

    if data.get('success'):
        # Store verified CURP in employee record
        return {
            'verified': True,
            'curp': data['data']['curp'],
            'nationality': data['data']['nacionalidad']
        }

    return {'verified': False, 'error': data.get('message')}

3. Voter Registration Verification

Validate voter credentials for electoral processes:

async function validateVoterCredential(credential) {
  const response = await fetch('https://api.yourdomain.com/v1/mex/ine/validate-voter-list', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      cic: credential.cic,
      identificadorCiudadano: credential.identifier,
      ocr: credential.ocr
    })
  });

  const data = await response.json();

  if (data.success && data.data.valid) {
    return {
      valid: true,
      section: data.data.seccion,
      municipality: data.data.municipio,
      state: data.data.entidad,
      expiryDate: data.data.fechaVigencia
    };
  }

  return { valid: false };
}

Best Practices

1. Data Normalization

Always normalize input data before sending requests:

function normalizeMexicanData(data) {
  return {
    nombres: data.nombres.toUpperCase().trim(),
    primerApellido: data.primerApellido.toUpperCase().trim(),
    segundoApellido: data.segundoApellido?.toUpperCase().trim() || null,
    sexo: data.sexo.toUpperCase(),
    fechaNacimiento: data.fechaNacimiento, // Format: YYYY-MM-DD
    claveEntidad: data.claveEntidad.padStart(2, '0')
  };
}

2. Error Handling

Implement robust error handling for different scenarios:

async function handleRenapoRequest(data) {
  try {
    const response = await fetch(RENAPO_ENDPOINT, {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${API_KEY}` },
      body: JSON.stringify(data)
    });

    const result = await response.json();

    switch (response.status) {
      case 200:
        return { success: true, data: result.data };
      case 400:
        return { success: false, error: 'Invalid input data', details: result };
      case 402:
        return { success: false, error: 'Insufficient credits' };
      case 403:
        return { success: false, error: 'Permission denied' };
      case 503:
        return { success: false, error: 'Service temporarily unavailable' };
      default:
        return { success: false, error: 'Unexpected error' };
    }
  } catch (error) {
    return { success: false, error: 'Network error', details: error.message };
  }
}

3. Input Validation

Validate input formats before making API calls:

function validateINEData(data) {
  const errors = [];

  // CIC must be 9 digits
  if (!/^\d{9}$/.test(data.cic)) {
    errors.push('CIC must be exactly 9 digits');
  }

  // Identificador Ciudadano must be 9 digits (if provided)
  if (data.identificadorCiudadano && !/^\d{9}$/.test(data.identificadorCiudadano)) {
    errors.push('Identificador Ciudadano must be exactly 9 digits');
  }

  // OCR must be 13 digits (if provided)
  if (data.ocr && !/^\d{13}$/.test(data.ocr)) {
    errors.push('OCR must be exactly 13 digits');
  }

  return {
    valid: errors.length === 0,
    errors
  };
}

4. Credit Management

Monitor credit usage to avoid service interruptions:

async function checkCreditsBeforeRequest() {
  const creditsResponse = await fetch('https://api.yourdomain.com/v1/credits/balance', {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });

  const { available_credits } = await creditsResponse.json();

  if (available_credits < 10) {
    console.warn('Low credits! Please add more credits to your account.');
  }

  return available_credits > 0;
}

5. Caching Strategy

Cache successful validations to reduce costs and improve performance:

const validationCache = new Map();
const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours

async function getCachedCURP(personalData) {
  const cacheKey = JSON.stringify(personalData);
  const cached = validationCache.get(cacheKey);

  if (cached && (Date.now() - cached.timestamp) < CACHE_DURATION) {
    return cached.data;
  }

  // Make API request
  const result = await makeRenapoRequest(personalData);

  if (result.success) {
    validationCache.set(cacheKey, {
      data: result,
      timestamp: Date.now()
    });
  }

  return result;
}

6. Privacy and Compliance

Handle sensitive personal data responsibly:

  • Never log personal identification data (CURP, INE numbers) in plain text

  • Encrypt stored validation results

  • Comply with Mexican data protection laws (LFPDPPP)

  • Retain data only as long as necessary

  • Implement proper access controls

// Good: Log validation without sensitive data
console.log(`CURP validation completed for user ${userId}: ${success ? 'SUCCESS' : 'FAILED'}`);

// Bad: Don't log sensitive data
// console.log(`CURP validation: ${curp} - ${personalData}`); // ❌ Never do this

Rate Limits and Credits

Credit Costs

Service
Credit Cost per Request

RENAPO CURP Validation

1 credit

INE Voter Validation

1 credit

Rate Limits

Rate limits depend on your subscription plan:

Plan
Requests per Minute
Requests per Day

Free

10

100

Basic

60

10,000

Professional

300

50,000

Enterprise

Custom

Custom


Security

All Mexican government service endpoints include:

  • TLS Encryption: All requests use HTTPS

  • API Key Authentication: Each request must include a valid API key

  • Permission Checks: API keys must have read permission

  • Audit Logging: All requests are logged with IP address and user agent

  • Rate Limiting: Prevents abuse and ensures fair usage

  • Input Validation: All parameters are validated before processing


Support

For issues or questions about Mexican government services:

  1. Check the error message and error codes in the response

  2. Verify your credits balance: GET /v1/credits/balance

  3. Review your API key permissions: GET /v1/api-keys

  4. Check service status: GET /v1/status

  5. Contact support if the issue persists

Note: Service availability depends on third-party providers and Mexican government systems, which may experience occasional downtime.

Last updated