Descarga PDF CURP Validation API Documentation


Descripción General del Endpoint

Endpoint: /api/v1/government/mx/curp/validate
Método: POST
Dominio: Gobierno - México
Propósito: Valida el formato, estructura y autenticidad del CURP (Clave Única de Registro de Población) mexicano


¿Qué es un CURP?

El CURP (Clave Única de Registro de Población) es un código alfanumérico único de 18 caracteres asignado a todos los residentes de México. Sirve como el número de identificación primario para servicios gubernamentales, bancarios, empleo y trámites oficiales.

Estructura del CURP:

  • 18 caracteres en total
  • Contiene: iniciales de apellidos, inicial del nombre, fecha de nacimiento, sexo, estado de nacimiento, consonantes internas y dígito verificador
  • Ejemplo: GAMC850815HDFRRL09

Autenticación

Este endpoint requiere autenticación API. Incluye tus credenciales API en los encabezados de la petición:

Authorization: Bearer TU_API_KEY
Content-Type: application/json

Parámetros de la Petición

Encabezados (Headers)

ParámetroTipoRequeridoDescripción
Request-IdstringOpcionalIdentificador único para rastrear tu petición. Si no se proporciona, se genera automáticamente.
AuthorizationstringRequeridoToken Bearer para autenticación API
Content-TypestringRequeridoDebe ser application/json

Cuerpo de la Petición (Request Body)

CampoTipoRequeridoDescripción
curpstringRequeridoLa cadena CURP a validar (18 caracteres)
require_pdfbooleanOpcionalSi es true, solicita el certificado PDF oficial del CURP desde RENAPO (requiere tiempo adicional de procesamiento)

Ejemplo de Petición

Validación Básica (sin PDF)

curl -X POST "https://api.jaak.ai/api/v1/government/mx/curp/validate" \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Request-Id: d99fe2d2-c0c3-4396-bd97-a502b4c30fa3" \
  -d '{
    "curp": "GAMC850815HDFRRL09",
    "require_pdf": false
  }'

Con Certificado PDF Oficial del CURP

curl -X POST "https://api.jaak.ai/api/v1/government/mx/curp/validate" \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Request-Id: d99fe2d2-c0c3-4396-bd97-a502b4c30fa3" \
  -d '{
    "curp": "GAMC850815HDFRRL09",
    "require_pdf": true
  }'

Nota: Cuando require_pdf: true, la respuesta incluirá una URL firmada en curp.details.pdf_url y metadata.pdf_url para descargar el certificado oficial del CURP desde RENAPO. Esta URL expira en 15 minutos.

Cuerpo de la Petición en JSON

{
  "curp": "GAMC850815HDFRRL09",
  "require_pdf": false
}

Formato de Respuesta

Respuesta Exitosa (200 OK)

{
  "event_id": "80b21c69-79ff-4431-8447-e38c49fb006c",
  "request_id": "80b21c69-79ff-4431-8447-e38c49fb006c",
  "timestamp": "2025-12-16T16:33:34.035842343Z",
  "process_time_ms": 63,
  "state": {
    "success": true
  },
  "curp": {
    "value": "GAMC850815HDFRRL09",
    "valid": true,
    "details": {
      "cache_invalidated": false,
      "pdf_present": true,
      "pdf_required": false,
      "pdf_url": "https://storage.googleapis.com/jaak-media/xxxxx.pdf?signature=...",
      "renapo_valid": true,
      "request_id": "b26f7618-ac0b-4da8-9b35-1436dd4a7b5f",
      "service_used": "RENAPO_GRPC",
      "status_curp": "AN"
    }
  },
  "validation_details": {
    "format_valid": true,
    "structure_valid": true,
    "check_digit_valid": true,
    "business_rules_valid": true
  },
  "personal_info": {
    "birth_date": "1985-08-15",
    "birth_entity_code": "DF",
    "birth_entity_name": "CIUDAD DE MEXICO",
    "curp_components": {
      "birth_date_curp": "1985-08-15",
      "birth_entity_curp": "DF",
      "consonants": "RRL",
      "first_letter_maternal": "M",
      "first_letter_name": "C",
      "first_letter_paternal": "G",
      "first_vowel_paternal": "A",
      "gender_curp": "H",
      "homonymy": "0",
      "verification_digit": "9"
    },
    "document_data": {
      "additional_data": "{\"additional_data\":{\"claveEntidadRegistro\":\"09\",\"claveMunicipioRegistro\":\"002\"},\"supporting_document_data\":{\"anioReg\":\"1985\",\"claveEntidadRegistro\":\"09\",\"claveMunicipioRegistro\":\"002\",\"entidadRegistro\":\"CIUDAD DE MEXICO\",\"foja\":\"\",\"libro\":\"\",\"municipioRegistro\":\"AZCAPOTZALCO\",\"numActa\":\"01234\",\"tomo\":\"\"}}",
      "certificate_number": "01234",
      "foreigner_registry_number": "",
      "registration_year": "1985",
      "registry_book": "",
      "registry_entity": "CIUDAD DE MEXICO",
      "registry_entity_code": "09",
      "registry_municipality": "AZCAPOTZALCO",
      "registry_municipality_code": "002",
      "registry_page": "",
      "registry_volume": ""
    },
    "full_name": "CARLOS",
    "maternal_surname": "MARTINEZ",
    "nationality": "MEXICO",
    "paternal_surname": "GARCIA",
    "renapo_birth_date": "1985-08-15",
    "renapo_gender": "HOMBRE",
    "status_curp": "AN",
    "status_curp_code": "AN",
    "supporting_document": "1",
    "supporting_document_code": "1"
  },
  "metadata": {
    "api_version": "v1",
    "birth_entity": "CIUDAD DE MEXICO",
    "cache_invalidated": false,
    "grpc_service": "curpv1",
    "nationality": "MEXICO",
    "pdf_expires_in": "15 minutes",
    "pdf_present": true,
    "pdf_required": false,
    "pdf_url": "https://storage.googleapis.com/jaak-media/xxxxx.pdf?signature=...",
    "renapo_status": "AN",
    "service": "RENAPO_CURP_VALIDATION",
    "supporting_document": "1"
  }
}

Explicación de los Campos de Respuesta

Campos de Nivel Raíz

CampoTipoDescripción
event_idstringIdentificador único para este evento de validación en el sistema JAAK
request_idstringEl Request-Id proporcionado en los encabezados o UUID autogenerado
timestampstringMarca de tiempo ISO 8601 de cuando ocurrió la validación (UTC)
process_time_msintegerTiempo de procesamiento en milisegundos
state.successbooleanIndica si la llamada a la API fue exitosa

Objeto CURP

CampoTipoDescripción
curp.valuestringEl CURP que fue validado
curp.validbooleanResultado general de validación - true si el CURP pasa todas las verificaciones

Objeto de Detalles del CURP

CampoTipoDescripción
curp.details.cache_invalidatedbooleanSi los datos en caché fueron invalidados para esta petición
curp.details.pdf_presentbooleanIndica si el certificado PDF oficial del CURP está disponible
curp.details.pdf_requiredbooleanSi el PDF fue explícitamente solicitado en la petición
curp.details.pdf_urlstringURL firmada para descargar el certificado oficial del CURP desde RENAPO (expira en 15 minutos)
curp.details.renapo_validbooleanSi el CURP fue validado directamente con RENAPO (Registro Nacional de Población de México)
curp.details.request_idstringID de petición interno usado para la llamada al servicio RENAPO
curp.details.service_usedstringServicio backend usado para validación (ej., "RENAPO_GRPC")
curp.details.status_curpstringCódigo de estado del CURP desde RENAPO (ver códigos de estado más abajo)

Detalles de Validación

CampoTipoDescripción
validation_details.format_validbooleanEl CURP tiene la longitud correcta (18 caracteres) y tipos de caracteres
validation_details.structure_validbooleanLos componentes del CURP (iniciales, fecha, código de estado) están estructurados correctamente
validation_details.check_digit_validbooleanEl dígito verificador (último carácter) es matemáticamente correcto
validation_details.business_rules_validbooleanEl CURP sigue las convenciones de nomenclatura y fecha del gobierno mexicano

Objeto de Información Personal

CampoTipoDescripción
personal_info.birth_datestringFecha de nacimiento extraída del CURP (YYYY-MM-DD)
personal_info.birth_entity_codestringCódigo de dos letras del estado donde nació la persona
personal_info.birth_entity_namestringNombre completo del estado de nacimiento
personal_info.full_namestringNombre(s) de la persona
personal_info.paternal_surnamestringApellido paterno
personal_info.maternal_surnamestringApellido materno
personal_info.nationalitystringNacionalidad (típicamente "MEXICO")
personal_info.renapo_birth_datestringFecha de nacimiento confirmada por RENAPO
personal_info.renapo_genderstringGénero confirmado por RENAPO ("HOMBRE" o "MUJER")
personal_info.status_curpstringEstado del CURP desde RENAPO
personal_info.status_curp_codestringCódigo de estado (ver sección de códigos de estado del CURP)
personal_info.supporting_documentstringCódigo del tipo de documento de respaldo
personal_info.supporting_document_codestringCódigo numérico para el tipo de documento

Componentes del CURP (Desglose)

El objeto personal_info.curp_components desglosa cada elemento del CURP de 18 caracteres:

CampoTipoDescripciónPosición en el CURP
first_letter_paternalstringPrimera letra del apellido paterno1
first_vowel_paternalstringPrimera vocal del apellido paterno2
first_letter_maternalstringPrimera letra del apellido materno3
first_letter_namestringPrimera letra del primer nombre4
birth_date_curpstringFecha de nacimiento (formato AAMMDD)5-10
gender_curpstringGénero ("H" = Hombre, "M" = Mujer)11
birth_entity_curpstringCódigo de dos letras del estado de nacimiento12-13
consonantsstringConsonantes internas de apellidos y nombre14-16
homonymystringDiferenciador de homonimia (0-9 o A-Z)17
verification_digitstringDígito de verificación para validación (0-9)18

Ejemplo: Para el CURP GAMC850815HDFRRL09

  • GA = García (paterno)
  • M = Martínez (materno)
  • C = Carlos (nombre)
  • 850815 = 15 de agosto de 1985
  • H = Hombre
  • DF = Ciudad de México
  • RRL = Consonantes
  • 0 = Homonimia
  • 9 = Dígito verificador

Datos del Documento (Información del Acta de Nacimiento)

El objeto personal_info.document_data contiene información del acta de nacimiento de la persona:

CampoTipoDescripción
certificate_numberstringNúmero del acta de nacimiento (número de acta)
registration_yearstringAño en que se registró el nacimiento
registry_entitystringEstado donde se registró el nacimiento
registry_entity_codestringCódigo numérico del estado de registro
registry_municipalitystringMunicipio donde se registró el nacimiento
registry_municipality_codestringCódigo numérico del municipio de registro
registry_bookstringNúmero del libro de registro - puede estar vacío
registry_volumestringVolumen de registro (tomo) - puede estar vacío
registry_pagestringPágina de registro (foja) - puede estar vacío
foreigner_registry_numberstringNúmero de registro extranjero (para ciudadanos naturalizados)
additional_datastringCadena JSON con información adicional del registro

Metadatos

CampoTipoDescripción
metadata.api_versionstringVersión de la API utilizada
metadata.birth_entitystringNombre del estado de nacimiento
metadata.cache_invalidatedbooleanIndicador de invalidación de caché
metadata.grpc_servicestringIdentificador del servicio gRPC interno
metadata.nationalitystringNacionalidad de la persona
metadata.pdf_presentbooleanIndicador de disponibilidad del PDF
metadata.pdf_requiredbooleanSi el PDF fue solicitado
metadata.pdf_urlstringURL firmada de descarga para el certificado del CURP
metadata.pdf_expires_instringTiempo hasta que expira la URL del PDF (típicamente "15 minutes")
metadata.renapo_statusstringEstado de validación de RENAPO
metadata.servicestringTipo de servicio usado ("RENAPO_CURP_VALIDATION")
metadata.supporting_documentstringTipo de documento de respaldo

Códigos de Estado del CURP

El campo status_curp indica el estado del CURP en RENAPO:

CódigoEstadoDescripción
ANActivo NormalActivo/Normal - El CURP es válido y está activo
ABActivo BajaActivo pero marcado para eliminación
INInactivoInactivo - El CURP ha sido desactivado
RNRegistro NacionalEstado de registro nacional
RERectificadoCURP rectificado/corregido

Más Común: AN (Activo Normal) indica un CURP completamente válido y activo.


Códigos de Documento de Respaldo

El campo supporting_document indica qué tipo de documento respalda el CURP:

CódigoTipo de Documento
1Acta de Nacimiento
2Certificado de Naturalización
3Acta de Nacimiento Extranjera
4Otros documentos oficiales

Respuesta de Error (400 Bad Request)

{
  "errorCode": "INVALID_CURP_FORMAT",
  "eventId": "evt_error_xyz789",
  "message": "El CURP debe tener exactamente 18 caracteres alfanuméricos",
  "statusCode": 400
}

Códigos de Error Comunes

Código de ErrorEstadoDescripciónSolución
INVALID_CURP_FORMAT400El CURP no cumple con los requisitos de formatoVerifica que el CURP tenga 18 caracteres alfanuméricos
INVALID_CHECK_DIGIT400Falló la validación del dígito verificadorEl CURP puede estar transcrito incorrectamente
INVALID_DATE400La fecha de nacimiento en el CURP es inválidaVerifica los componentes de fecha (posiciones 5-10)
INVALID_STATE_CODE400El código de estado no coincide con estados mexicanos válidosVerifica el código de estado (posiciones 12-13)
MISSING_REQUIRED_FIELD400Falta el campo requerido curpIncluye el campo curp en el cuerpo de la petición
AUTHENTICATION_FAILED401Credenciales API inválidas o faltantesVerifica el encabezado Authorization
RATE_LIMIT_EXCEEDED429Demasiadas peticionesImplementa limitación de tasa en tu aplicación
INTERNAL_ERROR500Error de procesamiento del servidorReintenta la petición o contacta soporte

Casos de Uso

1. Validación de Registro de Usuario

Valida el CURP durante el registro de usuario para asegurar calidad de datos y extraer información personal:

const validarCURPUsuario = async (curp) => {
  const response = await fetch('https://api.jaak.ai/api/v1/government/mx/curp/validate', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer TU_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ 
      curp: curp.trim().toUpperCase(), 
      require_pdf: false 
    })
  });
  
  const data = await response.json();
  
  if (data.curp.valid && data.curp.details.renapo_valid) {
    console.log('✓ CURP válido confirmado con RENAPO');
    
    // Extraer información personal verificada
    return {
      curp: data.curp.value,
      nombreCompleto: `${data.personal_info.full_name} ${data.personal_info.paternal_surname} ${data.personal_info.maternal_surname}`,
      fechaNacimiento: data.personal_info.birth_date,
      genero: data.personal_info.renapo_gender,
      estadoNacimiento: data.personal_info.birth_entity_name,
      nacionalidad: data.personal_info.nationality,
      estado: data.personal_info.status_curp,
      verificado: true
    };
  } else {
    console.log('✗ CURP inválido o no encontrado en RENAPO');
    return null;
  }
};

// Uso
const infoUsuario = await validarCURPUsuario('GAMC850815HDFRRL09');
if (infoUsuario) {
  console.log('Usuario registrado:', infoUsuario.nombreCompleto);
}

2. Verificación KYC con Descarga de Certificado

Extrae información verificada y descarga el certificado oficial del CURP para cumplimiento normativo:

import requests
from datetime import datetime

def verificar_curp_para_kyc(curp, descargar_certificado=False):
    """
    Verificar CURP para cumplimiento KYC y opcionalmente descargar certificado
    """
    url = "https://api.jaak.ai/api/v1/government/mx/curp/validate"
    headers = {
        "Authorization": "Bearer TU_API_KEY",
        "Content-Type": "application/json"
    }
    payload = {
        "curp": curp.strip().upper(),
        "require_pdf": descargar_certificado
    }
    
    response = requests.post(url, json=payload, headers=headers)
    data = response.json()
    
    if not data["curp"]["valid"] or not data["curp"]["details"]["renapo_valid"]:
        return {"validacion_aprobada": False, "error": "CURP no válido o no encontrado en RENAPO"}
    
    # Verificar estado del CURP
    if data["personal_info"]["status_curp_code"] != "AN":
        return {
            "validacion_aprobada": False, 
            "error": f"Estado del CURP es {data['personal_info']['status_curp']} (no activo)"
        }
    
    datos_kyc = {
        "validacion_aprobada": True,
        "curp": data["curp"]["value"],
        "info_personal": {
            "nombre_completo": f"{data['personal_info']['full_name']} "
                              f"{data['personal_info']['paternal_surname']} "
                              f"{data['personal_info']['maternal_surname']}",
            "fecha_nacimiento": data["personal_info"]["birth_date"],
            "genero": data["personal_info"]["renapo_gender"],
            "lugar_nacimiento": {
                "estado": data["personal_info"]["birth_entity_name"],
                "codigo_estado": data["personal_info"]["birth_entity_code"]
            },
            "nacionalidad": data["personal_info"]["nationality"]
        },
        "info_registro": {
            "numero_acta": data["personal_info"]["document_data"]["certificate_number"],
            "anio_registro": data["personal_info"]["document_data"]["registration_year"],
            "municipio_registro": data["personal_info"]["document_data"]["registry_municipality"]
        },
        "verificacion": {
            "validado_renapo": data["curp"]["details"]["renapo_valid"],
            "estado": data["personal_info"]["status_curp"],
            "timestamp": data["timestamp"],
            "event_id": data["event_id"]
        }
    }
    
    # Agregar URL del PDF si fue solicitado
    if descargar_certificado and data["curp"]["details"]["pdf_present"]:
        datos_kyc["url_certificado"] = data["curp"]["details"]["pdf_url"]
        datos_kyc["certificado_expira"] = "15 minutos"
    
    return datos_kyc

# Uso
resultado = verificar_curp_para_kyc('GAMC850815HDFRRL09', descargar_certificado=True)
if resultado["validacion_aprobada"]:
    print(f"✓ KYC Aprobado: {resultado['info_personal']['nombre_completo']}")
    print(f"  Fecha de Nacimiento: {resultado['info_personal']['fecha_nacimiento']}")
    print(f"  Certificado: {resultado.get('url_certificado', 'No solicitado')}")
else:
    print(f"✗ KYC Rechazado: {resultado['error']}")

3. Validación por Lote con Resultados Detallados

Valida múltiples CURPs y obtén reportes de validación completos:

const validarCURPsPorLote = async (listaCurps) => {
  const resultados = await Promise.all(
    listaCurps.map(async curp => {
      try {
        const response = await fetch('https://api.jaak.ai/api/v1/government/mx/curp/validate', {
          method: 'POST',
          headers: {
            'Authorization': 'Bearer TU_API_KEY',
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({ curp, require_pdf: false })
        });
        
        const data = await response.json();
        
        return {
          curp: curp,
          valido: data.curp?.valid || false,
          validado_renapo: data.curp?.details?.renapo_valid || false,
          estado: data.personal_info?.status_curp || 'DESCONOCIDO',
          verificaciones: {
            formato: data.validation_details?.format_valid,
            estructura: data.validation_details?.structure_valid,
            digito_verificador: data.validation_details?.check_digit_valid,
            reglas_negocio: data.validation_details?.business_rules_valid
          },
          datos_personales: data.curp?.valid ? {
            nombre: data.personal_info?.full_name,
            fecha_nacimiento: data.personal_info?.birth_date,
            estado: data.personal_info?.birth_entity_name
          } : null,
          tiempo_proceso_ms: data.process_time_ms
        };
      } catch (error) {
        return {
          curp: curp,
          valido: false,
          error: error.message
        };
      }
    })
  );
  
  // Generar resumen
  const resumen = {
    total: resultados.length,
    validos: resultados.filter(r => r.valido && r.validado_renapo).length,
    invalidos: resultados.filter(r => !r.valido).length,
    no_en_renapo: resultados.filter(r => r.valido && !r.validado_renapo).length,
    tiempo_promedio_ms: resultados.reduce((acc, r) => acc + (r.tiempo_proceso_ms || 0), 0) / resultados.length
  };
  
  return { resultados, resumen };
};

// Uso
const curps = [
  'GAMC850815HDFRRL09',
  'ROML901225HDFMZS08',
  'CURP_INVALIDO_123'
];

const { resultados, resumen } = await validarCURPsPorLote(curps);
console.log(`Validados ${resumen.total} CURPs: ${resumen.validos} válidos, ${resumen.invalidos} inválidos`);
console.log(`Tiempo promedio de procesamiento: ${resumen.tiempo_promedio_ms.toFixed(0)}ms`);

resultados.forEach(resultado => {
  console.log(`${resultado.curp}: ${resultado.valido ? '✓ Válido' : '✗ Inválido'} 
    ${resultado.validado_renapo ? '(Confirmado RENAPO)' : ''}`);
});

4. Descargar Certificado Oficial del CURP

Solicita y descarga el certificado PDF oficial del CURP desde RENAPO:

import requests

def descargar_certificado_curp(curp, ruta_guardado="certificado_curp.pdf"):
    """
    Validar CURP y descargar certificado oficial
    """
    url = "https://api.jaak.ai/api/v1/government/mx/curp/validate"
    headers = {
        "Authorization": "Bearer TU_API_KEY",
        "Content-Type": "application/json"
    }
    payload = {
        "curp": curp.strip().upper(),
        "require_pdf": True  # Solicitar certificado PDF
    }
    
    # Paso 1: Validar y obtener URL del PDF
    response = requests.post(url, json=payload, headers=headers)
    data = response.json()
    
    if not data["curp"]["valid"]:
        return {"exito": False, "error": "CURP inválido"}
    
    if not data["curp"]["details"]["pdf_present"]:
        return {"exito": False, "error": "PDF no disponible para este CURP"}
    
    url_pdf = data["curp"]["details"]["pdf_url"]
    
    # Paso 2: Descargar PDF desde URL firmada (expira en 15 minutos)
    respuesta_pdf = requests.get(url_pdf)
    
    if respuesta_pdf.status_code == 200:
        with open(ruta_guardado, 'wb') as f:
            f.write(respuesta_pdf.content)
        
        return {
            "exito": True,
            "curp": data["curp"]["value"],
            "ruta_archivo": ruta_guardado,
            "expira_en": data["metadata"]["pdf_expires_in"],
            "nombre_titular": f"{data['personal_info']['full_name']} "
                             f"{data['personal_info']['paternal_surname']} "
                             f"{data['personal_info']['maternal_surname']}"
        }
    else:
        return {"exito": False, "error": f"Falló la descarga del PDF: {respuesta_pdf.status_code}"}

# Uso
resultado = descargar_certificado_curp('GAMC850815HDFRRL09')
if resultado["exito"]:
    print(f"✓ Certificado descargado para {resultado['nombre_titular']}")
    print(f"  Guardado en: {resultado['ruta_archivo']}")
    print(f"  La URL expira en: {resultado['expira_en']}")
else:
    print(f"✗ Error: {resultado['error']}")

Mejores Prácticas

1. Sanitización de Entrada

Siempre limpia la entrada del CURP antes de enviarlo:

  • Eliminar espacios en blanco: curp.trim()
  • Convertir a mayúsculas: curp.toUpperCase()
  • Eliminar caracteres especiales

2. Manejo de Errores

Implementa manejo robusto de errores para fallos de la API:

try {
  const respuesta = await validarCURP(curp);
  if (!respuesta.curp.valid) {
    // Manejar CURP inválido
    const verificacionesFallidas = Object.entries(respuesta.validation_details)
      .filter(([clave, valor]) => !valor)
      .map(([clave]) => clave);
    console.log('Verificaciones fallidas:', verificacionesFallidas);
  }
} catch (error) {
  console.error('Error de API:', error);
  // Implementar lógica de respaldo o reintento
}

3. Rastreo de Request ID

Usa Request-IDs únicos para depuración:

const requestId = `curp_validation_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

4. Caché de Respuestas

Considera guardar en caché CURPs válidos para reducir llamadas a la API:

const cache = new Map();

const validarConCache = async (curp) => {
  if (cache.has(curp)) {
    return cache.get(curp);
  }
  
  const resultado = await validarCURP(curp);
  if (resultado.curp.valid) {
    cache.set(curp, resultado);
  }
  
  return resultado;
};


Soporte

Para soporte técnico o preguntas sobre este endpoint: