CURP (RENAPO)

The CURP (Clave Única de Registro de Población) is Mexico's 18-character unique population identity key, issued and maintained by RENAPO (Registro Nacional de Población). Every Mexican citizen and foreign resident holds one.

Send a CURP and we return the registered name, gender, nationality, and date of birth — synchronously, no credentials of your own required.

Validate a CURP

POST /v1/curp

{ "curp": "XEXX010101HNEXXXA4" }

Pass include_pdf: true to also receive the official constancia PDF:

{ "curp": "XEXX010101HNEXXXA4", "include_pdf": true }

The curp field must be exactly 18 characters and match the standard CURP format (AAAA######AAAAAA##). Laravel returns a 422 with field-level validation errors if the format is invalid — no call to RENAPO is made.

Response (200 OK):

{
  "curp":             "XEXX010101HNEXXXA4",
  "valid":            true,
  "name":             "JUAN",
  "last_name":        "EJEMPLO",
  "second_last_name": "DEMO",
  "gender":           "male",
  "date_of_birth":    "2001-01-01",
  "nationality":      "MEX",
  "status":           "active"
}

With include_pdf: true:

{
  "curp":             "XEXX010101HNEXXXA4",
  "valid":            true,
  "name":             "JUAN",
  "last_name":        "EJEMPLO",
  "second_last_name": "DEMO",
  "gender":           "male",
  "date_of_birth":    "2001-01-01",
  "nationality":      "MEX",
  "status":           "active",
  "pdf": {
    "available": true,
    "data":      "JVBERi0xLjQ...",
    "mime_type": "application/pdf",
    "filename":  "curp_XEXX010101HNEXXXA4.pdf",
    "encoding":  "base64"
  }
}

If the PDF could not be retrieved: pdf.available is false and data, mime_type, filename, encoding are null. The identity data is always returned regardless.

Field reference

Field Type Description
curp string The CURP as stored in RENAPO (uppercased)
valid bool Always true on a 200 — a CURP that fails validation returns an error, not valid: false
name string First name(s) as registered
last_name string Paternal surname
second_last_name string Maternal surname
gender "male" | "female" | "unknown" Derived from RENAPO's gender key (H/M)
date_of_birth string (YYYY-MM-DD) Date of birth from the RENAPO record
nationality string ISO nationality code (e.g. "MEX")
status "active" | "unknown" RENAPO registration status (Alta Normal → active)

Responses

Every non-2xx response carries a stable reason you can branch on directly:

Status reason What happened What to do
200 — CURP found and valid Use the identity fields
404 not_found CURP is not registered in RENAPO Verify the CURP with the person
422 — (Laravel errors) curp field failed format validation Fix the request body
429 rate_limited Too many requests to RENAPO Back off and retry
503 unavailable RENAPO is temporarily unreachable Retry — same request will succeed once RENAPO is back
503 upstream_error Unexpected error from the provider Retry later; contact support if it persists

Example (404):

{
  "message": "Bad request: CURP no encontrado en el padrón",
  "reason": "not_found"
}

CURP validation is synchronous — the result comes back in the response, so there is no CURP webhook. Webhooks are only for asynchronous SAT extractions.