Saltar al contenido
Constaia

Validar el DNI en un formulario de inscripción en 5 minutos

Cómo comprobar en una inscripción que el DNI, NIE o pasaporte está vigente, es de quien se inscribe y cumple la edad mínima, sin guardar la imagen. Con el widget y unas líneas de backend.

Por Equipo Constaia6 min de lectura

También en: English

En un formulario de inscripción (una carrera, una licencia, un campus de verano) el documento de identidad suele ser un campo de "sube una foto" que nadie mira hasta que hay un problema: el DNI estaba caducado, era del hermano o el participante no tenía la edad de la categoría.

Este artículo explica qué conviene comprobar, qué se puede comprobar de forma determinista y cómo montarlo con Constaia en unos minutos: un campo de subida en tu página y una llamada desde tu servidor. Sin guardar la imagen.

Qué comprobar de un documento de identidad en una inscripción

No se trata de hacer un KYC bancario. En una inscripción, las preguntas útiles son cuatro:

  1. ¿Es un documento de identidad aceptado? DNI, NIE/TIE o pasaporte, y no un carné de conducir, una tarjeta sanitaria o la foto de otra cosa.
  2. ¿Está vigente? En la fecha de hoy o, mejor, en la fecha de la prueba.
  3. ¿Es de quien se inscribe? El nombre, el número y la fecha de nacimiento coinciden con lo que la persona ha escrito en el formulario.
  4. ¿Cumple la edad? Mayor de edad para una prueba absoluta, o dentro del rango de una categoría.

Lo que se puede comprobar sin IA

Una parte del trabajo no necesita ningún modelo, solo aritmética:

  • La letra del DNI y del NIE. El Ministerio del Interior publica el algoritmo: el número módulo 23 da la posición de la letra en una tabla fija; en el NIE, la X, Y o Z inicial se sustituye por 0, 1 o 2 (Ministerio del Interior). Lo explicamos con código en Letra del DNI y del NIE.
  • La zona de lectura mecánica (MRZ). El reverso del DNI lleva una MRZ de formato TD1 con dígitos de control para el número de documento, la fecha de nacimiento y la caducidad, según el Doc 9303 de la OACI. Si los dígitos no cuadran, o la MRZ dice una cosa y lo impreso otra, algo va mal. Más en MRZ ICAO 9303.
  • Fechas. Caducidad frente a la fecha de referencia y edad calculada desde la fecha de nacimiento.

Lo que sí necesita un modelo es leer una foto de móvil torcida, con reflejos y en cualquier orientación, y clasificar qué documento es. Por eso Constaia combina las dos cosas: la IA lee y clasifica, el código valida.

Coherente no es auténtico

Que la letra y la MRZ cuadren prueba que los datos son coherentes, no que el documento sea auténtico. Constaia no hace reconocimiento facial ni garantiza autenticidad; devuelve indicios (por ejemplo, posible foto de pantalla) para que una persona mire.

El flujo en tres piezas

  1. Tu página muestra un campo de subida. El widget <constaia-upload> abre la cámara en el móvil, avisa si la foto sale borrosa y une las dos caras del DNI en una imagen.
  2. Tu servidor recibe el fichero, añade los datos que ya tiene de la inscripción (nombre, número, fecha de nacimiento) y llama a Constaia con tu clave. La clave nunca va al navegador.
  3. Tu servidor decide según el veredicto: confirmar, rechazar con el motivo o dejar pendiente de revisión.

Minuto 1: el campo en la página

inscripcion.html
<script type="module" src="https://cdn.jsdelivr.net/npm/@constaia/widget@0.1"></script>

<constaia-upload
  endpoint="/api/inscripciones/1234/documento"
  expect="es_dni,es_nie,passport"
  lang="es"
></constaia-upload>

El atributo expect solo orienta la interfaz. Quien decide qué se acepta es tu servidor.

Minutos 2 a 4: la llamada desde tu servidor

import { Constaia } from "@constaia/sdk";

const constaia = new Constaia(); // lee CONSTAIA_API_KEY

export async function comprobarDocumento(fichero: Buffer, nombreFichero: string, inscripcion: Inscripcion) {
  const analysis = await constaia.analyze(
    { file: fichero, filename: nombreFichero },
    {
      expect: ["es_dni", "es_nie", "passport"],
      checks: {
        notExpired: true,
        minAgeYears: 18,
        referenceDate: inscripcion.fechaPrueba, // "2027-03-14": vigencia y edad en el día de la prueba
        holder: {
          fullName: inscripcion.nombreCompleto,
          documentNumber: inscripcion.numeroDocumento,
          birthDate: inscripcion.fechaNacimiento, // "YYYY-MM-DD"
        },
      },
      storage: "none",
      language: "es",
      metadata: { registration_id: String(inscripcion.id) },
    },
  );
  return analysis;
}

holder compara con lo que escribió la persona sin tener en cuenta tildes, admite otro orden de apellidos y pequeñas erratas. storage: "none" hace que el fichero se procese en memoria y no se guarde.

Minuto 5: decidir

La respuesta trae verdict.status y la lista de motivos, ya en el idioma que pediste:

VeredictoQué significaQué hacer
validDocumento aceptado, vigente, del titular y con la edadConfirmar la inscripción
invalidAlgún motivo con severidad de error: caducado, otro titular, otro tipo de documento, menor que la edad mínima, letra o MRZ que no cuadranNo confirmar; mostrar el motivo y dejar subir otro
reviewAlgo impide decidir con seguridad: foto borrosa, un dato ilegibleAceptar provisionalmente y que lo mire una persona

Un mensaje típico en invalid es "Caducado el 15/06/2020." o "El titular tiene 16 años; el mínimo es 18.". Enseñárselo a la persona en el momento ahorra un correo de ida y vuelta.

No rechaces automáticamente los review: la mayoría son fotos mejorables de documentos correctos.

Menores y categorías

En una inscripción de menores cambia el planteamiento:

  • Si el documento es del tutor, valida su DNI o NIE con sus datos y min_age_years: 18.
  • Si es del menor, valida su documento y, si la categoría tiene un máximo, usa max_age_years. Con reference_date calculas la edad en la fecha que diga el reglamento (por ejemplo, el 31 de diciembre de la temporada).

Qué guardar (y qué no)

El artículo 5.1.c del RGPD pide que los datos sean los necesarios para la finalidad, y la AEPD ha declarado que exigir y conservar la copia del DNI cuando la identidad puede comprobarse sin ella infringe ese principio (PS-00138-2025). Lo contamos con detalle en Copias del DNI y la AEPD.

En la práctica, para justificar la comprobación suele bastar con guardar:

  • el id del análisis,
  • el veredicto y la fecha,
  • el número de documento comprobado, si lo necesitas para la licencia.

Si tampoco quieres que Constaia conserve los datos extraídos, añade keep_results: false: recibes la respuesta una vez y después no se puede consultar.

No es asesoramiento jurídico

Si pides el documento, sigues tratando datos personales aunque no guardes la imagen: necesitas una base jurídica, informar a las personas y un contrato de encargado con tu proveedor. Consulta tu caso con tu delegado de protección de datos.

Probarlo sin gastar créditos

Con una clave de prueba ck_test_… el resultado depende del nombre del fichero: dni_valid.jpg devuelve un DNI válido de datos ficticios, dni_expired.jpg uno caducado y blurry.jpg un caso de revisión. Así puedes programar todo el flujo antes de usar documentos reales. La guía completa, con Express y Laravel, está en DNI en un formulario de inscripción.

En resumen

  • En una inscripción importan cuatro cosas: tipo de documento, vigencia, titular y edad.
  • La letra del NIF, la MRZ y las fechas se comprueban con código; la IA se usa para leer y clasificar.
  • Con un campo de subida y una llamada desde tu servidor tienes veredicto y motivo en el momento.
  • Guarda el resultado de la comprobación, no la foto del documento.

Si quieres probarlo con tu formulario, crea una cuenta gratis: incluye 150 documentos al mes y claves de prueba que no consumen créditos.

Fuentes

  1. 01Ministerio del Interior — Cálculo del dígito de control del NIF/NIE
  2. 02OACI — Doc 9303, parte 5: documentos de viaje de lectura mecánica de tamaño TD1
  3. 03Reglamento (UE) 2016/679 (RGPD), EUR-Lex
  4. 04AEPD — Resolución PS-00138-2025 (Diputación de Pontevedra)