[MX] CURP validation

Validate a person in Mexico from their CURP (Clave Única de Registro de Población). With one request, Brinta returns their social security number (NSS) and RFC, or their RFC with the legal name and postal code registered for it. Use it to onboard individuals, such as workers, drivers, sellers or freelancers, when you only have their CURP.

📚

New to tax ID validations? Start with the generic guide.


Choose the validation_type

validation_typeYou get back
NSSThe person's NSS and RFC, plus name, phone, email and address when available
RFC_FULLThe person's RFC, with the legal name and postal code registered for it

Both use the same request. Only validation_type changes.


Request

curl -X POST https://api.brinta.com/tax-id-validations/ \
  -H "Authorization: Bearer $BRINTA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "locations": ["MX"],
    "validation_type": "NSS",
    "company": {
      "type": "person",
      "legal_name": "JUAN PEREZ LOPEZ",
      "phone": "525500000000",
      "address": { "postal_code": "06600" },
      "tax_registration": {
        "number": "AAAA800101HDFXXX09",
        "type": "CURP",
        "level": "country",
        "location": "MX"
      },
      "privacy_agreement": {
        "url": "https://example.com/legal/privacy-policy",
        "ip": "203.0.113.10"
      }
    }
  }'

Required fields

FieldNSSRFC_FULLNotes
company.tax_registration✅✅number is the 18-character CURP, type: "CURP", level: "country", location: "MX".
company.phone✅✅The person's mobile, with country code and digits only: 525512345678. A leading + is accepted. No spaces or symbols.
company.privacy_agreement.url✅✅URL of the privacy notice the person accepted.
company.privacy_agreement.ip✅✅IP address from which they accepted it.
company.legal_name✅The person's full name.
company.address.postal_code✅The person's postal code.
company.typeperson.

To use the same payload for both types, send all of the fields.

⚠️

Consent is mandatory. These checks query personal records. Only send privacy_agreement when the person really accepted your privacy notice at that URL. Keep evidence of that acceptance on your side.

⚠️

Send the person inline. The CURP validation needs company with the person's data and consent. It doesn't work with company_id or company_external_id, so nothing is stored on a company. To keep the result, save the returned registrations with POST /companies or PUT /companies/{id}.


Result

The POST answers right away with the validation id:

{ "id": "tiv2-5b0c9a7e-3f1d-4e8a-9c2b-7d6e5f4a3b21", "status": "in_process" }

The NSS lookup can take from a few seconds to a few minutes. When it succeeds, Brinta notifies your validation webhook. Read the result with GET /tax-id-validations/{id}. Also poll that endpoint every few seconds until status is succeeded or failed, because failures must be read with GET.

NSS

{
  "id": "tiv2-5b0c9a7e-3f1d-4e8a-9c2b-7d6e5f4a3b21",
  "status": "succeeded",
  "data": [
    {
      "locationIsoCode": "MX",
      "status": "succeeded",
      "company": {
        "name": "Juan Perez Lopez",
        "legal_name": "Juan Perez Lopez",
        "phone": "525500000000",
        "tax_registrations": [
          { "number": "AAAA800101HDFXXX09", "type": "CURP", "level": "country", "location": "MX" },
          { "number": "00000000000", "type": "NSS", "level": "country", "location": "MX" },
          { "number": "AAAA800101XXX", "type": "RFC", "level": "country", "location": "MX" }
        ],
        "address": { "postal_code": "06600", "address_line_1": "Calle Falsa 123", "neighborhood": "Juárez" }
      },
      "registry_lists": []
    }
  ]
}

RFC_FULL

{
  "id": "tiv2-0e1d2c3b-4a59-4687-b6c5-d4e3f2a1b0c9",
  "status": "succeeded",
  "data": [
    {
      "locationIsoCode": "MX",
      "status": "succeeded",
      "company": {
        "legal_name": "JUAN PEREZ LOPEZ",
        "tax_registrations": [
          { "number": "AAAA800101XXX", "type": "RFC", "level": "country", "location": "MX" }
        ],
        "address": { "postal_code": "06600" }
      },
      "registry_lists": []
    }
  ]
}
  • tax_registrations holds what was found. The NSS is 11 digits. An RFC for an individual is 13 characters.
  • name, legal_name and address come from the official record. They can differ from what you sent; use the returned values.
  • Fields the source didn't return are left out.

When it fails

{
  "id": "tiv2-5b0c9a7e-3f1d-4e8a-9c2b-7d6e5f4a3b21",
  "status": "failed",
  "data": [
    { "locationIsoCode": "MX", "status": "failed", "errors": ["curp: Formato de CURP inválido"], "registry_lists": [] }
  ]
}
CauseWhat to do
The CURP is malformed or doesn't existCheck the 18 characters with the person. They can download their CURP from gob.mx.
No records found for the personThe person may have no NSS (they never worked under IMSS) or no RFC.
400 before the validation startsA required field is missing, or the phone format is wrong. The message lists each field.

Common mistakes

MistakeFix
"phone": "5512345678" (no country code)Send 525512345678.
Using company_id for a CURP validationSend the person inline in company.
"type": "NSS" in tax_registrationThe NSS is a result, not an input. Send the CURP ("type": "CURP").
Missing legal_name or postal_code for RFC_FULLBoth are required.
Sending privacy_agreement without real consentOnly send it when the person accepted your privacy notice.

Did this page help you?