Certificado médico deportivo
Comprueba que un certificado médico deportivo declara apto, está firmado y sellado, es del deportista y no supera la antigüedad máxima que fijes.
Muchas federaciones, clubes y organizadores piden un certificado médico que declare a la persona apta para la práctica deportiva. Revisarlos a mano es lento: hay que mirar la fecha, la firma, el sello, el nombre y que diga "apto".
Con el tipo medical_certificate_sport Constaia extrae esos datos y aplica las reglas que le pidas.
Las opciones
{
"expect": "medical_certificate_sport",
"checks": {
"max_age_days": 365,
"require_signature": true,
"require_stamp": true,
"holder": { "full_name": "María García López", "document_number": "12345678Z" }
},
"storage": "none",
"metadata": { "athlete_id": "5521", "season": "2026-27" }
}| Check | Qué comprueba | Si falla |
|---|---|---|
max_age_days | Que la fecha de emisión no tiene más de N días. | max_age_days con severity: "error". Si no se encuentra la fecha, warning (→ review). |
require_signature | Que se aprecia una firma (signature_present). | require_signature con error. |
require_stamp | Que se aprecia un sello (stamp_present). | require_stamp con error. |
holder | Que el paciente es el deportista (nombre y documento). | holder con error, o warning si no se puede leer el dato. |
Además, sin que lo pidas, si el certificado no declara apto (fit_for_sport: false) el veredicto es invalid con
el motivo not_fit_for_sport: "El certificado no declara apto para la práctica deportiva.".
Si necesitas que aparezca un dato concreto, como el número de colegiado, añade
"require_fields": ["doctor_license_number"]: si falta, llega el motivo required_field_missing con error.
La antigüedad y la temporada
max_age_days cuenta los días entre la fecha de emisión y la fecha de referencia, que por defecto es hoy. Tu organización
decide la ventana: 365 días es habitual, pero hay reglamentos que piden el certificado de la temporada en curso.
Si quieres que el certificado siga dentro de plazo al final de la temporada, pasa la fecha de fin en
reference_date:
{ "max_age_days": 365, "reference_date": "2027-08-31" }Un certificado emitido más de un día después de reference_date también falla el check, así que no uses la fecha de
inicio de temporada como referencia si aceptas certificados emitidos durante ella.
El código
import { Constaia, ConstaiaError } from "@constaia/sdk";
import { fromPath } from "@constaia/sdk/node";
const constaia = new Constaia(); // lee CONSTAIA_API_KEY
export async function checkMedicalCertificate(path, athlete) {
const analysis = await constaia.analyze(await fromPath(path), {
expect: "medical_certificate_sport",
checks: {
maxAgeDays: 365,
requireSignature: true,
requireStamp: true,
holder: { fullName: athlete.fullName, documentNumber: athlete.documentNumber },
},
storage: "none",
metadata: { athlete_id: String(athlete.id), season: "2026-27" },
});
const { fields, verdict } = analysis;
return {
analysisId: analysis.id,
status: verdict?.status ?? "review",
problems: (verdict?.reasons ?? []).filter((r) => r.severity !== "info").map((r) => r.message),
issueDate: fields.issue_date?.value ?? null,
restrictions: fields.restrictions?.value ?? null,
doctorLicenseNumber: fields.doctor_license_number?.value ?? null,
};
}
try {
const result = await checkMedicalCertificate("./medical_certificate.pdf", {
id: 5521,
fullName: "María García López",
documentNumber: "12345678Z",
});
console.log(result);
} catch (err) {
if (err instanceof ConstaiaError) console.error(err.code, err.message, err.requestId);
else throw err;
}Qué devuelve
Con el fichero de test medical_certificate.pdf y las opciones del ejemplo de curl, el veredicto es:
{
"expected": ["medical_certificate_sport"],
"match": true,
"status": "valid",
"reasons": [
{ "code": "type_match", "severity": "info", "message": "El documento es Certificado médico deportivo." },
{ "code": "max_age_days", "severity": "info", "message": "Emitido hace 28 días (máximo 365)." },
{ "code": "require_signature", "severity": "info", "message": "El documento está firmado." },
{ "code": "require_stamp", "severity": "info", "message": "El documento tiene sello." }
]
}Los días de "Emitido hace…" dependen de la fecha en que lo ejecutes. Los campos extraídos (cada uno es un objeto con
value, confidence, validated y source):
| Campo | Valor de ejemplo |
|---|---|
patient_name | MARÍA GARCÍA LÓPEZ |
patient_id | 12345678Z (con la validación nif_check_digit) |
issue_date | 2026-09-01 |
doctor_name | LAURA MARTÍN RUIZ |
doctor_license_number | 282845678 |
fit_for_sport | true |
sport | Tiro con arco |
restrictions | Sin restricciones |
signature_present, stamp_present | true |
restrictions es texto libre: si el certificado declara apto con limitaciones (por ejemplo, "no apto para competición
de alto nivel"), decide en tu código qué hacer. Constaia no interpreta las restricciones más allá de fit_for_sport.
Lo que Constaia no comprueba
Constaia lee el número de colegiado, pero no consulta al colegio de médicos si ese número existe ni si el médico está colegiado. Tampoco verifica la firma electrónica del PDF. Si tu reglamento lo exige, haz esa comprobación aparte.
Decidir
| Veredicto | Acción |
|---|---|
| Válido | Marca el certificado como aceptado y guarda la fecha de emisión para avisar antes de que caduque. |
| No válido | Muestra los motivos (no apto, antiguo, sin firma o sello, otro titular) y pide otro certificado. |
| Revisar | Una persona lo revisa: falta la fecha, la foto es mala o la confianza es baja. Ver Revisión humana. |
Guarda en tu sistema el id del análisis, el veredicto, issue_date y, si lo necesitas, doctor_license_number. Con la
fecha de emisión y tu ventana puedes calcular cuándo pedir el siguiente certificado.
Probarlo
Con una clave ck_test_…, un PDF llamado medical_certificate.pdf (también sirve cualquier nombre que contenga
medical o medico) devuelve el certificado apto, firmado y sellado, emitido el 2026-09-01, de la página anterior.
Con holder { "full_name": "María García López" } añade el motivo holder informativo. Prueba con otro nombre para
ver el invalid. Más en Modo test.
Siguientes pasos
DNI en un formulario de inscripción
Valida el DNI, NIE o pasaporte en una inscripción deportiva (vigente, del titular y con edad mínima) con el widget, Express o Laravel.
Certificado de delitos sexuales (LOPIVI)
Valida el certificado negativo de delitos sexuales de entrenadores y voluntarios (reciente, del titular, sin antecedentes) sin guardarlo.