Saltar a contenido

Caso de uso: firmar un documento por etiqueta

Requisito previo: el dni que va a firmar debe tener un certificado principal cargado (ver Alta de usuario y certificado).

Este modo busca un texto exacto (label) dentro del PDF, en cualquier página, y coloca ahí el bloque de firma. Es útil cuando el documento tiene una marca fija como "FIRMA_AQUI" o "____________" en la plantilla.

Request

curl -X POST http://localhost:8080/api/doc/sign-by-label \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -F "file=@contrato.pdf;type=application/pdf" \
  -F "dni=12345678" \
  -F "label=FIRMA_AQUI" \
  -F "reason=Aprobación de contrato" \
  -F "typeSigner=1" \
  -F "hasImageSignature=true" \
  -F "useTsa=false" \
  -o respuesta.json

Response (200 OK)

{
  "fileBase64Encode": "JVBERi0xLjcNCiXi48/TDQoxIDAgb2Jq...",
  "status": "SUCCESS",
  "message": "Document signed successfully"
}

Extraer el PDF firmado

jq -r '.fileBase64Encode' respuesta.json | base64 -d > contrato-firmado.pdf

Errores frecuentes

Situación Respuesta
El file no tiene Content-Type: application/pdf 400 BAD_REQUEST — "The file must be a PDF"
Falta algún campo obligatorio (dni, label, reason, typeSigner) 400 BAD_REQUEST — "All fields are required (dni, label, reason, typeSigner, hasImageSignature)"
El texto de label no existe en el PDF 500 INTERNAL_SERVER_ERROR
El dni no tiene certificado principal cargado 500 INTERNAL_SERVER_ERROR
Token inválido o sin claims parseables 400 BAD_REQUEST — "Error getting claims from token"

Este endpoint no valida que el dni del token coincida con el dni enviado en el formulario (a diferencia de sign-by-coord); ver decisiones de diseño.

Variante: firmando con sello de tiempo (TSA)

curl -X POST http://localhost:8080/api/doc/sign-by-label \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -F "file=@contrato.pdf;type=application/pdf" \
  -F "dni=12345678" \
  -F "label=FIRMA_AQUI" \
  -F "reason=Aprobación de contrato" \
  -F "typeSigner=1" \
  -F "hasImageSignature=true" \
  -F "useTsa=true" \
  -F "tsaAlias=tsa-prd"

Si se omite tsaAlias, se usa la TSA marcada como isDefault; ver Configurar y usar una TSA.

Variante: tamaño de firma personalizado y sin CQFP

Por defecto el bloque de firma mide 180x100 puntos y muestra la línea CQFP: <matrícula>. Ambos son opcionales y se pueden ajustar:

curl -X POST http://localhost:8080/api/doc/sign-by-label \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -F "file=@contrato.pdf;type=application/pdf" \
  -F "dni=12345678" \
  -F "label=FIRMA_AQUI" \
  -F "reason=Aprobación de contrato" \
  -F "typeSigner=1" \
  -F "hasImageSignature=true" \
  -F "signatureWidth=220" \
  -F "signatureHeight=120" \
  -F "printCqfp=false"

Si se omiten signatureWidth/signatureHeight, se mantienen los valores por defecto (180x100); si se omite printCqfp, se sigue pintando la línea CQFP.

Variante: ocultar cargo/empresa y formato de fecha personalizado

printJobTitle y printCompany controlan si se pinta el cargo y la empresa del firmante (ambos true por defecto); dateFormat permite cambiar el patrón de la fecha mostrada en el bloque de firma (patrón DateTimeFormatter de Java). Si se usa un dateFormat personalizado, ya no se agrega el sufijo " h" que sí se agrega con el formato por defecto (yyyy-MM-dd HH:mm:ss):

curl -X POST http://localhost:8080/api/doc/sign-by-label \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -F "file=@contrato.pdf;type=application/pdf" \
  -F "dni=12345678" \
  -F "label=FIRMA_AQUI" \
  -F "reason=Aprobación de contrato" \
  -F "typeSigner=1" \
  -F "hasImageSignature=true" \
  -F "printJobTitle=false" \
  -F "printCompany=false" \
  -F "dateFormat=dd/MM/yyyy HH:mm"

Un dateFormat con un patrón inválido (que DateTimeFormatter.ofPattern no pueda parsear) hace que la firma falle con 500 INTERNAL_SERVER_ERROR.

Variante: etiquetas de texto para cargo, empresa y fecha

Por defecto, cargo, empresa y fecha se pintan sin ninguna etiqueta delante (igual que antes de agregar estos parámetros). printLabelJobTitle, printLabelCompany y printLabelDate (los tres false por defecto) permiten anteponer "Cargo: ", "Empresa: " y "Fecha y hora: " respectivamente:

curl -X POST http://localhost:8080/api/doc/sign-by-label \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -F "file=@contrato.pdf;type=application/pdf" \
  -F "dni=12345678" \
  -F "label=FIRMA_AQUI" \
  -F "reason=Aprobación de contrato" \
  -F "typeSigner=1" \
  -F "hasImageSignature=true" \
  -F "printLabelJobTitle=true" \
  -F "printLabelCompany=true" \
  -F "printLabelDate=true"

printLabelJobTitle/printLabelCompany solo tienen efecto si la línea correspondiente ya se está pintando (printJobTitle/printCompany en true y el dato no vacío); la fecha siempre se pinta, así que printLabelDate siempre aplica.