Normadata · Data Quality API

Normadata API vs. expresiones regulares (regex)

¿Cuándo una regex basta para validar un tax ID, y cuándo necesitás una API?

TL;DR

La respuesta honesta: a veces la regex basta. Si solo necesitás validar un DNI argentino de 8 dígitos en un proyecto personal, una regex de tres líneas es perfectamente razonable. Pero hay escenarios donde la regex te va a fallar de formas silenciosas y costosas. Esta comparativa te explica la diferencia con ejemplos reales.

Comparación rápida

AspectoRegex (casera)Normadata API
CostoGratisGratis en beta; pricing post-beta no anunciado
¿Verifica dígito verificador?No (regex no puede calcular módulo 11)Sí — algoritmo completo por país
¿Multi-país?Necesitás una regex por país (y maintenerla)Sí — un endpoint, cobertura multi-país
¿Normaliza el formato?NoSí — retorna forma canónica
¿Detecta prefijos inválidos (ej. CUIT)?Solo si la regex lo contempla explícitamenteSí — reglas de prefijo incluidas
¿Mantenimiento cuando cambia el estándar?TuyoDe Normadata
¿Funciona en cualquier lenguaje?Sí (con variaciones de sintaxis)Sí — HTTP, cualquier stack
¿Latencia?~0 ms (local)<50 ms (API call)

¿Cuándo usar cada uno?

Cuándo la regex es suficiente
  • Un solo país, un solo tipo de identificador, y el check digit no es crítico para tu caso de uso.
  • Prototipo o MVP donde la prioridad es velocidad de desarrollo, no robustez.
  • El identificador no tiene dígito verificador (ej. DNI argentino de 8 dígitos).
  • Ya tenés la librería instalada y funciona correctamente en tu test suite.
  • Cero presupuesto para dependencias externas y el equipo puede mantener las regex.
Cuándo la API gana
  • Multi-país: tenés usuarios o clientes en Argentina, Brasil, México, Colombia — cada uno con sus propias reglas.
  • El identificador tiene dígito verificador complejo (CUIT, CPF, CNPJ, RFC, RUT): la regex detecta formato pero no valida el checksum.
  • Necesitás normalización: que '20-12345678-9' y '20123456789' se traten como el mismo CUIT.
  • Stack multi-lenguaje (Python, Go, JS, Java): una sola API, en lugar de regex por lenguaje.
  • El equipo no quiere mantener 10-20 regex con sus edge cases, encodings y actualizaciones.
  • Vas a hacer match o dedupe sobre los identificadores y necesitás la forma canónica como base — algo que una regex no te da, pero el match/dedupe lo corrés vos.

El problema real: la regex que parece funcionar pero no valida

Tomá este ejemplo de CUIT. La regex más común que encontrás en Stack Overflow: `^(20|23|24|27|30|33|34)\d{8}\d$`. Parece correcta — valida el prefijo y los 11 dígitos. Pero el CUIT 20-12345678-5 (donde el dígito verificador correcto es 9, no 5) pasa esta regex sin problema. El número es structuralmente inválido según el algoritmo de AFIP, pero la regex no lo sabe. Esto significa que podés almacenar miles de CUITs inválidos en tu base de datos, todos con formato que parece correcto. Peor aún: si después necesitás hacer matching o deduplicación contra datos del cliente, los CUITs mal validados van a generar falsos negativos.

Código comparativo: Python, ambos lados

El siguiente ejemplo muestra cómo el mismo CUIT inválido (20123456785) pasa el regex pero falla la API. La diferencia está en el dígito verificador: el correcto para esa base es 9, no 5.

Ejemplos de código

Regex: pasa un CUIT inválido
import re

CPF_REGEX = re.compile(r'^\d{11}$')

def validate_with_regex(cpf: str) -> bool:
    digits = cpf.replace('.', '').replace('-', '').replace(' ', '')
    return bool(CPF_REGEX.match(digits))

print(validate_with_regex("111.444.777-35"))  # True  (valid)
print(validate_with_regex("111.444.777-00"))  # True  (WRONG — invalid check digit, should fail)
print(validate_with_regex("000.000.000-00"))  # True  (WRONG — known invalid CPF pattern)
Normadata API: detecta el dígito verificador incorrecto
import httpx

def validate_cpfs(cpfs: list[str]) -> list[dict]:
    response = httpx.post(
        "https://api.normadata.io/v1/validate/tax-ids",
        headers={"X-API-Key": "nd_your_key"},
        json={"items": [
            {"id": str(i), "value": v, "country": "BR"}
            for i, v in enumerate(cpfs)
        ]},
    )
    return response.json()["results"]

# Same endpoint for 1 or N — up to 1000 per request
results = validate_cpfs(["111.444.777-35", "111.444.777-00"])

print(results[0]["valid"])  # True
print(results[1]["valid"])  # False — wrong check digit
print(results[1]["error"])  # "invalid check digit"
Limitaciones

Normadata es una API hosted — requiere llamada de red, tiene latencia (aunque baja), y en post-beta tendrá un costo. Si tu caso de uso es de un solo país, sin dígito verificador complejo, y podés mantener el código, una regex puede ser la herramienta correcta. Normadata no es la respuesta a todo: es la respuesta a multi-país, check digits complejos y normalización.

Preguntas frecuentes

¿Puedo usar regex para el CPF de Brasil?

Podés validar el formato (11 dígitos, opcionalmente con puntos y guión), pero no podés validar los dos dígitos verificadores con una regex. El algoritmo del CPF usa módulo 11 con dos rondas de cálculo. Hay CPFs que tienen formato correcto pero dígito verificador incorrecto — una regex los aceptaría.

¿Cuánto cuesta Normadata después de la beta?

El pricing post-beta no está anunciado. Durante la beta privada, el acceso es gratuito. Si querés acceso anticipado y pricing preferencial, podés anotarte en la lista de espera.

¿La API funciona con cualquier lenguaje?

Sí. Es HTTP puro con JSON. Funciona con cualquier lenguaje que pueda hacer un POST request: Python, JavaScript, Go, Ruby, Java, PHP, Rust, etc. No hay SDKs propietarios requeridos.

¿Qué pasa con los edge cases de regex multi-país?

Son muchos y no intuitivos. El RFC mexicano tiene 12 caracteres para personas morales y 13 para personas físicas, con reglas de derivación de nombre y fecha. El RUT chileno tiene un dígito verificador que puede ser la letra K. El CNPJ brasileño tiene 14 dígitos con dos dígitos verificadores de pesos distintos. Cada uno requiere su propia lógica. Mantener las regex correctas y actualizadas por país es un compromiso de tiempo que una API resuelve.